Initial import
git-svn-id: svn://svn.code.sf.net/p/writer2latex/code/trunk@5 f0f2a975-2e09-46c8-9428-3b39399b9f3c
This commit is contained in:
parent
75e32b1e8f
commit
b0b66fcae9
252 changed files with 49000 additions and 0 deletions
460
source/COPYING.TXT
Normal file
460
source/COPYING.TXT
Normal file
|
@ -0,0 +1,460 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
460
source/distro/COPYING.TXT
Normal file
460
source/distro/COPYING.TXT
Normal file
|
@ -0,0 +1,460 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
121
source/distro/History.txt
Normal file
121
source/distro/History.txt
Normal file
|
@ -0,0 +1,121 @@
|
|||
Version history for Writer2LaTeX
|
||||
================================
|
||||
|
||||
Version 0.9.4 (February 2009)
|
||||
-Filters:
|
||||
- Changed to oxt format and separated into Writer2LaTeX and Writer2xhtml extensions
|
||||
- Added (localized) dialogs to the filters
|
||||
- LaTeX:
|
||||
- Export vector graphics to pdf for use with pdfTeX.
|
||||
- Support equations generated by OOoLaTeX.
|
||||
- XHTML:
|
||||
- Improved navigation features for splitted documents
|
||||
- Do not export hidden or filtered rows and columns. Apply print ranges.
|
||||
- Improved batch conversion
|
||||
- General:
|
||||
- Export images to a subdirectory.
|
||||
|
||||
Version 0.5 (June 2007)
|
||||
- LaTeX:
|
||||
- support fancyhdr.sty
|
||||
- support geometry.sty
|
||||
- support supertabular.sty
|
||||
- support tabulary.sty
|
||||
- support colortbl.sty
|
||||
- support l, c, r columns in tables
|
||||
- support floating figures and tables
|
||||
- some graphics improvements
|
||||
- custom tabstop handling
|
||||
- flexible handling of notes (ignore, comment, marginpar, pdf annotation)
|
||||
- string replace (eg. LaTeX -> \LaTeX)
|
||||
- XHTML:
|
||||
- convert an entire directory with index page(s)
|
||||
- convert using a template document
|
||||
- support html forms
|
||||
- custom tabstop handling
|
||||
- support continued lists
|
||||
- improved export of table formatting
|
||||
- support background images
|
||||
- improved table of contents
|
||||
- General:
|
||||
- support OpenDocument
|
||||
- now installable as uno package (extension)
|
||||
- no longer using the XMerge framework
|
||||
|
||||
Version 0.4 (July 2005)
|
||||
- LaTeX:
|
||||
- improved readability of output (wrap long lines, do not include unused
|
||||
labels and hypertargets)
|
||||
- support for more languages
|
||||
- writer.sty is replaced by the optional package ooomath.sty
|
||||
- color.sty is now optional
|
||||
- new options to ignore hard page and line breaks
|
||||
- new option to ignore double spaces
|
||||
- new option to specify that the document is *not* multilingual
|
||||
- support for cp1251 (Windows cyrillic) and latin2 inputenc
|
||||
- improved style maps for paragraphs (avoid line break, verbatim content)
|
||||
- cleaned up configuration of formatting
|
||||
- improved export of list formatting
|
||||
- support for other documentclasses than article
|
||||
- support for lastpage.sty
|
||||
- support for eurosym.sty
|
||||
- support for tipa.sty
|
||||
- support for various 8-bit fonts: Wingdings, Windows Symbol
|
||||
- support for OpenSymbol
|
||||
- XHTML:
|
||||
- converts units to px (default)
|
||||
- Calc2xhtml added
|
||||
- improved support for table formatting; table formatting is now always
|
||||
exported
|
||||
- (partial) bidi support
|
||||
- support for sections (margins and background color)
|
||||
- new option to scale column widths
|
||||
- new options to ignore double spaces, hard line breaks and empty paragraphs
|
||||
- General
|
||||
- Added ant build file (provided by Michael Niedermair)
|
||||
- Now possible to specify output path+file name on command line
|
||||
- removed usage of document specific configuration files (*-config.xml)
|
||||
- new option to create user configuration automatically
|
||||
|
||||
Version 0.3.2 (February 2004)
|
||||
- LaTeX:
|
||||
- support for custom math symbols (%symbol)
|
||||
- improved handling of paragraph formatting
|
||||
- support for table borders
|
||||
- support for alphabetical index
|
||||
- support for pdf meta data
|
||||
- XHTML:
|
||||
- support for three different XHTML variants
|
||||
- long documents can be split in several XHTML documents
|
||||
- support for custom style sheets
|
||||
- more flexible handling of fomatting
|
||||
- support for most XHTML elements (including blockquote, dl, hr)
|
||||
- support for alphabetical index
|
||||
- support for meta data
|
||||
|
||||
Version 0.3 (October 2003)
|
||||
- support for BibTeX
|
||||
- support for greek and russian text
|
||||
- support for more languages
|
||||
- support for latin1, cp1250, iso-8859-7, koi8-r and utf8 (Dominique
|
||||
Unruh's ucs.sty) inputencodings
|
||||
- support for symbol fonts: pifont.sty, wasysym.sty, ifsym.sty and
|
||||
bbding.sty
|
||||
- support for ulem.sty (underline/cross out)
|
||||
- export of footnotes configuration, list label styles, heading
|
||||
styles and hard paragraph formatting can be disabled
|
||||
- custom export of list styles
|
||||
- bugfixes
|
||||
|
||||
Version 0.2 (March 2003)
|
||||
- support for tables
|
||||
- support for graphics
|
||||
- support for outline numbering and list styles
|
||||
- support for page styles
|
||||
- support for sections (columns)
|
||||
- custom export of text and paragraph styles
|
||||
- integration with xmerge (enables use as export filter)
|
||||
- export to XHTML + MathML
|
||||
|
||||
Version 0.1 (September 2002)
|
||||
- first simple version
|
18
source/distro/Readme.txt
Normal file
18
source/distro/Readme.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
Writer2LaTeX version 0.9.4
|
||||
==========================
|
||||
|
||||
This is the distribution of Writer2LaTeX version 0.9.4
|
||||
|
||||
Latest version can be found at the web site
|
||||
http://writer2latex.sourceforge.net
|
||||
|
||||
You can read about installation and usage of Writer2LaTeX
|
||||
in the user guide, which is included in the
|
||||
directory doc.
|
||||
|
||||
Bugs and feature requests should be reported to
|
||||
henrikjust (at) openoffice.org
|
||||
|
||||
|
||||
February 2009
|
||||
Henrik Just
|
325
source/distro/changelog.txt
Normal file
325
source/distro/changelog.txt
Normal file
|
@ -0,0 +1,325 @@
|
|||
Changelog for Writer2LaTeX version 0.5 -> 1.0
|
||||
|
||||
---------- version 1.0 beta ----------
|
||||
|
||||
[w2l] Bugfix: Fixed crash for tables with fewer columns than rows
|
||||
|
||||
---------- version 0.9.4 -----------
|
||||
|
||||
[w2l] Added sample LaTeX configuration for Google Docs from Elefterios Stamatogiannakis
|
||||
|
||||
[w2x] Added MathML named entites table from Bruno Mascret
|
||||
|
||||
[all] Bugfix: Locked controls are now updated correctly when the dialog is displayed
|
||||
|
||||
[w2l] New backed xetex (initial prototype)
|
||||
|
||||
[c2x] Bugfix: Corrected wrong calculation of column number for columns with two letters
|
||||
(affected apply_print_ranges=true)
|
||||
|
||||
[c2x] Bugfix: Ensure that we always export a document, even if there are no defined
|
||||
print ranges (affected apply_print_ranges=true)
|
||||
|
||||
[c2x] Bugfix: Now also exports uplink for spreadsheets
|
||||
|
||||
[w2l] Bugfix: No longer incorrectly assume math mode when exporting plain text
|
||||
|
||||
[all] Added support for the new Writer notes/annotations (which now can contain several
|
||||
formatted paragraphs rather than a single, plain text paragraph)
|
||||
|
||||
[all] Added russian and ukrainian translations from Volodymyr Volkov
|
||||
|
||||
[all] Bugfix: Removed PreferredFilter propery from type definitions (makes sense
|
||||
only for import filters)
|
||||
|
||||
[all] Changed unix startscript: By default assume that w2l and writer2latex are
|
||||
in the same directory (thus using dirname $0), and assume that the java executable
|
||||
is either in the PATH or the location is defined by JAVA_HOME
|
||||
(which these assumptions manual editing of the script is usually not required)
|
||||
|
||||
[all] Added french translation from Jacques Lamoine
|
||||
|
||||
[w2l] The option simple_table_limit now refers to the *total* width of the table
|
||||
measured in characters rather than the width of individual cells
|
||||
|
||||
[w2x] Bugfix: The position and dimensions of a frame is now calculated correctly
|
||||
(previously the size of margins, borders and padding was not taken into account)
|
||||
|
||||
[w2l] The inputencoding utf8 now uses the LaTeX standard rather than ucs.sty
|
||||
(which only supports latin and cyrillic alphabets)
|
||||
|
||||
[w2l] New style map family "text-attribute" to map text formatting to LaTeX code
|
||||
currently only the values "bold", "italic", "small-caps", "subscript" and
|
||||
"superscript" are supported, and the verbatim attribute is not supported
|
||||
|
||||
---------- version 0.9.3 -----------
|
||||
|
||||
[all] All source files are now US ASCII; added encoding of source files to build file
|
||||
|
||||
[all] Added more File-based methods to the API
|
||||
|
||||
[w2l] The paper sizes defined by standard LaTeX document classes are now
|
||||
identified and added as global options (a4paper, a5paper, b5paper,
|
||||
letterpaper, legalpaper, executivepaper, including landscape variants)
|
||||
|
||||
[w2x] Bugfix: Now only exports the name of a text box if it actually exists!
|
||||
|
||||
[w2l] Removed option "pagecolor" from \hypersetup (this option has been removed
|
||||
from the hyperref package)
|
||||
|
||||
[all] Filter bugfix: The new option name "ConfigURL" is now used in the dialogs
|
||||
|
||||
[all] Added (partial) german localization from Martin Friedrich
|
||||
|
||||
[w2x] New option use_named_entities: When set to true, named character entities
|
||||
as defined in xhtml 1.0 are used (currently only those within ISO latin 1)
|
||||
|
||||
[w2x] Characters not supported by the encoding are now exported as numeric
|
||||
character entities
|
||||
|
||||
[w2x] Bugfix: Internal hyperlinks to tables, sections, frames and graphics now
|
||||
works correctly
|
||||
|
||||
[w2x] Bugfix: Subtables are no longer exported with an id attribute
|
||||
|
||||
[all] Bugfix: table:number-rows-repeated is now treated correctly
|
||||
|
||||
[c2x] New option: apply_print_ranges
|
||||
|
||||
---------- version 0.9.2 -----------
|
||||
|
||||
[c2x] No longer exports <tbody> for tables without <thead>
|
||||
|
||||
[all] Renamed "class" to "family" in style maps to avoid confusion
|
||||
with css classes (old name is still accepted)
|
||||
|
||||
[all] Filter: Renamed template and config options to the more
|
||||
descriptive TemplateURL and ConfigURL
|
||||
|
||||
[all] API: Added convenience method convert(File) to Converterer
|
||||
|
||||
[all] API: Added convenience method write(File) to ConverterResult
|
||||
|
||||
[all] New option: save_images_in_subdir
|
||||
|
||||
[all] Use Robert Harders public domain Base64 decoder (replacing
|
||||
the non-standard decoder in sun.misc)
|
||||
|
||||
[all] MIMETypes used in the API are now defined in writer2latex.api.MIMETypes
|
||||
|
||||
[all] Renamed the option keep_image_size to original_image_size (the meaning of
|
||||
this option was confusing). The old name is still recognized.
|
||||
|
||||
[all] OOo now saves SVM files with a MIME type in the package format.
|
||||
This is now recognized by w2l, which implies that GraphicConverter
|
||||
implementations can use SVM files from a package
|
||||
|
||||
[w2x] New uno service org.openoffice.da.writer2xhtml.BatchConverter
|
||||
provides batch conversion via uno. Interaction with the user can be implemented
|
||||
using the interface org.openoffice.da.writer2xhtml.XBatchHandler
|
||||
|
||||
[w2x] Batch processing from the command line can now be cancelled (using the Enter key)
|
||||
|
||||
[all] API: Created new API for batch conversion
|
||||
|
||||
[w2l] Bugfix: Tables were in rare cases exported with invalid row alignment
|
||||
(null character)
|
||||
|
||||
[w2x] Filter ui bugfix: Default value for RepeatLevels changed from
|
||||
6 to 5 (6 was not valid)
|
||||
|
||||
[w2x] Filter: The xhtml export now uses it's own custom configuration
|
||||
(writer2xhtml.xml, also stored in the user configuration of OOo)
|
||||
|
||||
[w2l] Tabstops are now exported as \ \ , which usually is closer to
|
||||
the expectations of the user (and is not ignored at the beginning of a par.)
|
||||
|
||||
[w2x] Empty paragraphs are now (again!) exported with a
|
||||
(otherwise they are ignored by the browser)
|
||||
|
||||
[w2x] Xhtml specific options no longer starts with the prefix xhtml_
|
||||
(is still accepted for backwards compatibility)
|
||||
|
||||
[all] Filter: Added display name and description to the extensions
|
||||
|
||||
[w2x] BatchConverter: Localized alternative text for icons
|
||||
|
||||
[w2b] Bugfix: Replace ";" with "and" also in in editor field
|
||||
|
||||
[w2x] Added new options xslt_path to give the path to the XSL
|
||||
transformation from w3c (also in the ui)
|
||||
|
||||
[all] Filter: Optimized the size of the extensions by excluding code not
|
||||
relevant for the format(s) supported by the extension
|
||||
|
||||
[all] Separated LaTeX and xhtml code. As a consequence, it is possible to build
|
||||
and run Writer2LaTeX with support for only one format
|
||||
|
||||
[c2x] New options display_hiddens_rows_cols and display_filtered_rows_cols. If
|
||||
set to false (default), rows and columns that are hidden or filtered are not
|
||||
exported
|
||||
|
||||
[all] Filter: Translated dialogs to Danish
|
||||
|
||||
[all] Filter: Raised requirement in description.xml to OOo 2.2
|
||||
(needs support for localized dialogs)
|
||||
|
||||
[w2l] Added ui option "Support additional symbols". This sets all the
|
||||
options use_pifont, use_ifsym, use_wasysym, use_eurosym and use_tipa.
|
||||
The pseudo-option additional_symbols can be used in the LockedOptions list
|
||||
|
||||
[all] Bugfix: The class w2l.xmerge.DOMDocument did not throw IOException when
|
||||
trying to read a non-xml document
|
||||
|
||||
[w2x] Bugfix: The convert method did not restart document enumeration
|
||||
(relevant if it's called several times for the same converter instance)
|
||||
|
||||
[w2x] API: Created new API for batch conversion, which is also moved
|
||||
from Application to a separate class
|
||||
|
||||
[all] API: The API now uses a interface to the configuration rather than using
|
||||
the class writer2latex.util.Config
|
||||
|
||||
[w2x] Style of header/footer in index pages (batch conversion) aligned with
|
||||
document header/footer
|
||||
|
||||
[all] Added package descriptions to the javadoc
|
||||
|
||||
[w2l] Always export non-breaking space as ~ even if inputenc supports it
|
||||
directly - non-breaking spaces are usually not easy to identify in text editors
|
||||
|
||||
---------- version 0.9.1 -----------
|
||||
|
||||
[w2x] New option: xhtml_add_bom (default false), if set to true
|
||||
a BOM will be added at the start of generated xhtml files
|
||||
|
||||
[w2x] Fixed typo in filter name: XHTML 1.0 + MathML 2.0 should be
|
||||
XHTML 1.1 + MathML 2.0
|
||||
|
||||
[w2l] Added support for the latin language
|
||||
|
||||
[w2l] Removed article.xml from w2l - it now belongs to Writer4LaTeX
|
||||
|
||||
[all] The distribution now includes a sample configuration
|
||||
package: xhtml-config-sample.oxt
|
||||
|
||||
[all] Filter: Split the filter component into two extensions:
|
||||
writer2latex.oxt for LaTeX and BibTeX, writer2xhtml.oxt for xhtml
|
||||
The build file now produces optimized jars for each application, and the
|
||||
standalone jar does not contain any uno code
|
||||
|
||||
[w2l] Added (imcomplete) support for some of the Euclid fonts from Design Science
|
||||
|
||||
[w2b] Replace ";" with "and" in author field (multiple authors)
|
||||
|
||||
[w2l] Added support for formulas inserted by OOoLaTeX
|
||||
|
||||
[w2x] Now adds mini-toc to the element with id "panel" if it exists in the xhtml
|
||||
template
|
||||
|
||||
[w2l] API: Added new api for standalone StarMath converter
|
||||
Writer2LaTeX api: writer2latex.api.StarMathConverter
|
||||
Uno service: org.openoffice.da.writer2latex.StarMathConverter
|
||||
|
||||
[all] Filter: Added dialogs to all filters (w2l, w2x and c2x)
|
||||
|
||||
[w2l] Vector graphics (except wmf) is now exported as pdf if backend is pdftex
|
||||
|
||||
[all] API: In the GraphicConverter interface, the method
|
||||
supportsFormat has been replaced with the method supportsConversion
|
||||
|
||||
[w2l] Added support for *numbered* display equations: If paragraph
|
||||
contains exactly one equation and exactly one sequence field (and otherwise
|
||||
only whitespace and brackets), it treated as a numbered equation
|
||||
|
||||
[w2l] I18n: If several characters in a row are converted using math mode, they
|
||||
are now combined (ie. ${\alpha}{\beta}$ rather than ${\alpha}$${\beta}$)
|
||||
|
||||
[all] Extended FilterData to support the property AutoCreate. If set to true,
|
||||
the configuration file will be created if it does not exist
|
||||
|
||||
[w2l] Even if formatting=IGNORE_ALL, we should still obey character style maps
|
||||
from the configuration
|
||||
|
||||
[w2x] Added german translation of navigation pane (w2l.util.L10n)
|
||||
|
||||
[all] Bugfix: A paragraph with a bibliographic reference as the only
|
||||
content was considered empty (and the reference was lost)
|
||||
|
||||
[w2l] Use url decoding when creating file names for linked sections
|
||||
(in order to obtain more readable file names)
|
||||
|
||||
[w2l] Avoid redundant \mathit in StarMathConverter in some rare
|
||||
cases (such as greek letters pasted into Math)
|
||||
|
||||
[w2l] Support formulas for sequence fields (only the most common
|
||||
cases oow:Name, oow:Name+Number, oow:Name-Number and oow:Number)
|
||||
|
||||
[c2x] New options xhtml_display_hidden_sheets, xhtml_use_title_as_heading and
|
||||
xhtml_use_sheet_names_as_headings
|
||||
|
||||
[o2x] New option xhtml_notes. If true notes (annotations) are exported to xhtml
|
||||
comments, if false they are ignored
|
||||
|
||||
[c2x] Convert notes (annotations)
|
||||
|
||||
[w2l] Heading formatting: The prefix and suffix to the counter should not be
|
||||
included in \thesection, but rather in the formatting. This means that the
|
||||
prefix and suffix no longer will be exported if formatting=CONVERT_BASIC
|
||||
|
||||
[w2l] Added support for chapter references to reference marks and bookmarks
|
||||
(if the marks are contained in a heading)
|
||||
|
||||
[w2l] New option external_bibtex_files gives a list of BibTeX files. If nonempty,
|
||||
these files will be used instead of converting the actual bibliography marks
|
||||
|
||||
[w2l] New option metadata. If true, export metadata as \author,
|
||||
\date and pdf metadata, as well as pdf metadata (if use_hyperref is true)
|
||||
|
||||
[all] Filters/API: Changed filternames to the more obvious
|
||||
org.openoffice.da.writer2latex etc.
|
||||
|
||||
[w2l] Updated clean.xml and ultraclean.xml. Both configurations
|
||||
now exports predefined Writer styles (like article.xml)
|
||||
|
||||
[w2x] New option: xhtml_repeat_levels defines the number of heading
|
||||
levels to repeat when splitting a file (0 means no levels are repeated)
|
||||
|
||||
[w2x] Allow xhtml templates without header and footer elements
|
||||
|
||||
[w2x] Bugfix (w2l.office.ListCounter): OpenDocument does not use
|
||||
numberings like 1.0.1 if a list level is missing, but rather 1.1.1
|
||||
|
||||
[all] Command line application now uses internal standard configurations
|
||||
(*ultraclean.xml etc.)
|
||||
|
||||
[all] Command line application now accepts several configuration
|
||||
files (by using the -config option more than once)
|
||||
|
||||
[w2x] Use text style for label when applying numbering to heading
|
||||
|
||||
[w2x] Added support for other list styes applied to headings
|
||||
|
||||
[w2x] Added support for text:restart-numbering, text:is-list-header on headings
|
||||
|
||||
[w2x] No longer add hr and [] to links in navigation (the template and style
|
||||
sheet should take care of this)
|
||||
|
||||
[all] New filter configuration concept: Configuration packages containing an OOo
|
||||
template, a w2l configuration and registry information to bind these together:
|
||||
When a configuration package is installed in OOo, the configuration is added
|
||||
to the filter ui, and is preselected for documents based on the OOo template
|
||||
|
||||
[all] Repackaging: Distribution files are included in source, build
|
||||
file is extended to create the distribution; source distribution is separated
|
||||
|
||||
[all] Changed to new extension format (.oxt)
|
||||
|
||||
[all] Filter: Added messagebox to display the error in case an
|
||||
exception happens during conversion
|
||||
|
||||
[all] Moved default configurations to jar; the FilterData property
|
||||
can refer to these using the special url *filename.xml
|
||||
|
||||
[all] The filter now reads the FilterData property, which can be
|
||||
used to specify options, configuration fil (url) and xhtml template (url)
|
BIN
source/distro/doc/user-manual.odt
Normal file
BIN
source/distro/doc/user-manual.odt
Normal file
Binary file not shown.
BIN
source/distro/doc/w2llogo.png
Normal file
BIN
source/distro/doc/w2llogo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
83
source/distro/latex/obsolete/writer.sty
Normal file
83
source/distro/latex/obsolete/writer.sty
Normal file
|
@ -0,0 +1,83 @@
|
|||
%% File: ooomath.sty, Copyright (C) 2002-2004 Henrik Just
|
||||
%%
|
||||
%% This file may be distributed and/or modified under the
|
||||
%% conditions of the LaTeX Project Public License, either version 1.2
|
||||
%% of this license or (at your option) any later version.
|
||||
%% The latest version of this license is in
|
||||
%% http://www.latex-project.org/lppl.txt
|
||||
%% and version 1.2 or later is part of all distributions of LaTeX
|
||||
%% version 1999/12/01 or later.
|
||||
%%
|
||||
\NeedsTeXFormat{LaTeX2e}
|
||||
\ProvidesPackage{ooomath}[2004/08/08 v1.0 - stylefile used by Writer2LaTeX]
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Some math mode macros defining additional symbols
|
||||
% \ddotsup is taken from "The comprehensive LaTeX symbol list"
|
||||
\newcommand\defeq{\stackrel{\mathrm{def}}{=}}
|
||||
\newcommand\lambdabar{\mathchar'26\mkern-10mu\lambda}
|
||||
\newcommand\ddotsup{\mathinner{\mkern1mu\raise\p@\vbox{\kern7\p@\hbox{.}}\mkern2mu\raise4\p@\hbox{.}\mkern2mu\raise7\p@
|
||||
\hbox{.}\mkern1mu}}
|
||||
% Fallback definitions for math mode macros defined in other packages
|
||||
\providecommand\multimapdotbothA{\bullet\kern-0.4em-\kern-0.4em\circ}
|
||||
\providecommand\multimapdotbothB{\circ\kern-0.4em-\kern-0.4em\bullet}
|
||||
\providecommand\oiint{\oint} % should be area integral...
|
||||
\providecommand\oiiint{\oint} % should be volume integral...
|
||||
\providecommand\llbracket{[} % should be double...
|
||||
\providecommand\rrbracket{]} % should be double...
|
||||
% More math mode macros
|
||||
\newcommand\wideslash[2]{{}^{#1}/_{#2}} % too small
|
||||
\newcommand\widebslash[2]{{}_{#1}\backslash^{#2}} % too small
|
||||
\newcommand\normalsubformula[1]{\text{$#1$}}
|
||||
\newcommand\boldsubformula[1]{\text{\mathversion{bold}$#1$}}
|
||||
% Multiscripts, based on leftidx.sty by Harald Harders
|
||||
\newlength{\idxmathdepth}
|
||||
\newlength{\idxmathtotal}
|
||||
\newlength{\idxmathwidth}
|
||||
\newlength{\idxraiseme}
|
||||
%
|
||||
\newcommand{\idxdheight}[1]{%
|
||||
\protect\settoheight{\idxmathtotal}{\(\displaystyle#1\)}%
|
||||
\protect\settodepth{\idxmathdepth}{\(\displaystyle#1\)}%
|
||||
\protect\settowidth{\idxmathwidth}{\(\displaystyle#1\)}%
|
||||
\protect\addtolength{\idxmathtotal}{\idxmathdepth}%
|
||||
\protect\setlength{\idxraiseme}{\idxmathtotal/2-\idxmathdepth}}
|
||||
\newcommand{\idxtheight}[1]{%
|
||||
\protect\settoheight{\idxmathtotal}{\(\textstyle #1\)}%
|
||||
\protect\settodepth{\idxmathdepth}{\(\textstyle #1\)}%
|
||||
\protect\settowidth{\idxmathwidth}{\(\textstyle#1\)}%
|
||||
\protect\addtolength{\idxmathtotal}{\idxmathdepth}%
|
||||
\protect\setlength{\idxraiseme}{\idxmathtotal/2-\idxmathdepth}}
|
||||
\newcommand{\idxsheight}[1]{%
|
||||
\protect\settoheight{\idxmathtotal}{\(\scriptstyle #1\)}%
|
||||
\protect\settodepth{\idxmathdepth}{\(\scriptstyle #1\)}%
|
||||
\protect\settowidth{\idxmathwidth}{\(\scriptstyle#1\)}%
|
||||
\protect\addtolength{\idxmathtotal}{\idxmathdepth}%
|
||||
\protect\setlength{\idxraiseme}{\idxmathtotal/2-\idxmathdepth}}
|
||||
\newcommand{\idxssheight}[1]{%
|
||||
\protect\settoheight{\idxmathtotal}{\(\scriptscriptstyle #1\)}%
|
||||
\protect\settodepth{\idxmathdepth}{\(\scriptscriptstyle #1\)}%
|
||||
\protect\settowidth{\idxmathwidth}{\(\scriptscriptstyle#1\)}%
|
||||
\protect\addtolength{\idxmathtotal}{\idxmathdepth}%
|
||||
\protect\setlength{\idxraiseme}{\idxmathtotal/2-\idxmathdepth}}
|
||||
% \multiscripts{<prescripts>}{<under>}{<over>}{<formula>}{<scripts>}
|
||||
\newcommand\multiscripts[5]{%
|
||||
\mathchoice%
|
||||
{\idxdheight{#4}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#1\underset{#2}
|
||||
{\overset{#3}{#4}}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#5}%
|
||||
{\idxtheight{#4}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#1\underset{#2}
|
||||
{\overset{#3}{#4}}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#5}%
|
||||
{\idxsheight{#4}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#1\underset{#2}
|
||||
{\overset{#3}{#4}}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#5}%
|
||||
{\idxssheight{#4}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#1\underset{#2}
|
||||
{\overset{#3}{#4}}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#5}
|
||||
}%
|
||||
\newcommand\mathoverstrike[1]{%
|
||||
\mathchoice%
|
||||
{\idxdheight{#1}\rlap{\rule[\idxraiseme]{\idxmathwidth}{0.4pt}}{#1}}%
|
||||
{\idxtheight{#1}\rlap{\rule[\idxraiseme]{\idxmathwidth}{0.4pt}}{#1}}%
|
||||
{\idxsheight{#1}\rlap{\rule[\idxraiseme]{\idxmathwidth}{0.4pt}}{#1}}%
|
||||
{\idxssheight{#1}\rlap{\rule[\idxraiseme]{\idxmathwidth}{0.4pt}}{#1}}%
|
||||
}
|
||||
\endinput
|
||||
|
83
source/distro/latex/ooomath.sty
Normal file
83
source/distro/latex/ooomath.sty
Normal file
|
@ -0,0 +1,83 @@
|
|||
%% File: ooomath.sty, Copyright (C) 2002-2004 Henrik Just
|
||||
%%
|
||||
%% This file may be distributed and/or modified under the
|
||||
%% conditions of the LaTeX Project Public License, either version 1.2
|
||||
%% of this license or (at your option) any later version.
|
||||
%% The latest version of this license is in
|
||||
%% http://www.latex-project.org/lppl.txt
|
||||
%% and version 1.2 or later is part of all distributions of LaTeX
|
||||
%% version 1999/12/01 or later.
|
||||
%%
|
||||
\NeedsTeXFormat{LaTeX2e}
|
||||
\ProvidesPackage{ooomath}[2004/12/27 v1.01 - stylefile used by Writer2LaTeX]
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Some math mode macros defining additional symbols
|
||||
% \ddotsup is taken from "The comprehensive LaTeX symbol list"
|
||||
\newcommand\defeq{\stackrel{\mathrm{def}}{=}}
|
||||
\newcommand\lambdabar{\mathchar'26\mkern-10mu\lambda}
|
||||
\newcommand\ddotsup{\mathinner{\mkern1mu\raise\p@\vbox{\kern7\p@\hbox{.}}\mkern2mu\raise4\p@\hbox{.}\mkern2mu\raise7\p@
|
||||
\hbox{.}\mkern1mu}}
|
||||
% Fallback definitions for math mode macros defined in other packages
|
||||
\providecommand\multimapdotbothA{\bullet\kern-0.4em-\kern-0.4em\circ}
|
||||
\providecommand\multimapdotbothB{\circ\kern-0.4em-\kern-0.4em\bullet}
|
||||
\providecommand\oiint{\oint} % should be area integral...
|
||||
\providecommand\oiiint{\oint} % should be volume integral...
|
||||
\providecommand\llbracket{[} % should be double...
|
||||
\providecommand\rrbracket{]} % should be double...
|
||||
% More math mode macros
|
||||
\newcommand\wideslash[2]{{}^{#1}/_{#2}} % too small
|
||||
\newcommand\widebslash[2]{{}_{#1}\backslash^{#2}} % too small
|
||||
\newcommand\normalsubformula[1]{\text{\mathversion{normal}$#1$}}
|
||||
\newcommand\boldsubformula[1]{\text{\mathversion{bold}$#1$}}
|
||||
% Multiscripts, based on leftidx.sty by Harald Harders
|
||||
\newlength{\idxmathdepth}
|
||||
\newlength{\idxmathtotal}
|
||||
\newlength{\idxmathwidth}
|
||||
\newlength{\idxraiseme}
|
||||
%
|
||||
\newcommand{\idxdheight}[1]{%
|
||||
\protect\settoheight{\idxmathtotal}{\(\displaystyle#1\)}%
|
||||
\protect\settodepth{\idxmathdepth}{\(\displaystyle#1\)}%
|
||||
\protect\settowidth{\idxmathwidth}{\(\displaystyle#1\)}%
|
||||
\protect\addtolength{\idxmathtotal}{\idxmathdepth}%
|
||||
\protect\setlength{\idxraiseme}{\idxmathtotal/2-\idxmathdepth}}
|
||||
\newcommand{\idxtheight}[1]{%
|
||||
\protect\settoheight{\idxmathtotal}{\(\textstyle #1\)}%
|
||||
\protect\settodepth{\idxmathdepth}{\(\textstyle #1\)}%
|
||||
\protect\settowidth{\idxmathwidth}{\(\textstyle#1\)}%
|
||||
\protect\addtolength{\idxmathtotal}{\idxmathdepth}%
|
||||
\protect\setlength{\idxraiseme}{\idxmathtotal/2-\idxmathdepth}}
|
||||
\newcommand{\idxsheight}[1]{%
|
||||
\protect\settoheight{\idxmathtotal}{\(\scriptstyle #1\)}%
|
||||
\protect\settodepth{\idxmathdepth}{\(\scriptstyle #1\)}%
|
||||
\protect\settowidth{\idxmathwidth}{\(\scriptstyle#1\)}%
|
||||
\protect\addtolength{\idxmathtotal}{\idxmathdepth}%
|
||||
\protect\setlength{\idxraiseme}{\idxmathtotal/2-\idxmathdepth}}
|
||||
\newcommand{\idxssheight}[1]{%
|
||||
\protect\settoheight{\idxmathtotal}{\(\scriptscriptstyle #1\)}%
|
||||
\protect\settodepth{\idxmathdepth}{\(\scriptscriptstyle #1\)}%
|
||||
\protect\settowidth{\idxmathwidth}{\(\scriptscriptstyle#1\)}%
|
||||
\protect\addtolength{\idxmathtotal}{\idxmathdepth}%
|
||||
\protect\setlength{\idxraiseme}{\idxmathtotal/2-\idxmathdepth}}
|
||||
% \multiscripts{<prescripts>}{<under>}{<over>}{<formula>}{<scripts>}
|
||||
\newcommand\multiscripts[5]{%
|
||||
\mathchoice%
|
||||
{\idxdheight{#4}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#1\underset{#2}
|
||||
{\overset{#3}{#4}}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#5}%
|
||||
{\idxtheight{#4}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#1\underset{#2}
|
||||
{\overset{#3}{#4}}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#5}%
|
||||
{\idxsheight{#4}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#1\underset{#2}
|
||||
{\overset{#3}{#4}}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#5}%
|
||||
{\idxssheight{#4}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#1\underset{#2}
|
||||
{\overset{#3}{#4}}\rule[-\idxmathdepth]{0mm}{\idxmathtotal}#5}
|
||||
}%
|
||||
\newcommand\mathoverstrike[1]{%
|
||||
\mathchoice%
|
||||
{\idxdheight{#1}\rlap{\rule[\idxraiseme]{\idxmathwidth}{0.4pt}}{#1}}%
|
||||
{\idxtheight{#1}\rlap{\rule[\idxraiseme]{\idxmathwidth}{0.4pt}}{#1}}%
|
||||
{\idxsheight{#1}\rlap{\rule[\idxraiseme]{\idxmathwidth}{0.4pt}}{#1}}%
|
||||
{\idxssheight{#1}\rlap{\rule[\idxraiseme]{\idxmathwidth}{0.4pt}}{#1}}%
|
||||
}
|
||||
\endinput
|
||||
|
113
source/distro/samples/config/google-docs-config.xml
Normal file
113
source/distro/samples/config/google-docs-config.xml
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- gdocs.xml
|
||||
This is a sample configuration file for Writer2LaTeX.
|
||||
The options are set to produce the cleanest possible
|
||||
LaTeX file from an Google Docs document.
|
||||
The configuration is provided by Elefterios Stamatogiannakis
|
||||
-->
|
||||
|
||||
|
||||
<config>
|
||||
<option name="documentclass" value="article" />
|
||||
<option name="backend" value="generic" />
|
||||
<option name="inputencoding" value="ascii" />
|
||||
<option name="multilingual" value="false" />
|
||||
<option name="use_ooomath" value="false" />
|
||||
<option name="use_color" value="false" />
|
||||
<option name="use_colortbl" value="false" />
|
||||
<option name="use_geometry" value="false" />
|
||||
<option name="use_fancyhdr" value="false" />
|
||||
<option name="use_hyperref" value="false" />
|
||||
<option name="use_caption" value="true" />
|
||||
<option name="use_endnotes" value="false" />
|
||||
<option name="use_bibtex" value="true" />
|
||||
<option name="bibtex_style" value="plain" />
|
||||
<option name="formatting" value="ignore_most" />
|
||||
<option name="page_formatting" value="ignore_all" />
|
||||
<option name="ignore_empty_paragraphs" value="true" />
|
||||
<option name="ignore_hard_page_breaks" value="true" />
|
||||
<option name="ignore_hard_line_breaks" value="true" />
|
||||
<option name="ignore_double_spaces" value="true" />
|
||||
<option name="use_supertabular" value="false" />
|
||||
<option name="simple_table_limit" value="10000" />
|
||||
<option name="wrap_lines_after" value="0" />
|
||||
<option name="debug" value="false" />
|
||||
<heading-map max-level="5">
|
||||
<heading-level-map writer-level="1" name="section" level="1" />
|
||||
<heading-level-map writer-level="2" name="subsection" level="2" />
|
||||
<heading-level-map writer-level="3" name="subsubsection" level="3" />
|
||||
<heading-level-map writer-level="4" name="paragraph" level="4" />
|
||||
<heading-level-map writer-level="5" name="subparagraph" level="5" />
|
||||
</heading-map>
|
||||
<custom-preamble />
|
||||
|
||||
<!-- Style maps: These rules defines how styles in OOo are mapped to LaTeX code.
|
||||
A number of predefined Writer styles are converted -->
|
||||
|
||||
<!-- "Title" is mapped to \maketitle. If the user chooses to export meta data,
|
||||
the author and date will be inserted automatically -->
|
||||
<style-map name="Title" class="paragraph" before="\title{" after="} \maketitle" line-break="false" />
|
||||
|
||||
<!-- "Quotations" is mapped to a quotation environment -->
|
||||
<style-map name="Quotations" family="paragraph-block" next="Quotations" before="\begin{quotation}" after="\end{quotation}" />
|
||||
<style-map name="Quotations" family="paragraph" before="" after="" />
|
||||
|
||||
<!-- Preformatted Text is mapped to a verbatim environment
|
||||
Note the attribute verbatim, which instructs OOo to output the content
|
||||
verbatim (characters not available in the inputencoding will be replaced
|
||||
by question marks; other content will be lost). -->
|
||||
<style-map name="Preformatted Text" family="paragraph-block" next="Preformatted Text" before="\begin{verbatim}" after="\end{verbatim}" />
|
||||
<style-map name="Preformatted Text" family="paragraph" before="" after="" verbatim="true" />
|
||||
|
||||
<!-- "Horizontal line" is mapped to a \hrule -->
|
||||
<style-map name="Horizontal Line" family="paragraph" before="" after=" \begin{center}\hrule\end{center}" />
|
||||
|
||||
<!-- "Emphasis" text style is mapped to \emph -->
|
||||
<style-map name="Emphasis" family="text" before="\emph{" after="}" />
|
||||
|
||||
<!-- Italics text style is mapped to \emph -->
|
||||
<style-map class="text-attribute" name="italic" before="\emph{" after="}" />
|
||||
|
||||
<!-- Underlined text style is mapped to latex verbatim output -->
|
||||
<style-map class="text-attribute" name="underline" before="" after="" verbatim="true"/>
|
||||
|
||||
<!-- Superscript text style is mapped to \textsuperscript -->
|
||||
<style-map class="text-attribute" name="superscript" before="\textsuperscript{" after="}" />
|
||||
|
||||
<!-- Subscript text style is mapped to clean latex -->
|
||||
<style-map class="text-attribute" name="subscript" before="$_{\textrm{" after="}}$" />
|
||||
|
||||
<!-- "Strong Emphasis" text style is mapped to \textbf -->
|
||||
<style-map name="Strong Emphasis" family="text" before="\textbf{" after="}"/>
|
||||
|
||||
<!-- "Teletype" text style is mapped to \texttt -->
|
||||
<style-map name="Teletype" family="text" before="\texttt{" after="}" />
|
||||
|
||||
<!-- "List Heading" and "List Contents" are mapped to a description environment -->
|
||||
<style-map name="List Heading" family="paragraph-block" next="List Heading;List Contents" before="\begin{description}" after="\end{description}"/>
|
||||
<style-map name="List Heading" family="paragraph" before="\item[" after="]" line-break="false" />
|
||||
<style-map name="List Contents" family="paragraph" before="" after="" />
|
||||
|
||||
<!-- Various characters are mapped to more human friendly latex entities-->
|
||||
<string-replace input=""" latex-code=""" />
|
||||
<string-replace input="<" latex-code="<" />
|
||||
<string-replace input=">" latex-code=">" />
|
||||
<string-replace input="‘" latex-code="`" />
|
||||
<string-replace input="’" latex-code="'" />
|
||||
<string-replace input="‚" latex-code="'" />
|
||||
<string-replace input="“" latex-code="``" />
|
||||
<string-replace input="”" latex-code="''" />
|
||||
<string-replace input="„" latex-code=""" />
|
||||
<string-replace input="" latex-code=""" />
|
||||
<string-replace input="" latex-code="''" />
|
||||
<string-replace input="" latex-code="'" />
|
||||
<string-replace input="" latex-code="``" />
|
||||
<string-replace input="" latex-code="'" />
|
||||
<string-replace input="'" latex-code="'" />
|
||||
|
||||
<!-- Some mappings to help with citations. -->
|
||||
<string-replace input="<<<" latex-code="\cite{" />
|
||||
<string-replace input=">>>" latex-code="}" />
|
||||
|
||||
</config>
|
||||
|
BIN
source/distro/samples/xhtml/sample-xhtml.odt
Normal file
BIN
source/distro/samples/xhtml/sample-xhtml.odt
Normal file
Binary file not shown.
22
source/distro/w2l
Normal file
22
source/distro/w2l
Normal file
|
@ -0,0 +1,22 @@
|
|||
# *Very* simple script to run Writer2LaTeX (unix version)
|
||||
# Created by Henrik Just, october 2003
|
||||
# Modified december 2003 as suggested by Juan Julian Merelo Guervos
|
||||
# Modified may 2004 as suggested by J. Wolfgang Kaltz
|
||||
# Last modified december 2008
|
||||
|
||||
# If writer2latex.jar is not in the same directory as the script, please
|
||||
# edit the following line to contain the full path to Writer2LaTeX:
|
||||
W2LPATH=`dirname $0`
|
||||
|
||||
# If the required JVM is not in your path, or the path is not set by JAVA_HOME,
|
||||
# please edit the following line to contain the full path and file name
|
||||
MYJAVAEXE="java"
|
||||
|
||||
if [ "$JAVA_HOME" = "" ]
|
||||
then
|
||||
JAVAEXE="$MYJAVAEXE"
|
||||
else
|
||||
JAVAEXE="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
|
||||
$JAVAEXE -jar "$W2LPATH/writer2latex.jar" "$@"
|
19
source/distro/w2l.bat
Normal file
19
source/distro/w2l.bat
Normal file
|
@ -0,0 +1,19 @@
|
|||
@echo off
|
||||
rem *Very* simple batch file to run Writer2LaTeX
|
||||
rem Created by Henrik Just, october 2003
|
||||
rem Modfied december 2003 as suggested by Juan Julian Merelo Guervos
|
||||
rem Last modified july 2007
|
||||
|
||||
rem Please edit the following line to contain the full path to Writer2LaTeX:
|
||||
|
||||
set W2LPATH="c:\writer2latex09"
|
||||
|
||||
rem If the Java executable is not in your path, please edit the following
|
||||
rem line to contain the full path and file name
|
||||
|
||||
set JAVAEXE="java"
|
||||
|
||||
%JAVAEXE% -jar %W2LPATH%\writer2latex.jar %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
|
||||
set W2LPATH=
|
||||
set JAVAEXE=
|
612
source/distro/xslt/pmathml.xsl
Normal file
612
source/distro/xslt/pmathml.xsl
Normal file
|
@ -0,0 +1,612 @@
|
|||
<xsl:stylesheet
|
||||
version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:mml="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:h="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
|
||||
xmlns:fns="http://www.w3.org/2002/Math/preference"
|
||||
xmlns:doc="http://www.dcarlisle.demon.co.uk/xsldoc"
|
||||
xmlns:ie5="http://www.w3.org/TR/WD-xsl"
|
||||
exclude-result-prefixes="h ie5 fns msxsl fns doc"
|
||||
extension-element-prefixes="msxsl fns doc"
|
||||
>
|
||||
|
||||
<!--
|
||||
$Id: pmathml.xsl,v 1.8 2003/06/23 14:46:44 davidc Exp $
|
||||
|
||||
Copyright David Carlisle 2001, 2002.
|
||||
|
||||
Use and distribution of this code are permitted under the terms of the <a
|
||||
href="http://www.w3.org/Consortium/Legal/copyright-software-19980720"
|
||||
>W3C Software Notice and License</a>.
|
||||
-->
|
||||
|
||||
<!-- MathPlayer mpdialog code for contributed by
|
||||
Jack Dignan and Robert Miner, both of Design Science.
|
||||
-->
|
||||
|
||||
<xsl:output method="xml" omit-xml-declaration="yes" />
|
||||
|
||||
<ie5:if doc:id="iehack" test=".">
|
||||
<ie5:eval no-entities="t">'<!--'</ie5:eval>
|
||||
</ie5:if>
|
||||
|
||||
|
||||
<fns:x name="mathplayer" o="MathPlayer.Factory.1">
|
||||
<object id="mmlFactory"
|
||||
classid="clsid:32F66A20-7614-11D4-BD11-00104BD3F987">
|
||||
</object>
|
||||
<?import namespace="mml" implementation="#mmlFactory"?>
|
||||
</fns:x>
|
||||
|
||||
<fns:x name="techexplorer" o="techexplorer.AxTchExpCtrl.1">
|
||||
<object id="mmlFactory" classid="clsid:0E76D59A-C088-11D4-9920-002035EFB1A4">
|
||||
</object>
|
||||
<?import namespace="mml" implementation="#mmlFactory"?>
|
||||
</fns:x>
|
||||
|
||||
|
||||
<!-- SCRIPT not script due to weird mozilla bug
|
||||
http://bugzilla.mozilla.org/show_bug.cgi?id=158457
|
||||
-->
|
||||
|
||||
<fns:x name="css" o="Microsoft.FreeThreadedXMLDOM">
|
||||
<SCRIPT for="window" event="onload">
|
||||
var xsl = new ActiveXObject("Microsoft.FreeThreadedXMLDOM");
|
||||
xsl.async = false;
|
||||
xsl.validateOnParse = false;
|
||||
xsl.load("pmathmlcss.xsl");
|
||||
var xslTemplate = new ActiveXObject("MSXML2.XSLTemplate.3.0");
|
||||
xslTemplate.stylesheet=xsl.documentElement;
|
||||
var xslProc = xslTemplate.createProcessor();
|
||||
xslProc.input = document.XMLDocument;
|
||||
xslProc.transform();
|
||||
var str = xslProc.output;
|
||||
<!-- work around bug in IE6 under Win XP, RM 6/5/2002 -->
|
||||
var repl = "replace";
|
||||
if (window.navigator.appVersion.match(/Windows NT 5.1/)) { repl = ""; }
|
||||
var newDoc = document.open("text/html", repl);
|
||||
newDoc.write(str);
|
||||
</SCRIPT>
|
||||
</fns:x>
|
||||
|
||||
|
||||
<h:p>
|
||||
in mpdialog mode, we just write out some JavaScript to display
|
||||
dialog to the reader asking whether they want to install MathPlayer
|
||||
Depending on the response we get, we then instantiate an XSL processor
|
||||
and reprocess the doc, passing $secondpass according to the
|
||||
reader response.
|
||||
</h:p>
|
||||
<h:p>Using d-o-e is fairly horrible, but this code is only for IE
|
||||
anyway, and we need to force HTML semantics in this case.</h:p>
|
||||
|
||||
<xsl:variable name="mpdialog">
|
||||
var cookieName = "MathPlayerInstall=";
|
||||
function MPInstall(){
|
||||
var showDialog=true;
|
||||
var c = document.cookie;
|
||||
var i = c.indexOf(cookieName);
|
||||
if (i >= 0) {
|
||||
if ( c.substr(i + cookieName.length, 1) >= 2) { showDialog=false; }
|
||||
}
|
||||
if (showDialog) {
|
||||
MPDialog();
|
||||
c = document.cookie;
|
||||
i = c.indexOf(cookieName);
|
||||
}
|
||||
if (i >= 0) return c.substr(i + cookieName.length, 1);
|
||||
else return null;
|
||||
}
|
||||
|
||||
function MPDialog() {
|
||||
var vArgs="";
|
||||
var sFeatures="dialogWidth:410px;dialogHeight:190px;help:off;status:no";
|
||||
var text = "";
|
||||
text += "javascript:document.write('"
|
||||
text += '<script>'
|
||||
text += 'function fnClose(v) { '
|
||||
text += 'var exp = new Date();'
|
||||
text += 'var thirtyDays = exp.getTime() + (30 * 24 * 60 * 60 * 1000);'
|
||||
text += 'exp.setTime(thirtyDays);'
|
||||
text += 'var cookieProps = ";expires=" + exp.toGMTString();'
|
||||
text += 'if (document.forms[0].dontask.checked) v+=2;'
|
||||
text += 'document.cookie="' + cookieName + '"+v+cookieProps;'
|
||||
text += 'window.close();'
|
||||
text += '}'
|
||||
text += '</' + 'script>'
|
||||
text += '<head><title>Install MathPlayer?</title></head>'
|
||||
text += '<body bgcolor="#D4D0C8"><form>'
|
||||
text += '<table cellpadding=10 style="font-family:Arial;font-size:10pt" border=0 width=100%>'
|
||||
text += '<tr><td align=left>This page requires Design Science\\\'s MathPlayer&trade;.<br>'
|
||||
text += 'Do you want to download and install MathPlayer?</td></tr>';
|
||||
text += '<tr><td align=center><input type="checkbox" name="dontask">'
|
||||
text += 'Don\\\'t ask me again</td></tr>'
|
||||
text += '<tr><td align=center><input id=yes type="button" value=" Yes "'
|
||||
text += ' onClick="fnClose(1)">&nbsp;&nbsp;&nbsp;'
|
||||
text += '<input type="button" value=" No " onClick="fnClose(0)"></td></tr>'
|
||||
text += '</table></form>';
|
||||
text += '</body>'
|
||||
text += "')"
|
||||
window.showModalDialog( text , vArgs, sFeatures );
|
||||
}
|
||||
|
||||
function WaitDialog() {
|
||||
var vArgs="";
|
||||
var sFeatures="dialogWidth:510px;dialogHeight:150px;help:off;status:no";
|
||||
var text = "";
|
||||
text += "javascript:document.write('"
|
||||
text += '<script>'
|
||||
text += 'window.onload=fnLoad;'
|
||||
text += 'function fnLoad() {document.forms[0].yes.focus();}'
|
||||
text += 'function fnClose(v) { '
|
||||
text += 'window.returnValue=v;'
|
||||
text += 'window.close();'
|
||||
text += '}'
|
||||
text += '</' + 'script>'
|
||||
text += '<head><title>Wait for Installation?</title></head>'
|
||||
text += '<body bgcolor="#D4D0C8" onload="fnLoad()"><form><'
|
||||
text += 'table cellpadding=10 style="font-family:Arial;font-size:10pt" border=0 width=100%>'
|
||||
text += '<tr><td align=left>Click OK once MathPlayer is installed '
|
||||
text += 'to refresh the page.<br>'
|
||||
text += 'Click Cancel to view the page immediately without MathPlayer.</td></tr>';
|
||||
text += '<tr><td align=center><input id=yes type="button" '
|
||||
text += 'value=" OK " onClick="fnClose(1)">&nbsp;&nbsp;&nbsp;'
|
||||
text += '<input type="button" value="Cancel" onClick="fnClose(0)"></td></tr>'
|
||||
text += '</table></form>';
|
||||
text += '</body>'
|
||||
text += "')"
|
||||
return window.showModalDialog( text , vArgs, sFeatures );
|
||||
}
|
||||
|
||||
var result = MPInstall();
|
||||
|
||||
var action = "fallthrough";
|
||||
if (result == 1 || result == 3) {
|
||||
window.open("http://www.dessci.com/webmath/mathplayer");
|
||||
var wait = WaitDialog();
|
||||
if ( wait == 1) {
|
||||
action = "install";
|
||||
document.location.reload();
|
||||
|
||||
}
|
||||
}
|
||||
if (action == "fallthrough") {
|
||||
var xsl = new ActiveXObject("Microsoft.FreeThreadedXMLDOM");
|
||||
xsl.async = false;
|
||||
xsl.validateOnParse = false;
|
||||
xsl.load("pmathmlcss.xsl");
|
||||
var xslTemplate = new ActiveXObject("MSXML2.XSLTemplate.3.0");
|
||||
xslTemplate.stylesheet=xsl.documentElement;
|
||||
var xslProc = xslTemplate.createProcessor();
|
||||
xslProc.input = document.XMLDocument;
|
||||
|
||||
xslProc.transform();
|
||||
var str = xslProc.output;
|
||||
<!-- work around bug in IE6 under Win XP, RM 6/5/2002 -->
|
||||
var repl = "replace";
|
||||
if (window.navigator.appVersion.match(/Windows NT 5.1/)) { repl = ""; }
|
||||
var newDoc = document.open("text/html", repl);
|
||||
newDoc.write(str);
|
||||
document.close();
|
||||
}
|
||||
</xsl:variable>
|
||||
|
||||
<fns:x name="mathplayer-dl" >mathplayer-dl</fns:x>
|
||||
|
||||
<fns:x name="techexplorer-plugin" >techexplorer-plugin</fns:x>
|
||||
|
||||
<xsl:variable name="root" select="/"/>
|
||||
|
||||
|
||||
|
||||
<xsl:param name="activex">
|
||||
<xsl:choose>
|
||||
<xsl:when test="/*/@fns:renderer='techexplorer-plugin'">techexplorer-plugin</xsl:when>
|
||||
<xsl:when test="system-property('xsl:vendor')!='Microsoft'"/>
|
||||
<xsl:otherwise>
|
||||
<xsl:variable name="docpref" select="document('')/*/fns:x[@name=$root/*/@fns:renderer][1]"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$docpref='mathplayer-dl'">mathplayer-dl</xsl:when>
|
||||
<xsl:when test="$docpref and fns:isinstalled(string($docpref/@o))='true'">
|
||||
<xsl:copy-of select="$docpref/node()"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:copy-of select="(document('')/*/fns:x[fns:isinstalled(string(@o))='true'])[1]/node()"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:param>
|
||||
|
||||
<h:div doc:ref="iehack">
|
||||
<h:h3>IE5 hacks</h:h3>
|
||||
<h:p>This code will be ignored by an XSLT engine as a top level
|
||||
element in a foreign namespace. It will be executed by an IE5XSL
|
||||
engine and insert <!-- into the output stream, ie the start of a
|
||||
comment. This will comment out all the XSLT code which will be copied
|
||||
to the output. A similar clause below will close this comment, it is
|
||||
then followed by the IE5XSL templates to be executed.</h:p>
|
||||
<h:p>This trick is due to Jonathan Marsh of Microsoft, and used in
|
||||
<h:a href="http://www.w3.org/TR/2001/WD-query-datamodel-20010607/xmlspec-ie-dm.xsl">the stylesheet for
|
||||
the XPath 2 data model draft</h:a>.</h:p>
|
||||
</h:div>
|
||||
|
||||
<h:h2>XSLT stylesheet</h:h2>
|
||||
<h:h3>MSXSL script block</h:h3>
|
||||
|
||||
<h:p>The following script block implements an extension function that
|
||||
tests whether a specified ActiveX component is known to the client.
|
||||
This is used below to test for the existence of MathML rendering
|
||||
components.</h:p>
|
||||
<msxsl:script language="JScript" implements-prefix="fns">
|
||||
function isinstalled(ax)
|
||||
{
|
||||
try {
|
||||
var ActiveX = new ActiveXObject(ax);
|
||||
return "true";
|
||||
} catch (e) {
|
||||
return "false";
|
||||
}
|
||||
}
|
||||
</msxsl:script>
|
||||
|
||||
<h:p>The main bulk of this stylesheet is an identity transformation so...</h:p>
|
||||
<xsl:template match="*|comment()">
|
||||
<xsl:copy>
|
||||
<xsl:copy-of select="@*"/>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:copy>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
|
||||
<h:p>XHTML elements are copied sans prefix (XHTML is default namespace
|
||||
here, so these elements will still be in XHTML namespace</h:p>
|
||||
<xsl:template match="h:*">
|
||||
<xsl:element name="{local-name(.)}">
|
||||
<xsl:copy-of select="@*"/>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>IE's treatment of XHTML as HTML needs a little help here...</h:p>
|
||||
<xsl:template match="h:br|h:hr">
|
||||
<xsl:choose>
|
||||
<xsl:when test="system-property('xsl:vendor')='Microsoft'">
|
||||
<xsl:value-of disable-output-escaping="yes" select="concat('<',local-name(.))"/>
|
||||
<xsl:apply-templates mode="verb" select="@*"/>
|
||||
<xsl:text disable-output-escaping="yes">></xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:element name="{local-name(.)}">
|
||||
<xsl:copy-of select="@*"/>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:element>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>This just ensures the mathml prefix declaration isn't copied from
|
||||
the source at this stage, so that the system will use the mml prefix
|
||||
coming from this stylesheet</h:p>
|
||||
<xsl:template match="h:html|html">
|
||||
<html>
|
||||
<xsl:copy-of select="@*[not(namespace-uri(.)='http://www.w3.org/2002/Math/preference')]"/>
|
||||
<xsl:apply-templates/>
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>We modify the head element to add code to specify a Microsoft
|
||||
"Behaviour" if the behaviour component is known to the system.</h:p>
|
||||
<h:span doc:ref="mp">Test for MathPlayer (Design Science)</h:span>
|
||||
<h:span doc:ref="te">Test for Techexplorer (IBM)</h:span>
|
||||
<h:span doc:ref="ms"><h:div>Test for Microsoft. In this case we just
|
||||
output a small HTML file that executes a script that will re-process
|
||||
the source docuument with a different stylesheet. Doing things this
|
||||
way avoids the need to xsl:import the second stylesheet, which would
|
||||
very much increase the processing overhead of running this
|
||||
stylesheet.</h:div></h:span>
|
||||
<h:span doc:ref="other">Further tests (eg for netscape/mozilla) could
|
||||
be added here if necessary</h:span>
|
||||
<xsl:template match="h:head|head">
|
||||
<head>
|
||||
|
||||
<!-- new if for IE frames bug -->
|
||||
<xsl:if test="system-property('xsl:vendor')='Microsoft'">
|
||||
<xsl:if test="name(msxsl:node-set($activex)/*)=''">
|
||||
<object id="mmlFactory"
|
||||
classid="clsid:32F66A20-7614-11D4-BD11-00104BD3F987">
|
||||
</object>
|
||||
<xsl:processing-instruction name="import">
|
||||
namespace="mml" implementation="#mmlFactory"
|
||||
</xsl:processing-instruction>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when doc:id="mp" test="$activex='mathplayer-dl'">
|
||||
<xsl:if test="fns:isinstalled('MathPlayer.Factory.1')='false'">
|
||||
<SCRIPT for="window" event="onload">
|
||||
<xsl:value-of select="$mpdialog" disable-output-escaping="yes"/>
|
||||
</SCRIPT>
|
||||
</xsl:if>
|
||||
<xsl:copy-of select="document('')/*/fns:x[@name='mathplayer']"/>
|
||||
</xsl:when>
|
||||
<xsl:when doc:id="mp" test="not($activex='techexplorer-plugin') and system-property('xsl:vendor')='Microsoft'">
|
||||
<xsl:copy-of select="$activex"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise doc:id="other">
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:apply-templates/>
|
||||
</head>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="mml:math" priority="22">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$activex='techexplorer-plugin'">
|
||||
<embed type="text/mathml" height="75" width="300">
|
||||
<xsl:attribute name="mmldata">
|
||||
<xsl:apply-templates mode="verb" select="."/>
|
||||
</xsl:attribute>
|
||||
</embed>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:element name="mml:{local-name(.)}">
|
||||
<xsl:copy-of select="@*"/>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:element>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- squash annotation elements -->
|
||||
|
||||
|
||||
|
||||
<h:p>Somewhat bizarrely in an otherwise namespace aware system,
|
||||
Microsoft behaviours are defined to trigger off the
|
||||
<h:em>prefix</h:em> not the <h:em>Namespace</h:em>. In the code above
|
||||
we associated a MathML rendering behaviour (if one was found) with the
|
||||
prefix <h:code>mml:</h:code> so here we ensure that this is the prefix
|
||||
that actually gets used in the output.</h:p>
|
||||
<xsl:template match="mml:*">
|
||||
<xsl:element name="mml:{local-name(.)}">
|
||||
<xsl:copy-of select="@*"/>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>Copy semantics element through in IE (so mathplayer gets to see
|
||||
mathplayer annotations, otherwise use first child or a presentation annotation.</h:p>
|
||||
<xsl:template match="mml:semantics">
|
||||
<xsl:choose>
|
||||
<xsl:when test="system-property('xsl:vendor')='Microsoft'">
|
||||
<xsl:element name="mml:{local-name(.)}">
|
||||
<xsl:copy-of select="@*"/>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:element>
|
||||
</xsl:when>
|
||||
<xsl:when test="mml:annotation-xml[@encoding='MathML-Presentation']">
|
||||
<xsl:apply-templates select="mml:annotation-xml[@encoding='MathML-Presentation']/node()"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates select="*[1]"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!-- a version of my old verb.xsl -->
|
||||
|
||||
<!-- non empty elements and other nodes. -->
|
||||
<xsl:template mode="verb" match="*[*]|*[text()]|*[comment()]|*[processing-instruction()]">
|
||||
<xsl:value-of select="concat('<',local-name(.))"/>
|
||||
<xsl:apply-templates mode="verb" select="@*"/>
|
||||
<xsl:text>></xsl:text>
|
||||
<xsl:apply-templates mode="verb"/>
|
||||
<xsl:value-of select="concat('</',local-name(.),'>')"/>
|
||||
</xsl:template>
|
||||
|
||||
<!-- empty elements -->
|
||||
<xsl:template mode="verb" match="*">
|
||||
<xsl:value-of select="concat('<',local-name(.))"/>
|
||||
<xsl:apply-templates mode="verb" select="@*"/>
|
||||
<xsl:text>/></xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<!-- attributes
|
||||
Output always surrounds attribute value by "
|
||||
so we need to make sure no literal " appear in the value -->
|
||||
<xsl:template mode="verb" match="@*">
|
||||
<xsl:value-of select="concat(' ',local-name(.),'=')"/>
|
||||
<xsl:text>"</xsl:text>
|
||||
<xsl:call-template name="string-replace">
|
||||
<xsl:with-param name="from" select="'"'"/>
|
||||
<xsl:with-param name="to" select="'&quot;'"/>
|
||||
<xsl:with-param name="string" select="."/>
|
||||
</xsl:call-template>
|
||||
<xsl:text>"</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<!-- pis -->
|
||||
<xsl:template mode="verb" match="processing-instruction()"/>
|
||||
|
||||
<!-- only works if parser passes on comment nodes -->
|
||||
<xsl:template mode="verb" match="comment()"/>
|
||||
|
||||
|
||||
<!-- text elements
|
||||
need to replace & and < by entity references-->
|
||||
<xsl:template mode="verb" match="text()">
|
||||
<a name="{generate-id(.)}"/>
|
||||
<xsl:call-template name="string-replace">
|
||||
<xsl:with-param name="to" select="'&gt;'"/>
|
||||
<xsl:with-param name="from" select="'>'"/>
|
||||
<xsl:with-param name="string">
|
||||
<xsl:call-template name="string-replace">
|
||||
<xsl:with-param name="to" select="'&lt;'"/>
|
||||
<xsl:with-param name="from" select="'<'"/>
|
||||
<xsl:with-param name="string">
|
||||
<xsl:call-template name="string-replace">
|
||||
<xsl:with-param name="to" select="'&amp;'"/>
|
||||
<xsl:with-param name="from" select="'&'"/>
|
||||
<xsl:with-param name="string" select="."/>
|
||||
</xsl:call-template>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- end verb mode -->
|
||||
|
||||
<!-- replace all occurences of the character(s) `from'
|
||||
by the string `to' in the string `string'.-->
|
||||
<xsl:template name="string-replace" >
|
||||
<xsl:param name="string"/>
|
||||
<xsl:param name="from"/>
|
||||
<xsl:param name="to"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains($string,$from)">
|
||||
<xsl:value-of select="substring-before($string,$from)"/>
|
||||
<xsl:value-of select="$to"/>
|
||||
<xsl:call-template name="string-replace">
|
||||
<xsl:with-param name="string" select="substring-after($string,$from)"/>
|
||||
<xsl:with-param name="from" select="$from"/>
|
||||
<xsl:with-param name="to" select="$to"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$string"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- end of verb.xsl -->
|
||||
|
||||
|
||||
|
||||
<h:h2>IE5XSL stylesheet</h:h2>
|
||||
<h:p>In a rare fit of sympathy for users of
|
||||
<h:em>the-language-known-as-XSL-in-IE5</h:em> this file incorporates a
|
||||
version of the above code designed to work in the Microsoft dialect.
|
||||
This is needed otherwise users of a MathML rendering behaviour would
|
||||
have to make a choice whether they wanted to use this stylesheet
|
||||
(keeping their source documents conforming XHTML+MathML) or to use
|
||||
the explicit Microsoft Object code, which is less portable, but would
|
||||
work in at least IE5.5.</h:p>
|
||||
|
||||
<h:p>This entire section of code, down to the end of the stylesheet is
|
||||
contained within this ie5:if. Thus XSLT sees it as a top level element
|
||||
from a foreign namespace and silently ignores it. IE5XSL sees it as
|
||||
"if true" and so executes the code.</h:p>
|
||||
|
||||
|
||||
<h:p doc:ref="closecomment">First close the comment started at the beginning. This ensures
|
||||
that the bulk of the XSLT code, while being copied to the result tree
|
||||
by the IE5XSL engine, will not be rendered in the browser.</h:p>
|
||||
|
||||
<h:span doc:ref="eval">Lacking attribute value templates in
|
||||
xsl:element, and the local-name() function, we resort to constructing
|
||||
the start and end tags in strings in javascript, then using
|
||||
no-entities attribute which is the IE5XSL equivalent of disable-output-encoding</h:span>
|
||||
<ie5:if test=".">
|
||||
|
||||
<ie5:eval doc:id="closecomment" no-entities="t">'-->'</ie5:eval>
|
||||
|
||||
<ie5:apply-templates select=".">
|
||||
|
||||
|
||||
<ie5:script>
|
||||
function mpisinstalled()
|
||||
{
|
||||
try {
|
||||
var ActiveX = new ActiveXObject("MathPlayer.Factory.1");
|
||||
return "true";
|
||||
} catch (e) {
|
||||
return "false";
|
||||
}
|
||||
}
|
||||
</ie5:script>
|
||||
|
||||
<ie5:template match="/">
|
||||
<ie5:apply-templates/>
|
||||
</ie5:template>
|
||||
|
||||
<ie5:template match="head|h:head"/>
|
||||
|
||||
<ie5:template match="text()">
|
||||
<ie5:value-of select="."/>
|
||||
</ie5:template>
|
||||
|
||||
<ie5:template match="*|@*">
|
||||
<ie5:copy>
|
||||
<ie5:apply-templates select="*|text()|@*"/>
|
||||
</ie5:copy>
|
||||
</ie5:template>
|
||||
|
||||
|
||||
<ie5:template match="mml:*">
|
||||
<ie5:eval no-entities="t" doc:id="eval">'<mml:' + this.nodeName.substring(this.nodeName.indexOf(":")+1)</ie5:eval>
|
||||
<ie5:for-each select="@*">
|
||||
<ie5:eval no-entities="t">' ' + this.nodeName</ie5:eval>="<ie5:value-of select="."/>"
|
||||
</ie5:for-each>
|
||||
<ie5:eval no-entities="t">'>'</ie5:eval>
|
||||
<ie5:apply-templates select="*|text()"/>
|
||||
<ie5:eval no-entities="t">'</mml:' + this.nodeName.substring(this.nodeName.indexOf(":")+1) + '>'</ie5:eval>
|
||||
</ie5:template>
|
||||
|
||||
|
||||
<ie5:template match="mml:math">
|
||||
<ie5:if expr="mpisinstalled()=='false'">
|
||||
<embed type="text/mathml" height="75" width="300">
|
||||
<ie5:attribute name="mmldata">
|
||||
<ie5:eval doc:id="eval" no-entities="t">'<math>'</ie5:eval>
|
||||
<ie5:apply-templates/>
|
||||
<ie5:eval doc:id="eval" no-entities="t">'</math>'</ie5:eval>
|
||||
</ie5:attribute>
|
||||
</embed>
|
||||
</ie5:if>
|
||||
<ie5:if expr="mpisinstalled()=='true'">
|
||||
<ie5:eval doc:id="eval" no-entities="t">'<mml:' + this.nodeName.substring(this.nodeName.indexOf(":")+1)</ie5:eval>
|
||||
<ie5:for-each select="@*">
|
||||
<ie5:eval no-entities="t">' ' + this.nodeName</ie5:eval>="<ie5:value-of select="."/>"
|
||||
</ie5:for-each>
|
||||
<ie5:eval no-entities="t">'>'</ie5:eval>
|
||||
<ie5:apply-templates select="*|text()"/>
|
||||
<ie5:eval no-entities="t">'</mml:' + this.nodeName.substring(this.nodeName.indexOf(":")+1) + '>'</ie5:eval>
|
||||
</ie5:if>
|
||||
</ie5:template>
|
||||
|
||||
<ie5:template match="html|h:html">
|
||||
<html xmlns:mml="http://www.w3.org/1998/Math/MathML">
|
||||
<head>
|
||||
<ie5:if expr="mpisinstalled()=='true'">
|
||||
<object id="mmlFactory"
|
||||
classid="clsid:32F66A20-7614-11D4-BD11-00104BD3F987">
|
||||
</object>
|
||||
<ie5:pi name="IMPORT">
|
||||
namespace="mml" implementation="#mmlFactory"
|
||||
</ie5:pi>
|
||||
</ie5:if>
|
||||
<ie5:apply-templates select="h:head/*|head/*"/>
|
||||
</head>
|
||||
<body>
|
||||
<ie5:apply-templates select="body|h:body"/>
|
||||
</body>
|
||||
</html>
|
||||
</ie5:template>
|
||||
|
||||
</ie5:apply-templates>
|
||||
|
||||
|
||||
</ie5:if>
|
||||
|
||||
|
||||
</xsl:stylesheet>
|
872
source/distro/xslt/pmathmlcss.xsl
Normal file
872
source/distro/xslt/pmathmlcss.xsl
Normal file
|
@ -0,0 +1,872 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!--
|
||||
Presentation MathML Stylesheet
|
||||
-->
|
||||
|
||||
<!--
|
||||
$Id: pmathmlcss.xsl,v 1.1 2002/03/20 12:20:57 mf Exp $
|
||||
|
||||
Copyright David Carlisle 2001, 2002.
|
||||
|
||||
Use and distribution of this code are permitted under the terms of the <a
|
||||
href="http://www.w3.org/Consortium/Legal/copyright-software-19980720"
|
||||
>W3C Software Notice and License</a>.
|
||||
-->
|
||||
|
||||
<xsl:stylesheet
|
||||
version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:h="http://www.w3.org/1999/xhtml"
|
||||
xmlns:m="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:doc="http://www.dcarlisle.demon.co.uk/xsldoc"
|
||||
xmlns:x="data:,x"
|
||||
exclude-result-prefixes="x h doc"
|
||||
>
|
||||
|
||||
<h:h2>Dictionary</h:h2>
|
||||
|
||||
<h:p> The following elements in the x: namespace form an
|
||||
implementation of an "Operator Dictionary" for this MathML
|
||||
Implementation. In the case of stretch operators, the element
|
||||
specifies the symbol parts via the latin-1 equivalent character based
|
||||
on the encoding in the symbol font. It is a clear "failure to comply
|
||||
to the spec" that using latin 1 characters (or numeric character
|
||||
references) in the latin 1 range access glyphs in teh symbol font via
|
||||
font position, however most of these character parts are not in
|
||||
Unicode (until 3.2), so there is no standard way to access these characters.</h:p>
|
||||
|
||||
<x:x x="{" m="0em" stretch="true" top="ì" middle="í" extend="ï" bottom="î">{</x:x>
|
||||
<x:x x="}" m="0em" stretch="true" top="ü" middle="ý" extend="ú" bottom="þ">{</x:x>
|
||||
|
||||
<x:x x="(" m="0em" stretch="true" top="æ" middle="ç" extend="ç" bottom="è">(</x:x>
|
||||
<x:x x=")" m="0em" stretch="true" top="ö" middle="÷" extend="÷" bottom="ø">)</x:x>
|
||||
|
||||
<x:x x="[" m="0em" stretch="true" top="é" middle="ê" extend="ê" bottom="ë">[</x:x>
|
||||
<x:x x="]" m="0em" stretch="true" top="ù" middle="ú" extend="ú" bottom="û">]</x:x>
|
||||
|
||||
<x:x x="〚" m="0em" stretch="true" top="éé" middle="êê" extend="êê" bottom="ëë">[[</x:x>
|
||||
<x:x x="〛" m="0em" stretch="true" top="ùù" middle="úú" extend="úú" bottom="ûû">]]</x:x>
|
||||
|
||||
<x:x x="|" m="0em" stretch="true" top="ç" middle="ç" extend="ç" bottom="ç">|</x:x>
|
||||
<x:x x="||" m="0em" stretch="true" top="çç" middle="çç" extend="çç" bottom="çç">||</x:x>
|
||||
|
||||
<x:x x="⁡" m="0em"></x:x><!-- applyfunction -->
|
||||
<x:x x="⁢" m="0em"></x:x><!-- invisibletimes -->
|
||||
<x:x x="-">−</x:x>
|
||||
<x:x x="≃"><span style="position:
|
||||
relative; top: +.1em;">−</span><span style="position:
|
||||
relative; left: -.55em; top: -.2em; margin: 0em;">~</span></x:x>
|
||||
<x:x x="︸" m="0em">_v_</x:x>
|
||||
|
||||
|
||||
<h:p>Remove these for now, as XML parser in IE6 is broken and doesn't
|
||||
accept plane 1 characters.</h:p>
|
||||
<!--
|
||||
<x:x x="𝔸" v="doublestruck">A</x:x>
|
||||
<x:x x="𝔹" v="doublestruck">B</x:x>
|
||||
<x:x x="ℂ" v="doublestruck">C</x:x>
|
||||
<x:x x="𝔻" v="doublestruck">D</x:x>
|
||||
|
||||
<x:x x="𝕒" v="doublestruck">a</x:x>
|
||||
<x:x x="𝕓" v="doublestruck">b</x:x>
|
||||
<x:x x="𝕔" v="doublestruck">c</x:x>
|
||||
<x:x x="𝕕" v="doublestruck">d</x:x>
|
||||
|
||||
<x:x x="𝔄" v="fraktur">A</x:x>
|
||||
<x:x x="𝔅" v="fraktur">B</x:x>
|
||||
<x:x x="ℭ" v="fraktur">C</x:x>
|
||||
<x:x x="𝔇" v="fraktur">D</x:x>
|
||||
|
||||
<x:x x="𝔞" v="fraktur">a</x:x>
|
||||
<x:x x="𝔟" v="fraktur">b</x:x>
|
||||
<x:x x="𝔠" v="fraktur">c</x:x>
|
||||
<x:x x="𝔡" v="fraktur">d</x:x>
|
||||
-->
|
||||
|
||||
<h:p>Grab all of the above into a variable.</h:p>
|
||||
<xsl:variable name="opdict" select="document('')/*/x:x"/>
|
||||
|
||||
<h:h2>HTML elements</h:h2>
|
||||
|
||||
<h:p>
|
||||
XHTML elements get passed straight through, sans namespace prefix.
|
||||
</h:p>
|
||||
<xsl:template match="h:*">
|
||||
<xsl:element name="{local-name(.)}">
|
||||
<xsl:copy-of select="@*"/>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
|
||||
|
||||
<h:p>
|
||||
Template for the head element copies the original content, aand in
|
||||
addition adds a script element and CSS style element that implement
|
||||
the core of the MathML renderer.
|
||||
</h:p>
|
||||
|
||||
<h:p doc:ref="malign">
|
||||
The malign function first finds the left most item in the aligngroup, and
|
||||
then modifies the left margin of each item to make them
|
||||
align. (Currently only left alignment is supported.)
|
||||
</h:p>
|
||||
|
||||
<h:p doc:ref="mrowStretch">
|
||||
The mrowStretch function implements stretchy brackets. It is called
|
||||
repeatedly, once for each mo child,after a span corresponding to an
|
||||
mrow. The arguments are the id of teh span and the characters to use
|
||||
for the parts of the stretch operator.
|
||||
constructed fence. The
|
||||
</h:p>
|
||||
|
||||
<h:p doc:ref="css">
|
||||
Inline CSS style block handles all font and size specification for the
|
||||
various MathML operators.
|
||||
</h:p>
|
||||
|
||||
<xsl:template match="h:head">
|
||||
|
||||
<xsl:element name="{local-name(.)}">
|
||||
<xsl:copy-of select="@*"/>
|
||||
<xsl:apply-templates/>
|
||||
|
||||
<script>
|
||||
|
||||
<xsl:text doc:id="malign">
|
||||
function malign (l)
|
||||
{
|
||||
var m = 0;
|
||||
for ( i = 0; i < l.length ; i++)
|
||||
{
|
||||
m = Math.max(m,l[i].offsetLeft);
|
||||
}
|
||||
for ( i = 0; i < l.length ; i++)
|
||||
{
|
||||
l[i].style.marginLeft=m - l[i].offsetLeft;
|
||||
}
|
||||
}
|
||||
</xsl:text>
|
||||
|
||||
<xsl:text doc:id="mrowStretch">
|
||||
function mrowStretch (opid,opt,ope,opm,opb){
|
||||
opH = opid.offsetHeight;
|
||||
var opH;
|
||||
var i;
|
||||
var es;
|
||||
if (mrowH > opH * 2) {
|
||||
m= "<font size='+1' face='symbol'>" + opm + "</font><br/>" ;
|
||||
if ((mrowH < opH * 3) &&(opm == ope) ) m="";
|
||||
es="";
|
||||
for ( i = 3; i <= mrowH / (2*opH) ; i += 1) es += "<font size='+1' face='symbol'>" + ope + "</font><br/>" ;
|
||||
opid.innerHTML="<table class='lr'><tr><td><font size='+1' face='symbol'>" +
|
||||
opt + "</font><br/>" +
|
||||
es +
|
||||
m +
|
||||
es +
|
||||
"<font size='+1' face='symbol'>" + opb + "</font></td></tr></table>";
|
||||
}
|
||||
}
|
||||
</xsl:text>
|
||||
|
||||
<xsl:text doc:id="msubsup">
|
||||
function msubsup (bs,bbs,x,b,p){
|
||||
<!--
|
||||
p.style.setExpression("top",bs +" .offsetTop - " + (p.offsetHeight/2 +(bbs.offsetHeight - Math.max(bbs.offsetHeight, b.offsetHeight + p.offsetHeight)*.5)));
|
||||
-->
|
||||
p.style.setExpression("top",bs +" .offsetTop -" + (p.offsetHeight/2));
|
||||
b.style.setExpression("top",bs + ".offsetTop + " + (bbs.offsetHeight - b.offsetHeight*.5));
|
||||
x.style.setExpression("marginLeft",Math.max(p.offsetWidth,b.offsetWidth));
|
||||
document.recalc(true);
|
||||
}
|
||||
</xsl:text>
|
||||
|
||||
<!--
|
||||
function msubsupzz (bs,x,b,p){
|
||||
p.style.setExpression("top",bs +" .offsetTop - " + bs +
|
||||
"p.offsetHeight/2 +(" + bs + ".offsetHeight - Math.max(" + bs + ".offsetHeight, (" + bs + "b.offsetHeight + " + bs + "p.offsetHeight)*.5))");
|
||||
b.style.setExpression("top",bs + ".offsetTop + " + bs + ".offsetHeight - " + bs + "b.offsetHeight/2");
|
||||
x.style.setExpression("marginLeft","Math.max(" + bs +"p.offsetWidth,"
|
||||
+ bs +"b.offsetWidth)");
|
||||
}
|
||||
-->
|
||||
|
||||
<xsl:text doc:id="msup">
|
||||
function msup (bs,x,p){
|
||||
p.style.setExpression("top",bs +" .offsetTop -" + (p.offsetHeight/2));
|
||||
x.style.setExpression("marginLeft", bs +"p.offsetWidth");
|
||||
x.style.setExpression("height", bs + ".offsetHeight + " + p.offsetHeight);
|
||||
document.recalc(true);
|
||||
}
|
||||
</xsl:text>
|
||||
|
||||
<xsl:text doc:id="msub">
|
||||
function msub (bs,x,p){
|
||||
p.style.setExpression("top",bs +" .offsetTop +" + (p.offsetHeight/2));
|
||||
x.style.setExpression("marginLeft", bs +"p.offsetWidth");
|
||||
x.style.setExpression("height", bs + ".offsetHeight + " + p.offsetHeight);
|
||||
document.recalc(true);
|
||||
}
|
||||
</xsl:text>
|
||||
|
||||
<xsl:text doc:id="toggle">
|
||||
function toggle (x) {
|
||||
for ( i = 0 ; i < x.childNodes.length ; i++) {
|
||||
if (x.childNodes.item(i).style.display=='inline') {
|
||||
x.childNodes.item(i).style.display='none';
|
||||
if ( i+1 == x.childNodes.length) {
|
||||
x.childNodes.item(0).style.display='inline';
|
||||
} else {
|
||||
x.childNodes.item(i+1).style.display='inline';
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
</xsl:text>
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
<xsl:text doc:id="css">
|
||||
|
||||
.msubsup {
|
||||
<!--background-color: red;-->
|
||||
font-size: 80%;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.munderover {
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.lr {
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mi {
|
||||
font-style: serif;
|
||||
}
|
||||
|
||||
|
||||
.mspace{
|
||||
display: inline;
|
||||
}
|
||||
.mtext {
|
||||
font-style: serif;
|
||||
}
|
||||
.ms {
|
||||
font-style: monospace;
|
||||
}
|
||||
|
||||
.mi1 {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.doublestruck {
|
||||
font-family: castellar, algerian,niagara engraved;
|
||||
}
|
||||
.mo {
|
||||
padding-right: .3em;
|
||||
padding-left: .3em;
|
||||
}
|
||||
|
||||
.mn {
|
||||
}
|
||||
|
||||
.msqrt {
|
||||
border-style: solid;
|
||||
border-color: black;
|
||||
border-width: .1em 0pt 0pt .1em;
|
||||
padding-left: .2em;
|
||||
margin-left: 0em;
|
||||
margin-top: .2em;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.actuarial {
|
||||
border-style: solid;
|
||||
border-color: black;
|
||||
border-width: .1em .1em 0pt 0pt ;
|
||||
padding-right: .2em;
|
||||
margin-right: 0em;
|
||||
margin-top: .2em;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.ssa {
|
||||
position:relative; top:+0.5ex;
|
||||
width: 0pt;
|
||||
color: red;
|
||||
}
|
||||
|
||||
|
||||
.mover {
|
||||
margin: 0pt;
|
||||
padding: 0pt;
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mtable {
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
.mfrac {
|
||||
text-align: center;
|
||||
display:inline;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mfraca {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.mfracaa {
|
||||
border-width: 0em 0em .2ex 0em ; border-style: solid;
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
|
||||
.mfracb {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.merror{
|
||||
background-color: white ;
|
||||
border-style: solid;
|
||||
border-color: #FF0000;
|
||||
color: #FF0000;
|
||||
}
|
||||
.mphantom{
|
||||
visibility: hidden;
|
||||
}
|
||||
</xsl:text>
|
||||
</style>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>
|
||||
Unimplemented MathML elements get copied literally, in red, mainly as
|
||||
a debugging aid.
|
||||
</h:p>
|
||||
<xsl:template match="m:*">
|
||||
<span style="color: red;"><<xsl:value-of select="local-name(.)"/>></span>
|
||||
<xsl:apply-templates/>
|
||||
<span style="color: red;"></<xsl:value-of select="local-name(.)"/>></span>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>
|
||||
mi: set default font based on string length, otherwise behaviour based
|
||||
on entries in the operator dictionary if one exists, or content is
|
||||
copied through to the output unchanged.
|
||||
</h:p>
|
||||
<xsl:template match="m:mi">
|
||||
<span class="mi">
|
||||
<xsl:if test="1=string-length(normalize-space(.))">
|
||||
<xsl:attribute name="class">mi1</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="@mathvariant"/>
|
||||
<xsl:variable name="x" select="normalize-space(.)"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$opdict[@x=$x and @v]">
|
||||
<xsl:attribute name="class"><xsl:value-of select="$opdict[@x=$x]/@v"/></xsl:attribute>
|
||||
<xsl:value-of select="$opdict[@x=$x and @v]"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$x"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>
|
||||
Handling of mathvariant attribute.
|
||||
The choice of font families here (currently) avoids math-specific
|
||||
fonts but does use several fionts coming with windows 9.x and/or
|
||||
office 2000.
|
||||
</h:p>
|
||||
<xsl:template match="@mathvariant[.='bold']">
|
||||
<xsl:attribute name="style">font-weight: bold; font-style: upright</xsl:attribute>
|
||||
</xsl:template>
|
||||
<xsl:template match="@mathvariant[.='bold-italic']">
|
||||
<xsl:attribute name="style">font-style: upright; font-weight: bold; font-style: italic;</xsl:attribute>
|
||||
</xsl:template>
|
||||
<xsl:template match="@mathvariant[.='italic']">
|
||||
<xsl:attribute name="style">font-style: italic; </xsl:attribute>
|
||||
</xsl:template>
|
||||
<xsl:template match="@mathvariant[.='monospace']">
|
||||
<xsl:attribute name="style">font-family: monospace; </xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="@mathvariant[.='sans-serif']">
|
||||
<xsl:attribute name="style">font-family: sans-serif; </xsl:attribute>
|
||||
</xsl:template>
|
||||
<xsl:template match="@mathvariant[.='bold-sans-serif']">
|
||||
<xsl:attribute name="style">font-family: sans-serif; font-weight: bold; </xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="@mathvariant[.='fraktur']">
|
||||
<xsl:attribute name="style">font-family: old english text mt</xsl:attribute>
|
||||
<xsl:attribute name="class"></xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="@mathvariant[.='double-struck']">
|
||||
<xsl:attribute name="class">doublestruck</xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="@mathvariant[.='script']">
|
||||
<xsl:attribute name="style">font-family: brush script mt italic</xsl:attribute>
|
||||
<xsl:attribute name="class"></xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<h:p>mo: Generate a unique ID so that a script at the end of any
|
||||
surrounding mrow may replace the conent by a suitably stretched
|
||||
operator if need be.</h:p>
|
||||
<xsl:template match="m:mo">
|
||||
<span id="{generate-id()}" class="mo">
|
||||
<xsl:apply-templates/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>mn: a simple span</h:p>
|
||||
<xsl:template match="m:mn">
|
||||
<span class="mn">
|
||||
<xsl:apply-templates/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>munder: currently only supports underline, with a bottom border</h:p>
|
||||
<xsl:template match="m:munder">
|
||||
<span class="munder">
|
||||
<xsl:if test="normalize-space(*[2])='̲'">
|
||||
<xsl:attribute
|
||||
name="style">border-width: 0pt 0pt .1em 0pt; border-style: solid;"</xsl:attribute>
|
||||
</xsl:if>
|
||||
<span><xsl:apply-templates select="*[1]"/></span>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>mover: currently only supports overline, with a top border</h:p>
|
||||
<xsl:template match="m:mover">
|
||||
<span class="munder">
|
||||
<xsl:if test="normalize-space(*[2])='¯'">
|
||||
<xsl:attribute
|
||||
name="style">border-width: .1em 0pt 0pt 0pt; border-style: solid;"</xsl:attribute>
|
||||
</xsl:if>
|
||||
<span><xsl:apply-templates select="*[1]"/></span>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>munderover: </h:p>
|
||||
<xsl:template match="m:munderover">
|
||||
<table class="munderover">
|
||||
<tr><td><xsl:apply-templates select="*[3]"/></td></tr>
|
||||
<tr><td><xsl:apply-templates select="*[1]"/></td></tr>
|
||||
<tr><td><xsl:apply-templates select="*[2]"/></td></tr>
|
||||
</table>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>mtext: a simple span</h:p>
|
||||
<xsl:template match="m:mtext">
|
||||
<span class="mtext">
|
||||
<xsl:value-of select="normalize-space(.)"/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>mstyle: not many attributes currently supported</h:p>
|
||||
<xsl:template match="m:mstyle">
|
||||
<span>
|
||||
<xsl:attribute name="style">
|
||||
<xsl:if test="@color">color: <xsl:value-of select="@color"/>; </xsl:if>
|
||||
<xsl:if test="@background">background-color: <xsl:value-of select="@background"/>; </xsl:if>
|
||||
</xsl:attribute>
|
||||
<xsl:apply-templates/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<h:p>mglyph: Uses disable output escaping to construct a numeric
|
||||
character reference. Uses IE's non conforming behaviour of using this
|
||||
number to access the font encoding rather than unicode.</h:p>
|
||||
<xsl:template match="m:mglyph">
|
||||
<font face="{@fontfamily}"><xsl:value-of
|
||||
disable-output-escaping="yes" select="'&#'"/>
|
||||
<xsl:value-of select="@index"/>;<xsl:text/>
|
||||
</font>
|
||||
</xsl:template>
|
||||
|
||||
<h:p>ms: a simple span with left and right character added to the content.</h:p>
|
||||
<xsl:template match="m:ms">
|
||||
<span class="ms">
|
||||
<xsl:value-of select="@lquote"/><xsl:if test="not(@lquote)">"</xsl:if>
|
||||
<xsl:value-of select="normalize-space(.)"/>
|
||||
<xsl:value-of select="@rquote"/><xsl:if test="not(@rquote)">"</xsl:if>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="m:math">
|
||||
<xsl:call-template name="mrow"/>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
|
||||
<xsl:template match="m:mfenced">
|
||||
<xsl:variable name="l">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@open"><xsl:value-of select="@open"/></xsl:when>
|
||||
<xsl:otherwise>(</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="r">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@close"><xsl:value-of select="@close"/></xsl:when>
|
||||
<xsl:otherwise>)</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="s">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@sep">
|
||||
<xsl:call-template name="text">
|
||||
<xsl:with-param name="x" select="@sep"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>,</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<span id="{generate-id()}L"><xsl:value-of select="$l"/></span>
|
||||
<span id="{generate-id()}M">
|
||||
<xsl:for-each select="*">
|
||||
<xsl:apply-templates select="."/>
|
||||
<xsl:if test="position() != last()"><span id="{generate-id()}X{position()}"><xsl:value-of select="$s"/></span></xsl:if>
|
||||
</xsl:for-each>
|
||||
</span>
|
||||
<span id="{generate-id()}R"><xsl:value-of select="$r"/></span>
|
||||
<script>
|
||||
|
||||
<xsl:if test="$s=$opdict[@stretch='true']/@x">
|
||||
<xsl:for-each select="*[position()<last()]">
|
||||
<xsl:variable name="opdictentry" select="$opdict[@x=$s]"/>
|
||||
mrowStretch(<xsl:value-of select="concat(generate-id(),'X',position())"/>,"<xsl:value-of
|
||||
select="$opdictentry/@top"/>","<xsl:value-of
|
||||
select="$opdictentry/@extend"/>","<xsl:value-of
|
||||
select="$opdictentry/@middle"/>","<xsl:value-of
|
||||
select="$opdictentry/@bottom"/>");</xsl:for-each>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:variable name="opdictentry" select="$opdict[@x=$l]"/>
|
||||
var mrowH = <xsl:value-of select="generate-id()"/>M.offsetHeight;
|
||||
mrowStretch(<xsl:value-of select="generate-id()"/>L,"<xsl:value-of
|
||||
select="$opdictentry/@top"/>","<xsl:value-of
|
||||
select="$opdictentry/@extend"/>","<xsl:value-of
|
||||
select="$opdictentry/@middle"/>","<xsl:value-of
|
||||
select="$opdictentry/@bottom"/>");<xsl:text/>
|
||||
|
||||
<xsl:variable name="opdictentry2" select="$opdict[@x=$r]"/>
|
||||
mrowStretch(<xsl:value-of select="generate-id()"/>R,"<xsl:value-of
|
||||
select="$opdictentry2/@top"/>","<xsl:value-of
|
||||
select="$opdictentry2/@extend"/>","<xsl:value-of
|
||||
select="$opdictentry2/@middle"/>","<xsl:value-of
|
||||
select="$opdictentry2/@bottom"/>");<xsl:text/>
|
||||
</script>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
|
||||
<xsl:template match="m:mmultiscripts">
|
||||
<table style="display:inline; vertical-align: middle;">
|
||||
<tr>
|
||||
<xsl:for-each select="*[preceding-sibling::m:mprescripts and position() mod 2 = 0]">
|
||||
<td><xsl:apply-templates select="."/></td>
|
||||
</xsl:for-each>
|
||||
<td rowspan="2"><xsl:apply-templates select="*[1]"/></td>
|
||||
<xsl:for-each select="*[not(preceding-sibling::m:mprescripts) and position() !=1 and position() mod 2 = 1]">
|
||||
<td><xsl:apply-templates select="."/></td>
|
||||
</xsl:for-each>
|
||||
</tr>
|
||||
<tr>
|
||||
<xsl:for-each select="*[preceding-sibling::m:mprescripts and position() mod 2 = 1]">
|
||||
<td><xsl:apply-templates select="."/></td>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="*[not(preceding-sibling::m:mprescripts) and
|
||||
not(self::m:mprescripts) and position() mod 2 = 0]">
|
||||
<td><xsl:apply-templates select="."/></td>
|
||||
</xsl:for-each>
|
||||
</tr>
|
||||
</table>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="m:none"></xsl:template>
|
||||
|
||||
<xsl:template match="m:merror">
|
||||
<span class="merror"><xsl:call-template name="mrow"/></span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:mphantom">
|
||||
<span class="mphantom"><xsl:apply-templates/></span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:maction[@type='tooltip']">
|
||||
<span title="{*[2]}"><xsl:apply-templates select="*[1]"/></span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:maction[@type='toggle']">
|
||||
<span id="{generate-id()}" onclick="toggle({generate-id()})">
|
||||
<span style="display:inline;"><xsl:apply-templates select="*[1]"/></span>
|
||||
<xsl:for-each select="*[position() > 1]">
|
||||
<span style="display:none;"><xsl:apply-templates select="."/></span>
|
||||
</xsl:for-each>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="m:maction[@type='statusline']">
|
||||
<span id="{generate-id()}"
|
||||
onmouseover="window.status='{*[2]}';"
|
||||
onmouseout="window.status='';"
|
||||
>
|
||||
<xsl:apply-templates select="*[1]"/></span>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="m:maction[@type='highlight']">
|
||||
<span id="{generate-id()}"
|
||||
onmouseover="{generate-id()}.style.backgroundColor='yellow';"
|
||||
onmouseout="{generate-id()}.style.backgroundColor='white';"><xsl:apply-templates/></span>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
|
||||
<xsl:template match="m:mrow" name="mrow">
|
||||
<span id="{generate-id()}" class="mrow">
|
||||
<xsl:apply-templates select="*"/>
|
||||
</span>
|
||||
<xsl:if test="m:mo[@stretch='true' or normalize-space(.)=$opdict[@stretch='true']/@x]">
|
||||
<script>
|
||||
var mrowH = <xsl:value-of select="generate-id()"/>.offsetHeight;
|
||||
<xsl:for-each select="m:mo[@stretch='true' or
|
||||
normalize-space(.)=$opdict[@stretch='true']/@x]">
|
||||
|
||||
<xsl:variable name="o" select="normalize-space(.)"/>
|
||||
<xsl:variable name="opdictentry" select="$opdict[@x=$o]"/>
|
||||
mrowStretch(<xsl:value-of select="generate-id()"/>,"<xsl:value-of
|
||||
select="$opdictentry/@top"/>","<xsl:value-of
|
||||
select="$opdictentry/@extend"/>","<xsl:value-of
|
||||
select="$opdictentry/@middle"/>","<xsl:value-of
|
||||
select="$opdictentry/@bottom"/>");</xsl:for-each>
|
||||
</script>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="m:msubsup">
|
||||
<span id="{generate-id()}" >
|
||||
<xsl:apply-templates select="*[1]"/></span
|
||||
><span id="{generate-id()}b" class="msubsup"><xsl:apply-templates
|
||||
select="*[2]"/></span
|
||||
><span id="{generate-id()}p" class="msubsup"><xsl:apply-templates
|
||||
select="*[3]"/></span
|
||||
><span id="{generate-id()}x"></span>
|
||||
<script>
|
||||
msubsup("<xsl:value-of select="concat(generate-id(),'",',generate-id(),',',generate-id(),'x,',generate-id(),'b,',generate-id())"/>p);
|
||||
</script>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="h:table//m:msubsup|m:mtable//m:msubsup|m:msubsup"
|
||||
priority="2">
|
||||
<span>
|
||||
<xsl:apply-templates select="*[1]"/>
|
||||
</span
|
||||
><sub><xsl:apply-templates
|
||||
select="*[2]"/></sub>
|
||||
<sup><xsl:apply-templates
|
||||
select="*[3]"/></sup>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:msup
|
||||
">
|
||||
<span id="{generate-id()}">
|
||||
<xsl:apply-templates select="*[1]"/>
|
||||
</span
|
||||
><span id="{generate-id()}p" class="msubsup"><xsl:apply-templates
|
||||
select="*[2]"/></span
|
||||
><span id="{generate-id()}x"></span>
|
||||
<script>
|
||||
msup("<xsl:value-of select="concat(generate-id(),'",',generate-id(),'x,',generate-id())"/>p);
|
||||
</script>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="h:table//m:msup|m:mtable//m:msup|m:msup"
|
||||
priority="2">
|
||||
<span>
|
||||
<xsl:apply-templates select="*[1]"/>
|
||||
</span
|
||||
><sup><xsl:apply-templates
|
||||
select="*[2]"/></sup>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:msub
|
||||
">
|
||||
<span id="{generate-id()}">
|
||||
<xsl:apply-templates select="*[1]"/>
|
||||
</span
|
||||
><span id="{generate-id()}p" class="msubsup"><xsl:apply-templates
|
||||
select="*[2]"/></span
|
||||
><span id="{generate-id()}x"></span>
|
||||
<script>
|
||||
msub("<xsl:value-of select="concat(generate-id(),'",',generate-id(),'x,',generate-id())"/>p);
|
||||
</script>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="h:table//m:msub|m:mtable//m:msub|m:msub"
|
||||
priority="2">
|
||||
<span>
|
||||
<xsl:apply-templates select="*[1]"/>
|
||||
</span
|
||||
><sub><xsl:apply-templates
|
||||
select="*[2]"/></sub>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="m:*/text()" name="text">
|
||||
<xsl:param name="x" select="normalize-space(.)"/>
|
||||
<xsl:variable name="mo" select="document('')/*/x:x[@x=$x]"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$mo"><xsl:copy-of select="$mo/node()"/></xsl:when>
|
||||
<xsl:otherwise><xsl:copy-of select="$x"/></xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="m:msqrt">
|
||||
<span class="msqrtx">\</span><span class="msqrt">
|
||||
<xsl:apply-templates/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:menclose[@notation='radical']">
|
||||
<span class="msqrtx">\</span><span class="msqrt">
|
||||
<xsl:apply-templates/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:menclose[@notation='actuarial']">
|
||||
<span class="actuarial">
|
||||
<xsl:apply-templates/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:menclose">
|
||||
<span class="msqrt">
|
||||
<xsl:apply-templates/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:mroot">
|
||||
<span class="msqrtx"><sup><xsl:apply-templates select="*[2]"/></sup>\</span><span class="msqrt">
|
||||
<xsl:apply-templates select="*[1]"/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="m:mfrac">
|
||||
<xsl:param name="full" select="not(ancestor::m:mfrac)"/>
|
||||
<table class="mfrac">
|
||||
<xsl:if test="$full">
|
||||
<xsl:attribute name="style">font-size: 75% ;</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test="not($full)">
|
||||
<xsl:attribute name="style">font-size: 100% ;</xsl:attribute>
|
||||
</xsl:if>
|
||||
<tr id="a{generate-id()}" class="mfraca"><td class="mfracaa">
|
||||
<xsl:apply-templates select="*[1]"/>
|
||||
</td></tr>
|
||||
<tr id="b{generate-id()}" class="mfracb"><td>
|
||||
<xsl:apply-templates select="*[2]"/>
|
||||
</td></tr>
|
||||
</table><xsl:if test="$full"><script>
|
||||
if ( a<xsl:value-of select="generate-id()"
|
||||
/>.offsetHeight > b<xsl:value-of select="generate-id()"
|
||||
/>.offsetHeight ) b<xsl:value-of select="generate-id()
|
||||
"/>.style.setExpression("height",a<xsl:value-of select="generate-id()"/>.offsetHeight );
|
||||
else a<xsl:value-of
|
||||
select="generate-id()"/>.style.setExpression("height",b<xsl:value-of
|
||||
select="generate-id()"/>.offsetHeight );
|
||||
</script></xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:padded">
|
||||
<span>
|
||||
<xsl:attribute name="display">
|
||||
</xsl:attribute>
|
||||
<xsl:apply-templates/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="m:mspace">
|
||||
<span style="padding-left: {@width};"></span>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:mtable">
|
||||
<table class="mtable">
|
||||
<xsl:apply-templates/>
|
||||
</table>
|
||||
<script>
|
||||
<xsl:variable name="t" select="."/>
|
||||
<xsl:for-each select="m:mtr[1]/m:mtd">
|
||||
<xsl:variable name="c" select="position()"/>
|
||||
<xsl:for-each select="descendant::m:maligngroup">
|
||||
<xsl:variable name="g" select="position()"/>
|
||||
malign([<xsl:for-each
|
||||
select="$t/m:mtr/m:mtd[$c]/descendant::m:maligngroup[$g]">
|
||||
<xsl:value-of select="generate-id()"/>
|
||||
<xsl:if test="position()<last()">,</xsl:if>
|
||||
</xsl:for-each>]);</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
</script>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:mtr">
|
||||
<tr>
|
||||
<xsl:apply-templates/>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="m:mtd">
|
||||
<td>
|
||||
<xsl:apply-templates/>
|
||||
</td>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="m:maligngroup">
|
||||
<xsl:variable name="g">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@groupalign">
|
||||
</xsl:when>
|
||||
<xsl:when test="ancestor::td/@groupalign">
|
||||
</xsl:when>
|
||||
<xsl:when test="ancestor::tr/@groupalign">
|
||||
</xsl:when>
|
||||
<xsl:when test="ancestor::table/@groupalign">
|
||||
</xsl:when>
|
||||
|
||||
<xsl:otherwise>left</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<span id="{generate-id()}"></span>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
</xsl:stylesheet>
|
30
source/idl/readme-idl.txt
Normal file
30
source/idl/readme-idl.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
This directory contains idl specifications for the custom uno interfaces
|
||||
defined by the Writer2LaTeX and Writer2xhtml extensions
|
||||
|
||||
To avoid dependencies on the OOo SDK in the build process, compiled versions
|
||||
are included here.
|
||||
|
||||
If you need to rebuild it, the complete SDK is required. These are the steps:
|
||||
|
||||
To create the registry database for Writer2LaTeX:
|
||||
|
||||
idlc -I<path to SDK>\idl XW2LStarMathConverter.idl
|
||||
regmerge writer2latex.rdb /UCR XW2LStarMathConverter.urd
|
||||
|
||||
To create the java interface
|
||||
|
||||
javamaker -BUCR -Torg.openoffice.da.writer2latex.XW2LStarMathConverter -nD <path to the OOo installation>\program\types.rdb writer2latex.rdb
|
||||
|
||||
and likewise for Writer2xhtml:
|
||||
|
||||
idlc -I<path to SDK>\idl XBatchConverter.idl
|
||||
regmerge writer2xhtml.rdb /UCR XBatchConverter.urd
|
||||
|
||||
To create the java interfaces
|
||||
|
||||
javamaker -BUCR -Torg.openoffice.da.writer2xhtml.XBatchConverter -nD <path to the OOo installation>\program\types.rdb writer2xhtml.rdb
|
||||
javamaker -BUCR -Torg.openoffice.da.writer2xhtml.XBatchHandler -nD <path to the OOo installation>\program\types.rdb writer2xhtml.rdb
|
||||
|
||||
|
||||
If you need to use the interfaces from C++ you will also need to run cppumaker
|
||||
|
22
source/idl/writer2latex/XW2LStarMathConverter.idl
Normal file
22
source/idl/writer2latex/XW2LStarMathConverter.idl
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef __org_openoffice_da_writer2latex_XW2LStarMathConverter_idl__
|
||||
#define __org_openoffice_da_writer2latex_XW2LStarMathConverter_idl__
|
||||
#include <com/sun/star/uno/XInterface.idl>
|
||||
|
||||
module org { module openoffice { module da { module writer2latex {
|
||||
|
||||
interface XW2LStarMathConverter : com::sun::star::uno::XInterface
|
||||
{
|
||||
|
||||
// method org::openoffice::da::writer2latex::XW2LStarMathConverter::convertFormula
|
||||
string convertFormula ( [in] string sStarMathFormula );
|
||||
|
||||
// method org::openoffice::da::writer2latex::XW2LStarMathConverter::getPreamble
|
||||
string getPreamble ( );
|
||||
|
||||
};
|
||||
|
||||
}; }; }; };
|
||||
|
||||
#endif
|
||||
|
||||
|
Binary file not shown.
BIN
source/idl/writer2latex/writer2latex.rdb
Normal file
BIN
source/idl/writer2latex/writer2latex.rdb
Normal file
Binary file not shown.
52
source/idl/writer2xhtml/XBatchConverter.idl
Normal file
52
source/idl/writer2xhtml/XBatchConverter.idl
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifndef __org_openoffice_da_writer2xhtml_XBatchConverter_idl__
|
||||
#define __org_openoffice_da_writer2xhtml_XBatchConverter_idl__
|
||||
#include <com/sun/star/uno/XInterface.idl>
|
||||
#include <com/sun/star/beans/PropertyValue.idl>
|
||||
|
||||
module org { module openoffice { module da { module writer2xhtml {
|
||||
|
||||
// This interface is an IDL version of the java interface (writer2latex.api.BatchHandler)
|
||||
interface XBatchHandler : com::sun::star::uno::XInterface
|
||||
{
|
||||
|
||||
// method org::openoffice::da::writer2xhtml::XBatchHandler::startConversion
|
||||
void startConversion ();
|
||||
|
||||
// method org::openoffice::da::writer2xhtml::XBatchHandler::endConversion
|
||||
void endConversion ();
|
||||
|
||||
// method org::openoffice::da::writer2xhtml::XBatchHandler::startDirectory
|
||||
void startDirectory ( [in] string sName );
|
||||
|
||||
// method org::openoffice::da::writer2xhtml::XBatchHandler::endDirectory
|
||||
void endDirectory ( [in] string sName, [in] boolean bSuccess );
|
||||
|
||||
// method org::openoffice::da::writer2xhtml::XBatchHandler::startFile
|
||||
void startFile ( [in] string sName );
|
||||
|
||||
// method org::openoffice::da::writer2xhtml::XBatchHandler::endFile
|
||||
void endFile ( [in] string sName, [in] boolean bSuccess );
|
||||
|
||||
// method org::openoffice::da::writer2xhtml::XBatchHandler::cancel
|
||||
boolean cancel ();
|
||||
|
||||
};
|
||||
|
||||
// This interface is an IDL version of the java interface (writer2latex.api.BatchConverter)
|
||||
interface XBatchConverter : com::sun::star::uno::XInterface
|
||||
{
|
||||
|
||||
// method org::openoffice::da::writer2xhtml::XBatchConverter::convert
|
||||
void convert ( [in] string sSourceURL,
|
||||
[in] string sTargetURL,
|
||||
[in] sequence< com::sun::star::beans::PropertyValue > lArguments,
|
||||
[in] XBatchHandler handler );
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
}; }; }; };
|
||||
|
||||
#endif
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
BIN
source/idl/writer2xhtml/writer2xhtml.rdb
Normal file
BIN
source/idl/writer2xhtml/writer2xhtml.rdb
Normal file
Binary file not shown.
|
@ -0,0 +1,188 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ByteArrayXStream.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
// This class is based on these java uno adapter classes:
|
||||
// com.sun.star.lib.uno.adapter.ByteArrayToXInputStreamAdapter;
|
||||
// com.sun.star.lib.uno.adapter.XOutputStreamToByteArrayAdapter;
|
||||
// See http://go-oo.org/lxr/source/udk/javaunohelper/com/sun/star/lib/uno/adapter/XOutputStreamToByteArrayAdapter.java
|
||||
// and http://go-oo.org/lxr/source/udk/javaunohelper/com/sun/star/lib/uno/adapter/ByteArrayToXInputStreamAdapter.java
|
||||
// for original source
|
||||
|
||||
import com.sun.star.io.XInputStream;
|
||||
import com.sun.star.io.XOutputStream;
|
||||
import com.sun.star.io.XSeekable;
|
||||
import com.sun.star.io.XStream;
|
||||
|
||||
/** <p>This is a java-uno adapter class which implements XStream using a
|
||||
* byte array. (We need this because XGraphicProvider demans read/write access
|
||||
* when storing a graphic to a stream.)</p>
|
||||
*/
|
||||
public class ByteArrayXStream implements XInputStream, XOutputStream, XSeekable, XStream {
|
||||
|
||||
// Keep data about our byte array (we read and write to the same byte array)
|
||||
|
||||
private int initialSize = 100240; // 10 kb
|
||||
private int size = 0; // The current buffer size
|
||||
private int position = 0; // The current write position, always<=size
|
||||
private int readPosition = 0; // The current read position, always<=position
|
||||
private boolean closed = false; // The XStream is closed
|
||||
private byte[] buffer; // The buffer
|
||||
|
||||
// Constructor: Initialize the byte array
|
||||
|
||||
public ByteArrayXStream() {
|
||||
size = initialSize;
|
||||
buffer = new byte[size];
|
||||
}
|
||||
|
||||
// Implementation of XOutputStream
|
||||
|
||||
public void closeOutput()
|
||||
throws com.sun.star.io.NotConnectedException,
|
||||
com.sun.star.io.BufferSizeExceededException,
|
||||
com.sun.star.io.IOException {
|
||||
|
||||
// trim buffer
|
||||
if ( buffer.length > position) {
|
||||
byte[] newBuffer = new byte[position];
|
||||
System.arraycopy(buffer, 0, newBuffer, 0, position);
|
||||
buffer = newBuffer;
|
||||
}
|
||||
closed = true;
|
||||
}
|
||||
|
||||
public void flush()
|
||||
throws com.sun.star.io.NotConnectedException,
|
||||
com.sun.star.io.BufferSizeExceededException,
|
||||
com.sun.star.io.IOException {
|
||||
}
|
||||
|
||||
public void writeBytes(byte[] values)
|
||||
throws com.sun.star.io.NotConnectedException,
|
||||
com.sun.star.io.BufferSizeExceededException,
|
||||
com.sun.star.io.IOException {
|
||||
if ( values.length > size-position ) {
|
||||
byte[] newBuffer = null;
|
||||
while ( values.length > size-position )
|
||||
size *= 2;
|
||||
newBuffer = new byte[size];
|
||||
System.arraycopy(buffer, 0, newBuffer, 0, position);
|
||||
buffer = newBuffer;
|
||||
}
|
||||
System.arraycopy(values, 0, buffer, position, values.length);
|
||||
position += values.length;
|
||||
}
|
||||
|
||||
// Implementation of XInputStream
|
||||
|
||||
private void _check() throws com.sun.star.io.NotConnectedException, com.sun.star.io.IOException {
|
||||
if(closed) {
|
||||
throw new com.sun.star.io.IOException("input closed");
|
||||
}
|
||||
}
|
||||
|
||||
public int available() throws com.sun.star.io.NotConnectedException, com.sun.star.io.IOException {
|
||||
_check();
|
||||
return position - readPosition;
|
||||
}
|
||||
|
||||
public void closeInput() throws com.sun.star.io.NotConnectedException, com.sun.star.io.IOException {
|
||||
closed = true;
|
||||
}
|
||||
|
||||
public int readBytes(byte[][] values, int param) throws com.sun.star.io.NotConnectedException, com.sun.star.io.BufferSizeExceededException, com.sun.star.io.IOException {
|
||||
_check();
|
||||
try {
|
||||
int remain = (int)(position - readPosition);
|
||||
if (param > remain) param = remain;
|
||||
/* ARGH!!! */
|
||||
if (values[0] == null){
|
||||
values[0] = new byte[param];
|
||||
// System.err.println("allocated new buffer of "+param+" bytes");
|
||||
}
|
||||
System.arraycopy(buffer, readPosition, values[0], 0, param);
|
||||
// System.err.println("readbytes() -> "+param);
|
||||
readPosition += param;
|
||||
return param;
|
||||
} catch (ArrayIndexOutOfBoundsException ae) {
|
||||
// System.err.println("readbytes() -> ArrayIndexOutOfBounds");
|
||||
ae.printStackTrace();
|
||||
throw new com.sun.star.io.BufferSizeExceededException("buffer overflow");
|
||||
} catch (Exception e) {
|
||||
// System.err.println("readbytes() -> Exception: "+e.getMessage());
|
||||
e.printStackTrace();
|
||||
throw new com.sun.star.io.IOException("error accessing buffer");
|
||||
}
|
||||
}
|
||||
|
||||
public int readSomeBytes(byte[][] values, int param) throws com.sun.star.io.NotConnectedException, com.sun.star.io.BufferSizeExceededException, com.sun.star.io.IOException {
|
||||
// System.err.println("readSomebytes()");
|
||||
return readBytes(values, param);
|
||||
}
|
||||
|
||||
public void skipBytes(int param) throws com.sun.star.io.NotConnectedException, com.sun.star.io.BufferSizeExceededException, com.sun.star.io.IOException {
|
||||
// System.err.println("skipBytes("+param+")");
|
||||
_check();
|
||||
if (param > (position - readPosition))
|
||||
throw new com.sun.star.io.BufferSizeExceededException("buffer overflow");
|
||||
readPosition += param;
|
||||
}
|
||||
|
||||
|
||||
// Implementation of XSeekable
|
||||
|
||||
public long getLength() throws com.sun.star.io.IOException {
|
||||
// System.err.println("getLength() -> "+m_length);
|
||||
if (buffer != null) return position;
|
||||
else throw new com.sun.star.io.IOException("no bytes");
|
||||
}
|
||||
|
||||
public long getPosition() throws com.sun.star.io.IOException {
|
||||
// System.err.println("getPosition() -> "+m_pos);
|
||||
if (buffer != null) return readPosition;
|
||||
else throw new com.sun.star.io.IOException("no bytes");
|
||||
}
|
||||
|
||||
public void seek(long param) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.io.IOException {
|
||||
// System.err.println("seek("+param+")");
|
||||
if (buffer != null) {
|
||||
if (param < 0 || param > position) throw new com.sun.star.lang.IllegalArgumentException("invalid seek position");
|
||||
else readPosition = (int)param;
|
||||
} else throw new com.sun.star.io.IOException("no bytes");
|
||||
}
|
||||
|
||||
// Implementation of XStream
|
||||
public XInputStream getInputStream() { return this; }
|
||||
|
||||
public XOutputStream getOutputStream() { return this; }
|
||||
|
||||
// Get the buffer
|
||||
public byte[] getBuffer() { return buffer; }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,504 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ExportFilterBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-24)
|
||||
*
|
||||
*/
|
||||
|
||||
// This file was originally based on OOo's XMergeBridge, which is (c) by Sun Microsystems
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
import com.sun.star.lib.uno.adapter.XInputStreamToInputStreamAdapter;
|
||||
import com.sun.star.lib.uno.adapter.XOutputStreamToOutputStreamAdapter;
|
||||
|
||||
//import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.io.XInputStream;
|
||||
import com.sun.star.io.XOutputStream;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XServiceName;
|
||||
import com.sun.star.lang.XTypeProvider;
|
||||
import com.sun.star.uno.AnyConverter;
|
||||
import com.sun.star.ucb.XSimpleFileAccess2;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
//import com.sun.star.xml.sax.InputSource;
|
||||
//import com.sun.star.xml.sax.XParser;
|
||||
import com.sun.star.xml.sax.XDocumentHandler;
|
||||
import com.sun.star.xml.XExportFilter;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.MessageBox;
|
||||
//import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
import writer2latex.api.Converter;
|
||||
import writer2latex.api.ConverterFactory;
|
||||
import writer2latex.api.ConverterResult;
|
||||
import writer2latex.api.OutputFile;
|
||||
|
||||
import java.util.Iterator;
|
||||
//import java.util.Enumeration;
|
||||
//import java.util.Vector;
|
||||
import java.io.*;
|
||||
//import javax.xml.parsers.*;
|
||||
//import org.xml.sax.SAXException;
|
||||
//import java.net.URI;
|
||||
|
||||
|
||||
/** This class provides an abstract uno component which implements an XExportFilter.
|
||||
* The filter is actually generic and only then constructor and 3 strings needs
|
||||
* to changed by the subclass.
|
||||
*/
|
||||
public abstract class ExportFilterBase implements
|
||||
XExportFilter,
|
||||
XServiceName,
|
||||
XServiceInfo,
|
||||
XDocumentHandler,
|
||||
XTypeProvider {
|
||||
|
||||
/** Service name for the component */
|
||||
public static final String __serviceName = "";
|
||||
|
||||
/** Implementation name for the component */
|
||||
public static final String __implementationName = "";
|
||||
|
||||
/** Filter name to include in error messages */
|
||||
public static final String __displayName = "";
|
||||
|
||||
private static XComponentContext xComponentContext = null;
|
||||
protected static XMultiServiceFactory xMSF;
|
||||
private static XInputStream xInStream =null;
|
||||
private static XOutputStream xOutStream=null;
|
||||
private static XOutputStream xos = null;
|
||||
private static String sdMime=null;
|
||||
private static String sURL="";
|
||||
|
||||
private Object filterData;
|
||||
private XSimpleFileAccess2 sfa2;
|
||||
|
||||
|
||||
/** We need to get the Service Manager from the Component context to
|
||||
* instantiate certain services, hence this constructor.
|
||||
* The subclass must override this to set xMSF properly from the reigstration class
|
||||
*/
|
||||
public ExportFilterBase(XComponentContext xComponentContext1) {
|
||||
xComponentContext = xComponentContext1;
|
||||
xMSF = null;
|
||||
}
|
||||
|
||||
|
||||
// Some utility methods:
|
||||
|
||||
String getFileName(String origName) {
|
||||
String name=null;
|
||||
if (origName !=null) {
|
||||
if(origName.equalsIgnoreCase(""))
|
||||
name = "OutFile";
|
||||
else {
|
||||
if (origName.lastIndexOf("/")>=0) {
|
||||
origName=origName.substring(origName.lastIndexOf("/")+1,origName.length());
|
||||
}
|
||||
if (origName.lastIndexOf(".")>=0) {
|
||||
name = origName.substring(0,(origName.lastIndexOf(".")));
|
||||
}
|
||||
else {
|
||||
name=origName;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
name = "OutFile";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public String replace(String origString, String origChar, String replaceChar){
|
||||
String tmp="";
|
||||
int index=origString.indexOf(origChar);
|
||||
if(index !=-1){
|
||||
while (index !=-1){
|
||||
String first =origString.substring(0,index);
|
||||
first=first.concat(replaceChar);
|
||||
tmp=tmp.concat(first);
|
||||
origString=origString.substring(index+1,origString.length());
|
||||
index=origString.indexOf(origChar);
|
||||
if(index==-1) {
|
||||
tmp=tmp.concat(origString);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public String needsMask(String origString) {
|
||||
if (origString.indexOf("&")!=-1){
|
||||
origString=replace(origString,"&","&");
|
||||
}
|
||||
if (origString.indexOf("\"")!=-1){
|
||||
origString=replace(origString,"\"",""");
|
||||
}
|
||||
if (origString.indexOf("<")!=-1){
|
||||
origString=replace(origString,"<","<");
|
||||
}
|
||||
if (origString.indexOf(">")!=-1){
|
||||
origString=replace(origString,">",">");
|
||||
}
|
||||
return origString;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Implementation of XExportFilter:
|
||||
|
||||
public boolean exporter(com.sun.star.beans.PropertyValue[] aSourceData,
|
||||
java.lang.String[] msUserData) throws com.sun.star.uno.RuntimeException{
|
||||
|
||||
sURL=null;
|
||||
filterData = null;
|
||||
|
||||
// Get user data from configuration (type detection)
|
||||
//String udConvertClass=msUserData[0];
|
||||
//String udImport =msUserData[2];
|
||||
//String udExport =msUserData[3];
|
||||
sdMime = msUserData[5];
|
||||
|
||||
// Get source data (only the OutputStream and the URL are actually used)
|
||||
com.sun.star.beans.PropertyValue[] pValue = aSourceData;
|
||||
for (int i = 0 ; i < pValue.length; i++) {
|
||||
try{
|
||||
if (pValue[i].Name.compareTo("OutputStream")==0){
|
||||
xos=(com.sun.star.io.XOutputStream)AnyConverter.toObject(new Type(com.sun.star.io.XOutputStream.class), pValue[i].Value);
|
||||
}
|
||||
//if (pValue[i].Name.compareTo("FileName")==0){
|
||||
// sFileName=(String)AnyConverter.toObject(new Type(java.lang.String.class), pValue[i].Value);
|
||||
//}
|
||||
if (pValue[i].Name.compareTo("URL")==0){
|
||||
sURL=(String)AnyConverter.toObject(new Type(java.lang.String.class), pValue[i].Value);
|
||||
}
|
||||
//if (pValue[i].Name.compareTo("Title")==0){
|
||||
// title=(String)AnyConverter.toObject(new Type(java.lang.String.class), pValue[i].Value);
|
||||
//}
|
||||
if (pValue[i].Name.compareTo("FilterData")==0) {
|
||||
filterData = pValue[i].Value;
|
||||
}
|
||||
}
|
||||
catch(com.sun.star.lang.IllegalArgumentException AnyExec){
|
||||
System.err.println("\nIllegalArgumentException "+AnyExec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sURL==null){
|
||||
sURL="";
|
||||
}
|
||||
|
||||
// Create a pipe to be used by the XDocumentHandler implementation:
|
||||
try {
|
||||
Object xPipeObj=xMSF.createInstance("com.sun.star.io.Pipe");
|
||||
xInStream = (XInputStream) UnoRuntime.queryInterface(
|
||||
XInputStream.class , xPipeObj );
|
||||
xOutStream = (XOutputStream) UnoRuntime.queryInterface(
|
||||
XOutputStream.class , xPipeObj );
|
||||
}
|
||||
catch (Exception e){
|
||||
System.err.println("Exception "+e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Implementation of XDocumentHandler:
|
||||
// Flat xml is created by the sax events and passed through the pipe
|
||||
// created by exporter()
|
||||
|
||||
public void startDocument () {
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
public void endDocument()throws com.sun.star.uno.RuntimeException {
|
||||
try{
|
||||
xOutStream.closeOutput();
|
||||
convert(xInStream,xos);
|
||||
}
|
||||
catch (IOException e){
|
||||
MessageBox msgBox = new MessageBox(xComponentContext);
|
||||
msgBox.showMessage(__displayName+": IO error in conversion",
|
||||
e.toString()+" at "+e.getStackTrace()[0].toString());
|
||||
throw new com.sun.star.uno.RuntimeException(e.getMessage());
|
||||
}
|
||||
catch (Exception e){
|
||||
MessageBox msgBox = new MessageBox(xComponentContext);
|
||||
msgBox.showMessage(__displayName+": Internal error in conversion",
|
||||
e.toString()+" at "+e.getStackTrace()[0].toString());
|
||||
throw new com.sun.star.uno.RuntimeException(__displayName+" Exception");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void startElement (String str, com.sun.star.xml.sax.XAttributeList xattribs)
|
||||
{
|
||||
|
||||
str="<".concat(str);
|
||||
if (xattribs !=null)
|
||||
{
|
||||
str= str.concat(" ");
|
||||
int len=xattribs.getLength();
|
||||
for (short i=0;i<len;i++)
|
||||
{
|
||||
str=str.concat(xattribs.getNameByIndex(i));
|
||||
str=str.concat("=\"");
|
||||
str=str.concat(needsMask(xattribs.getValueByIndex(i)));
|
||||
str=str.concat("\" ");
|
||||
}
|
||||
}
|
||||
str=str.concat(">");
|
||||
try{
|
||||
xOutStream.writeBytes(str.getBytes("UTF-8"));
|
||||
}
|
||||
catch (Exception e){
|
||||
System.err.println("\n"+e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void endElement(String str){
|
||||
|
||||
str="</".concat(str);
|
||||
str=str.concat(">");
|
||||
try{
|
||||
xOutStream.writeBytes(str.getBytes("UTF-8"));
|
||||
|
||||
}
|
||||
catch (Exception e){
|
||||
System.err.println("\n"+e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public void characters(String str){
|
||||
str=needsMask(str);
|
||||
try{
|
||||
xOutStream.writeBytes(str.getBytes("UTF-8"));
|
||||
}
|
||||
catch (Exception e){
|
||||
System.err.println("\n"+e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void ignorableWhitespace(String str){
|
||||
|
||||
|
||||
}
|
||||
public void processingInstruction(String aTarget, String aData){
|
||||
|
||||
}
|
||||
|
||||
public void setDocumentLocator(com.sun.star.xml.sax.XLocator xLocator){
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This is the actual conversion method, using Writer2LaTeX to convert
|
||||
// the flat xml recieved from the XInputStream, and writing the result
|
||||
// to the XOutputStream. The XMLExporter does not support export to
|
||||
// compound documents with multiple output files; so the main file
|
||||
// is written to the XOutStream and other files are written using ucb.
|
||||
|
||||
public void convert (com.sun.star.io.XInputStream xml,com.sun.star.io.XOutputStream exportStream)
|
||||
throws com.sun.star.uno.RuntimeException, IOException {
|
||||
|
||||
// Initialise the file access
|
||||
sfa2 = null;
|
||||
try {
|
||||
Object sfaObject = xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.ucb.SimpleFileAccess", xComponentContext);
|
||||
sfa2 = (XSimpleFileAccess2) UnoRuntime.queryInterface(XSimpleFileAccess2.class, sfaObject);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// failed to get SimpleFileAccess service (should not happen)
|
||||
}
|
||||
|
||||
// Get base name from the url provided by OOo
|
||||
String sName= getFileName(sURL);
|
||||
|
||||
// Adapter for input stream (OpenDocument flat xml)
|
||||
XInputStreamToInputStreamAdapter xis =new XInputStreamToInputStreamAdapter(xml);
|
||||
|
||||
// Adapter for output stream (Main output file)
|
||||
XOutputStreamToOutputStreamAdapter newxos =new XOutputStreamToOutputStreamAdapter(exportStream);
|
||||
|
||||
// Create converter
|
||||
Converter converter = ConverterFactory.createConverter(sdMime);
|
||||
if (converter==null) {
|
||||
throw new com.sun.star.uno.RuntimeException("Failed to create converter to "+sdMime);
|
||||
}
|
||||
|
||||
// Apply the FilterData to the converter
|
||||
if (filterData!=null) {
|
||||
FilterDataParser fdp = new FilterDataParser(xComponentContext);
|
||||
fdp.applyFilterData(filterData,converter);
|
||||
}
|
||||
|
||||
// Do conversion
|
||||
converter.setGraphicConverter(new GraphicConverterImpl(xComponentContext));
|
||||
|
||||
ConverterResult dataOut = null;
|
||||
try {
|
||||
dataOut = converter.convert(xis,sName);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// Fail silently
|
||||
}
|
||||
|
||||
// Write out files
|
||||
Iterator docEnum = dataOut.iterator();
|
||||
|
||||
// Remove the file name part of the url
|
||||
String sNewURL = null;
|
||||
if (sURL.lastIndexOf("/")>-1) {
|
||||
// Take the url up to and including the last slash
|
||||
sNewURL = sURL.substring(0,sURL.lastIndexOf("/")+1);
|
||||
}
|
||||
else {
|
||||
// The url does not include a path; this should not really happen,
|
||||
// but in this case we will write to the current default directory
|
||||
sNewURL = "";
|
||||
}
|
||||
|
||||
while (docEnum.hasNext() && sURL.startsWith("file:")) {
|
||||
OutputFile docOut = (OutputFile)docEnum.next();
|
||||
|
||||
if (dataOut.getMasterDocument()==docOut) {
|
||||
// The master document is written to the XOutStream supplied
|
||||
// by the XMLFilterAdaptor
|
||||
docOut.write(newxos);
|
||||
newxos.flush();
|
||||
newxos.close();
|
||||
}
|
||||
else {
|
||||
// Additional documents are written directly using ucb
|
||||
|
||||
// Get the file name and the (optional) directory name
|
||||
String sFullFileName = docOut.getFileName();
|
||||
String sDirName = "";
|
||||
String sFileName = sFullFileName;
|
||||
int nSlash = sFileName.indexOf("/");
|
||||
if (nSlash>-1) {
|
||||
sDirName = sFileName.substring(0,nSlash);
|
||||
sFileName = sFileName.substring(nSlash+1);
|
||||
}
|
||||
|
||||
try{
|
||||
// Create subdirectory if required
|
||||
if (sDirName.length()>0 && !sfa2.exists(sNewURL+sDirName)) {
|
||||
sfa2.createFolder(sNewURL+sDirName);
|
||||
}
|
||||
|
||||
// writeFile demands an InputStream, so we need a pipe
|
||||
Object xPipeObj=xMSF.createInstance("com.sun.star.io.Pipe");
|
||||
XInputStream xInStream
|
||||
= (XInputStream) UnoRuntime.queryInterface(XInputStream.class, xPipeObj );
|
||||
XOutputStream xOutStream
|
||||
= (XOutputStream) UnoRuntime.queryInterface(XOutputStream.class, xPipeObj );
|
||||
OutputStream outStream = new XOutputStreamToOutputStreamAdapter(xOutStream);
|
||||
// Feed the pipe with content...
|
||||
docOut.write(outStream);
|
||||
outStream.flush();
|
||||
outStream.close();
|
||||
xOutStream.closeOutput();
|
||||
// ...and then write the content to the url
|
||||
sfa2.writeFile(sNewURL+sFullFileName,xInStream);
|
||||
}
|
||||
catch (Throwable e){
|
||||
MessageBox msgBox = new MessageBox(xComponentContext);
|
||||
msgBox.showMessage(__displayName+": Error writing files",
|
||||
e.toString()+" at "+e.getStackTrace()[0].toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Implement methods from interface XTypeProvider
|
||||
// Implementation of XTypeProvider
|
||||
|
||||
public com.sun.star.uno.Type[] getTypes() {
|
||||
Type[] typeReturn = {};
|
||||
|
||||
try {
|
||||
typeReturn = new Type[] {
|
||||
new Type( XTypeProvider.class ),
|
||||
new Type( XExportFilter.class ),
|
||||
new Type( XServiceName.class ),
|
||||
new Type( XServiceInfo.class ) };
|
||||
}
|
||||
catch( Exception exception ) {
|
||||
|
||||
}
|
||||
|
||||
return( typeReturn );
|
||||
}
|
||||
|
||||
|
||||
public byte[] getImplementationId() {
|
||||
byte[] byteReturn = {};
|
||||
|
||||
byteReturn = new String( "" + this.hashCode() ).getBytes();
|
||||
|
||||
return( byteReturn );
|
||||
}
|
||||
|
||||
// Implement method from interface XServiceName
|
||||
public String getServiceName() {
|
||||
return( __serviceName );
|
||||
}
|
||||
|
||||
// Implement methods from interface XServiceInfo
|
||||
public boolean supportsService(String stringServiceName) {
|
||||
return( stringServiceName.equals( __serviceName ) );
|
||||
}
|
||||
|
||||
public String getImplementationName() {
|
||||
return __implementationName;
|
||||
//return( W2LExportFilter.class.getName() );
|
||||
}
|
||||
|
||||
public String[] getSupportedServiceNames() {
|
||||
String[] stringSupportedServiceNames = { __serviceName };
|
||||
return( stringSupportedServiceNames );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* FilterDataParser.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.io.NotConnectedException;
|
||||
import com.sun.star.io.XInputStream;
|
||||
import com.sun.star.io.XOutputStream;
|
||||
import com.sun.star.ucb.CommandAbortedException;
|
||||
import com.sun.star.ucb.XSimpleFileAccess2;
|
||||
import com.sun.star.uno.AnyConverter;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.util.XStringSubstitution;
|
||||
|
||||
import com.sun.star.lib.uno.adapter.XInputStreamToInputStreamAdapter;
|
||||
import com.sun.star.lib.uno.adapter.XOutputStreamToOutputStreamAdapter;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
import writer2latex.api.Converter;
|
||||
|
||||
|
||||
/** This class parses the FilterData property passed to the filter and
|
||||
* applies it to a <code>Converter</code>
|
||||
* All errors are silently ignored
|
||||
*/
|
||||
public class FilterDataParser {
|
||||
|
||||
//private static XComponentContext xComponentContext = null;
|
||||
|
||||
private XSimpleFileAccess2 sfa2;
|
||||
private XStringSubstitution xPathSub;
|
||||
|
||||
public FilterDataParser(XComponentContext xComponentContext) {
|
||||
//this.xComponentContext = xComponentContext;
|
||||
|
||||
// Get the SimpleFileAccess service
|
||||
sfa2 = null;
|
||||
try {
|
||||
Object sfaObject = xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.ucb.SimpleFileAccess", xComponentContext);
|
||||
sfa2 = (XSimpleFileAccess2) UnoRuntime.queryInterface(XSimpleFileAccess2.class, sfaObject);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// failed to get SimpleFileAccess service (should not happen)
|
||||
}
|
||||
|
||||
// Get the PathSubstitution service
|
||||
xPathSub = null;
|
||||
try {
|
||||
Object psObject = xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.util.PathSubstitution", xComponentContext);
|
||||
xPathSub = (XStringSubstitution) UnoRuntime.queryInterface(XStringSubstitution.class, psObject);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// failed to get PathSubstitution service (should not happen)
|
||||
}
|
||||
}
|
||||
|
||||
/** Apply the given FilterData property to the given converter
|
||||
* @param data an Any containing the FilterData property
|
||||
* @param converter a <code>writer2latex.api.Converter</code> implementation
|
||||
*/
|
||||
public void applyFilterData(Object data, Converter converter) {
|
||||
// Get the array from the data, if possible
|
||||
PropertyValue[] filterData = null;
|
||||
if (AnyConverter.isArray(data)) {
|
||||
try {
|
||||
Object[] arrayData = (Object[]) AnyConverter.toArray(data);
|
||||
if (arrayData instanceof PropertyValue[]) {
|
||||
filterData = (PropertyValue[]) arrayData;
|
||||
}
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
// Failed to convert to array; should not happen - ignore
|
||||
}
|
||||
}
|
||||
if (filterData==null) { return; }
|
||||
|
||||
PropertyHelper props = new PropertyHelper(filterData);
|
||||
|
||||
// Get the special properties TemplateURL, ConfigURL and AutoCreate
|
||||
Object tpl = props.get("TemplateURL");
|
||||
String sTemplate = null;
|
||||
if (tpl!=null && AnyConverter.isString(tpl)) {
|
||||
try {
|
||||
sTemplate = substituteVariables(AnyConverter.toString(tpl));
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
// Failed to convert to String; should not happen - ignore
|
||||
}
|
||||
}
|
||||
|
||||
Object auto = props.get("AutoCreate");
|
||||
boolean bAutoCreate = false;
|
||||
if (auto!=null && AnyConverter.isString(auto)) {
|
||||
try {
|
||||
if ("true".equals(AnyConverter.toString(auto))) {
|
||||
bAutoCreate = true;
|
||||
}
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
// Failed to convert to String; should not happen - ignore
|
||||
}
|
||||
}
|
||||
|
||||
Object cfg = props.get("ConfigURL");
|
||||
String sConfig = null;
|
||||
if (cfg!=null && AnyConverter.isString(cfg)) {
|
||||
try {
|
||||
sConfig = substituteVariables(AnyConverter.toString(cfg));
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
// Failed to convert to String; should not happen - ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Load the template from the specified URL, if any
|
||||
if (sfa2!=null && sTemplate!=null && sTemplate.length()>0) {
|
||||
try {
|
||||
XInputStream xIs = sfa2.openFileRead(sTemplate);
|
||||
if (xIs!=null) {
|
||||
InputStream is = new XInputStreamToInputStreamAdapter(xIs);
|
||||
converter.readTemplate(is);
|
||||
is.close();
|
||||
xIs.closeInput();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (NotConnectedException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Create config if required
|
||||
try {
|
||||
if (bAutoCreate && sfa2!=null && sConfig!=null && !sConfig.startsWith("*") && !sfa2.exists(sConfig)) {
|
||||
// Note: Requires random access, ie. must be a file URL:
|
||||
XOutputStream xOs = sfa2.openFileWrite(sConfig);
|
||||
if (xOs!=null) {
|
||||
OutputStream os = new XOutputStreamToOutputStreamAdapter(xOs);
|
||||
converter.getConfig().write(os);
|
||||
os.flush();
|
||||
os.close();
|
||||
xOs.closeOutput();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (NotConnectedException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// Ignore
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
// Load the configuration from the specified URL, if any
|
||||
if (sConfig!=null) {
|
||||
if (sConfig.startsWith("*")) { // internal configuration
|
||||
try {
|
||||
converter.getConfig().readDefaultConfig(sConfig.substring(1));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
else if (sfa2!=null) { // real URL
|
||||
try {
|
||||
XInputStream xIs = sfa2.openFileRead(sConfig);;
|
||||
if (xIs!=null) {
|
||||
InputStream is = new XInputStreamToInputStreamAdapter(xIs);
|
||||
converter.getConfig().read(is);
|
||||
is.close();
|
||||
xIs.closeInput();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
catch (NotConnectedException e) {
|
||||
// Ignore
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// Ignore
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read further configuration properties
|
||||
Enumeration keys = props.keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
String sKey = (String) keys.nextElement();
|
||||
if (!"ConfigURL".equals(sKey) && !"TemplateURL".equals(sKey) && !"AutoCreate".equals(sKey)) {
|
||||
Object value = props.get(sKey);
|
||||
if (AnyConverter.isString(value)) {
|
||||
try {
|
||||
converter.getConfig().setOption(sKey,AnyConverter.toString(value));
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
// Failed to convert to String; should not happen - ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String substituteVariables(String sUrl) {
|
||||
if (xPathSub!=null) {
|
||||
try {
|
||||
return xPathSub.substituteVariables(sUrl, false);
|
||||
}
|
||||
catch (com.sun.star.container.NoSuchElementException e) {
|
||||
// Found an unknown variable, no substitution
|
||||
// (This will only happen if false is replaced by true above)
|
||||
return sUrl;
|
||||
}
|
||||
}
|
||||
else { // Not path substitution available
|
||||
return sUrl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* GraphicConverterImpl.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import writer2latex.api.GraphicConverter;
|
||||
|
||||
public class GraphicConverterImpl implements GraphicConverter {
|
||||
|
||||
private GraphicConverter graphicConverter1;
|
||||
private GraphicConverter graphicConverter2;
|
||||
|
||||
public GraphicConverterImpl(XComponentContext xComponentContext) {
|
||||
graphicConverter1 = new GraphicConverterImpl1(xComponentContext);
|
||||
graphicConverter2 = new GraphicConverterImpl2(xComponentContext);
|
||||
}
|
||||
|
||||
public boolean supportsConversion(String sSourceMime, String sTargetMime, boolean bCrop, boolean bResize) {
|
||||
return graphicConverter1.supportsConversion(sSourceMime, sTargetMime, bCrop, bResize) ||
|
||||
graphicConverter2.supportsConversion(sSourceMime, sTargetMime, bCrop, bResize);
|
||||
}
|
||||
|
||||
public byte[] convert(byte[] source, String sSourceMime, String sTargetMime) {
|
||||
byte[] result = null;
|
||||
|
||||
// Prefer the simple implementation (GraphicProvider)
|
||||
if (graphicConverter1.supportsConversion(sSourceMime, sTargetMime, false, false)) {
|
||||
result = graphicConverter1.convert(source, sSourceMime, sTargetMime);
|
||||
}
|
||||
|
||||
// If this is not possible or fails, try the complex implementation
|
||||
if (result==null) {
|
||||
result = graphicConverter2.convert(source, sSourceMime, sTargetMime);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* GraphicConverterImpl1.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
// Version 1.0 (2008-11-22)
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
// Java uno helper class
|
||||
import com.sun.star.lib.uno.adapter.ByteArrayToXInputStreamAdapter;
|
||||
|
||||
// UNO classes
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.graphic.XGraphic;
|
||||
import com.sun.star.graphic.XGraphicProvider;
|
||||
//import com.sun.star.io.XInputStream;
|
||||
//import com.sun.star.io.XOutputStream;
|
||||
import com.sun.star.lang.XMultiComponentFactory;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
|
||||
import writer2latex.api.GraphicConverter;
|
||||
import writer2latex.api.MIMETypes;
|
||||
|
||||
/** A GraphicConverter implementation which uses the GraphicProvider service
|
||||
* to convert the graphic. This service does only support simple format
|
||||
* conversion using the "internal" graphics filters in Draw. Advanced features
|
||||
* like pdf, crop and resize thus cannot be handled.
|
||||
*/
|
||||
public class GraphicConverterImpl1 implements GraphicConverter {
|
||||
|
||||
// Signatures for start and end in exp
|
||||
private byte[] psStart;
|
||||
private byte[] psEnd;
|
||||
|
||||
|
||||
private XGraphicProvider xGraphicProvider;
|
||||
|
||||
public GraphicConverterImpl1(XComponentContext xComponentContext) {
|
||||
try {
|
||||
// Get the XGraphicProvider interface of the GraphicProvider service
|
||||
XMultiComponentFactory xMCF = xComponentContext.getServiceManager();
|
||||
Object graphicProviderObject = xMCF.createInstanceWithContext("com.sun.star.graphic.GraphicProvider", xComponentContext);
|
||||
xGraphicProvider = (XGraphicProvider) UnoRuntime.queryInterface(XGraphicProvider.class, graphicProviderObject);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception ex) {
|
||||
System.err.println("Failed to get XGraphicProvider object");
|
||||
xGraphicProvider = null;
|
||||
}
|
||||
try {
|
||||
psStart = "%!PS-Adobe".getBytes("US-ASCII");
|
||||
psEnd = "%%EOF".getBytes("US-ASCII");
|
||||
}
|
||||
catch (java.io.UnsupportedEncodingException ex) {
|
||||
// US-ASCII *is* supported :-)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean supportsConversion(String sSourceMime, String sTargetMime, boolean bCrop, boolean bResize) {
|
||||
// We don't support cropping and resizing
|
||||
if (bCrop || bResize) { return false; }
|
||||
|
||||
// We can convert vector formats to eps:
|
||||
if (MIMETypes.EPS.equals(sTargetMime) && (MIMETypes.WMF.equals(sSourceMime) && MIMETypes.SVM.equals(sSourceMime))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// And we can convert all formats to bitmaps
|
||||
boolean bSupportsSource =
|
||||
MIMETypes.PNG.equals(sSourceMime) || MIMETypes.JPEG.equals(sSourceMime) ||
|
||||
MIMETypes.GIF.equals(sSourceMime) || MIMETypes.TIFF.equals(sSourceMime) ||
|
||||
MIMETypes.BMP.equals(sSourceMime) || MIMETypes.WMF.equals(sSourceMime) ||
|
||||
MIMETypes.SVM.equals(sSourceMime);
|
||||
boolean bSupportsTarget =
|
||||
MIMETypes.PNG.equals(sTargetMime) || MIMETypes.JPEG.equals(sTargetMime) ||
|
||||
MIMETypes.GIF.equals(sTargetMime) || MIMETypes.TIFF.equals(sTargetMime) ||
|
||||
MIMETypes.BMP.equals(sTargetMime);
|
||||
return bSupportsSource && bSupportsTarget;
|
||||
}
|
||||
|
||||
public byte[] convert(byte[] source, String sSourceMime, String sTargetMime) {
|
||||
|
||||
// It seems that the GraphicProvider can only create proper eps if
|
||||
// the source is a vector format, hence
|
||||
if (MIMETypes.EPS.equals(sTargetMime)) {
|
||||
if (!MIMETypes.WMF.equals(sSourceMime) && !MIMETypes.SVM.equals(sSourceMime)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
ByteArrayToXInputStreamAdapter xSource = new ByteArrayToXInputStreamAdapter(source);
|
||||
ByteArrayXStream xTarget = new ByteArrayXStream();
|
||||
try {
|
||||
// Read the source
|
||||
PropertyValue[] sourceProps = new PropertyValue[1];
|
||||
sourceProps[0] = new PropertyValue();
|
||||
sourceProps[0].Name = "InputStream";
|
||||
sourceProps[0].Value = xSource;
|
||||
XGraphic result = xGraphicProvider.queryGraphic(sourceProps);
|
||||
|
||||
// Store as new type
|
||||
PropertyValue[] targetProps = new PropertyValue[2];
|
||||
targetProps[0] = new PropertyValue();
|
||||
targetProps[0].Name = "MimeType";
|
||||
targetProps[0].Value = sTargetMime;
|
||||
targetProps[1] = new PropertyValue();
|
||||
targetProps[1].Name = "OutputStream";
|
||||
targetProps[1].Value = xTarget;
|
||||
xGraphicProvider.storeGraphic(result,targetProps);
|
||||
|
||||
|
||||
// Close the output and return the result
|
||||
xTarget.closeOutput();
|
||||
xTarget.flush();
|
||||
if (MIMETypes.EPS.equals(sTargetMime)) {
|
||||
return cleanEps(xTarget.getBuffer());
|
||||
}
|
||||
else {
|
||||
return xTarget.getBuffer();
|
||||
}
|
||||
}
|
||||
catch (com.sun.star.io.IOException e) {
|
||||
return null;
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
catch (com.sun.star.lang.WrappedTargetException e) {
|
||||
return null;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] cleanEps(byte[] blob) {
|
||||
int n = blob.length;
|
||||
|
||||
int nStart = 0;
|
||||
for (int i=0; i<n; i++) {
|
||||
if (match(blob,psStart,i)) {
|
||||
nStart=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int nEnd = n;
|
||||
for (int i=nStart; i<n; i++) {
|
||||
if (match(blob,psEnd,i)) {
|
||||
nEnd=i+psEnd.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] newBlob = new byte[nEnd-nStart];
|
||||
System.arraycopy(blob,nStart,newBlob,0,nEnd-nStart);
|
||||
return newBlob;
|
||||
}
|
||||
|
||||
private boolean match(byte[] blob, byte[] sig, int nStart) {
|
||||
int n = sig.length;
|
||||
if (nStart+n>=blob.length) { return false; }
|
||||
for (int i=0; i<n; i++) {
|
||||
if (blob[nStart+i]!=sig[i]) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* GraphicConverterImpl2.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-07)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import com.sun.star.awt.Point;
|
||||
import com.sun.star.awt.Size;
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.drawing.XDrawPage;
|
||||
import com.sun.star.drawing.XDrawPages;
|
||||
import com.sun.star.drawing.XDrawPagesSupplier;
|
||||
import com.sun.star.drawing.XShape;
|
||||
import com.sun.star.frame.XComponentLoader;
|
||||
import com.sun.star.frame.XStorable;
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.lang.XMultiComponentFactory;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.util.XRefreshable;
|
||||
|
||||
import com.sun.star.lib.uno.adapter.ByteArrayToXInputStreamAdapter;
|
||||
import com.sun.star.lib.uno.adapter.XOutputStreamToByteArrayAdapter;
|
||||
|
||||
import writer2latex.api.GraphicConverter;
|
||||
import writer2latex.api.MIMETypes;
|
||||
|
||||
/** A GraphicConverter implementation which uses a hidden Draw document to
|
||||
* store the graphic, providing more control over the image than the
|
||||
* simple GraphicProvider implementation.
|
||||
*/
|
||||
public class GraphicConverterImpl2 implements GraphicConverter {
|
||||
|
||||
private XComponentContext xComponentContext;
|
||||
private Hashtable importFilter;
|
||||
private Hashtable exportFilter;
|
||||
|
||||
public GraphicConverterImpl2(XComponentContext xComponentContext) {
|
||||
this.xComponentContext = xComponentContext;
|
||||
|
||||
importFilter = new Hashtable();
|
||||
importFilter.put(MIMETypes.BMP, "BMP - MS Windows");
|
||||
//importFilter.put(MIMETypes.EMF, "EMF - MS Windows Metafile");
|
||||
importFilter.put(MIMETypes.EPS, "EPS - Encapsulated PostScript");
|
||||
importFilter.put(MIMETypes.GIF, "GIF - Graphics Interchange Format");
|
||||
importFilter.put(MIMETypes.JPEG, "JPG - JPEG");
|
||||
importFilter.put(MIMETypes.PNG, "PNG - Portable Network Graphic");
|
||||
importFilter.put(MIMETypes.SVM, "SVM - StarView Metafile");
|
||||
importFilter.put(MIMETypes.TIFF, "TIF - Tag Image File");
|
||||
importFilter.put(MIMETypes.WMF, "WMF - MS Windows Metafile");
|
||||
|
||||
exportFilter = new Hashtable();
|
||||
exportFilter.put(MIMETypes.BMP,"draw_bmp_Export");
|
||||
//exportFilter.put(MIMETypes.EMF,"draw_emf_Export");
|
||||
exportFilter.put(MIMETypes.EPS,"draw_eps_Export");
|
||||
exportFilter.put(MIMETypes.GIF,"draw_gif_Export");
|
||||
exportFilter.put(MIMETypes.JPEG,"draw_jpg_Export");
|
||||
exportFilter.put(MIMETypes.PNG,"draw_png_Export");
|
||||
//exportFilter.put(MIMETypes.SVG,"draw_svg_Export");
|
||||
exportFilter.put(MIMETypes.SVM,"draw_svm_Export");
|
||||
exportFilter.put(MIMETypes.TIFF,"draw_tif_Export");
|
||||
exportFilter.put(MIMETypes.WMF,"draw_wmf_Export");
|
||||
exportFilter.put(MIMETypes.PDF,"draw_pdf_Export");
|
||||
}
|
||||
|
||||
public boolean supportsConversion(String sSourceMime, String sTargetMime, boolean bCrop, boolean bResize) {
|
||||
// We don't support cropping and resizing
|
||||
if (bCrop || bResize) { return false; }
|
||||
|
||||
// We currently only support conversion of svm into pdf
|
||||
// Trying wmf causes an IllegalArgumentException "URL seems to be an unsupported one"
|
||||
// Seems to be an OOo bug; workaround: Use temporary files..??
|
||||
boolean bSupportsSource = MIMETypes.SVM.equals(sSourceMime);
|
||||
/*MIMETypes.PNG.equals(sSourceMime) || MIMETypes.JPEG.equals(sSourceMime) ||
|
||||
MIMETypes.GIF.equals(sSourceMime) || MIMETypes.TIFF.equals(sSourceMime) ||
|
||||
MIMETypes.BMP.equals(sSourceMime) || MIMETypes.WMF.equals(sSourceMime) ||
|
||||
MIMETypes.SVM.equals(sSourceMime);*/
|
||||
return bSupportsSource && MIMETypes.PDF.equals(sTargetMime);
|
||||
}
|
||||
|
||||
public byte[] convert(byte[] source, String sSourceMime, String sTargetMime) {
|
||||
// Open a hidden sdraw document
|
||||
XMultiComponentFactory xMCF = xComponentContext.getServiceManager();
|
||||
|
||||
org.openoffice.da.comp.w2lcommon.helper.MessageBox msgBox = new org.openoffice.da.comp.w2lcommon.helper.MessageBox(xComponentContext);
|
||||
|
||||
try {
|
||||
// Load the graphic into a new draw document as xDocument
|
||||
// using a named filter
|
||||
Object desktop = xMCF.createInstanceWithContext(
|
||||
"com.sun.star.frame.Desktop", xComponentContext);
|
||||
|
||||
XComponentLoader xComponentLoader = (XComponentLoader)
|
||||
UnoRuntime.queryInterface(XComponentLoader.class, desktop);
|
||||
//msgBox.showMessage("Graphics","Trying to load using filter name "+importFilter.get(sSourceMime));
|
||||
|
||||
PropertyValue[] fileProps = new PropertyValue[3];
|
||||
fileProps[0] = new PropertyValue();
|
||||
fileProps[0].Name = "FilterName";
|
||||
fileProps[0].Value = (String) importFilter.get(sSourceMime);
|
||||
fileProps[1] = new PropertyValue();
|
||||
fileProps[1].Name = "InputStream";
|
||||
fileProps[1].Value = new ByteArrayToXInputStreamAdapter(source);
|
||||
fileProps[2] = new PropertyValue();
|
||||
fileProps[2].Name = "Hidden";
|
||||
fileProps[2].Value = new Boolean(true);
|
||||
|
||||
XComponent xDocument = xComponentLoader.loadComponentFromURL(
|
||||
"private:stream", "_blank", 0, fileProps);
|
||||
|
||||
// Get the first draw page as xDrawPage
|
||||
XDrawPagesSupplier xDrawPagesSupplier = (XDrawPagesSupplier)
|
||||
UnoRuntime.queryInterface(XDrawPagesSupplier.class, xDocument);
|
||||
XDrawPages xDrawPages = xDrawPagesSupplier.getDrawPages();
|
||||
Object drawPage = xDrawPages.getByIndex(0);
|
||||
XDrawPage xDrawPage = (XDrawPage) UnoRuntime.queryInterface(
|
||||
XDrawPage.class, drawPage);
|
||||
|
||||
// Get the shape as xShape
|
||||
Object shape = xDrawPage.getByIndex(0);
|
||||
XShape xShape = (XShape) UnoRuntime.queryInterface(XShape.class, shape);
|
||||
|
||||
// Move the shape to upper left corner of the page
|
||||
Point position = new Point();
|
||||
position.X = 0;
|
||||
position.Y = 0;
|
||||
xShape.setPosition(position);
|
||||
|
||||
// Adjust the page size and margin to the size of the graphic
|
||||
XPropertySet xPageProps = (XPropertySet) UnoRuntime.queryInterface(
|
||||
XPropertySet.class, xDrawPage);
|
||||
Size size = xShape.getSize();
|
||||
xPageProps.setPropertyValue("Width", new Integer(size.Width));
|
||||
xPageProps.setPropertyValue("Height", new Integer(size.Height));
|
||||
xPageProps.setPropertyValue("BorderTop", new Integer(0));
|
||||
xPageProps.setPropertyValue("BorderBottom", new Integer(0));
|
||||
xPageProps.setPropertyValue("BorderLeft", new Integer(0));
|
||||
xPageProps.setPropertyValue("BorderRight", new Integer(0));
|
||||
|
||||
// Export the draw document (xDocument)
|
||||
refreshDocument(xDocument);
|
||||
|
||||
XOutputStreamToByteArrayAdapter outputStream = new XOutputStreamToByteArrayAdapter();
|
||||
|
||||
PropertyValue[] exportProps = new PropertyValue[3];
|
||||
exportProps[0] = new PropertyValue();
|
||||
exportProps[0].Name = "FilterName";
|
||||
exportProps[0].Value = (String) exportFilter.get(sTargetMime);
|
||||
exportProps[1] = new PropertyValue();
|
||||
exportProps[1].Name = "OutputStream";
|
||||
exportProps[1].Value = outputStream;
|
||||
exportProps[2] = new PropertyValue();
|
||||
exportProps[2].Name = "Overwrite";
|
||||
exportProps[2].Value = new Boolean(true);
|
||||
|
||||
XStorable xStore = (XStorable) UnoRuntime.queryInterface (
|
||||
XStorable.class, xDocument);
|
||||
xStore.storeToURL ("private:stream", exportProps);
|
||||
outputStream.closeOutput();
|
||||
|
||||
byte[] result = outputStream.getBuffer();
|
||||
xDocument.dispose();
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
catch (com.sun.star.beans.PropertyVetoException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.beans.UnknownPropertyException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.io.IOException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.lang.IndexOutOfBoundsException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.lang.WrappedTargetException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
|
||||
// Conversion failed, for whatever reason
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
protected void refreshDocument(XComponent document) {
|
||||
XRefreshable refreshable = (XRefreshable) UnoRuntime.queryInterface(XRefreshable.class, document);
|
||||
if (refreshable != null) {
|
||||
refreshable.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Dim SelSize As New com.sun.star.awt.Size
|
||||
SelSize = oGraphic.Size
|
||||
oDrawGraphic.GraphicURL = oGraphic.GraphicURL
|
||||
oDrawGraphic.Size = SelSize
|
||||
oDrawPage.add(oDrawGraphic)
|
||||
oDrawGraphic.GraphicCrop = oGraphic.GraphicCrop
|
||||
oDrawPage.Width = oGraphic.Size.Width
|
||||
oDrawPage.Height = oGraphic.Size.Height
|
||||
Dim aFilterData (1) As new com.sun.star.beans.PropertyValue
|
||||
aFilterData(0).Name = "PixelWidth" '
|
||||
aFilterData(0).Value = oDrawPage.Width/100 * iPixels / 25.40
|
||||
aFilterData(1).Name = "PixelHeight"
|
||||
aFilterData(1).Value = oDrawPage.Height/100 * iPixels / 25.40
|
||||
Export( oDrawPage, sURLImageResized , aFilterData() )
|
||||
On error resume Next
|
||||
oDrawDoc.Close(True)
|
||||
On error goto 0
|
||||
|
||||
SUB Export( xObject, sFileUrl As String, aFilterData )
|
||||
Dim xExporter As Object
|
||||
xExporter = createUnoService( "com.sun.star.drawing.GraphicExportFilter" )
|
||||
xExporter.SetSourceDocument( xObject )
|
||||
Dim aArgs (2) As new com.sun.star.beans.PropertyValue
|
||||
'sFileURL = ConvertToURL(sFileURL)
|
||||
aArgs(0).Name = "FilterName"
|
||||
aArgs(0).Value = "jpg"
|
||||
aArgs(1).Name = "URL"
|
||||
aArgs(1).Value = sFileURL
|
||||
'print sFileURL
|
||||
aArgs(2).Name = "FilterData"
|
||||
aArgs(2).Value = aFilterData
|
||||
xExporter.filter( aArgs() )
|
||||
END SUB*/
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,547 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* OptionsDialogBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-14)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.sun.star.awt.XDialogEventHandler;
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.beans.XPropertyAccess;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.container.XNameAccess;
|
||||
import com.sun.star.document.XDocumentInfoSupplier;
|
||||
import com.sun.star.frame.XDesktop;
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.lang.IllegalArgumentException;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XServiceName;
|
||||
import com.sun.star.lang.XTypeProvider;
|
||||
import com.sun.star.ui.dialogs.XExecutableDialog;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.util.XChangesBatch;
|
||||
import com.sun.star.util.XMacroExpander;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.DialogBase;
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
|
||||
/** This class provides an abstract uno component which implements a filter ui
|
||||
*/
|
||||
public abstract class OptionsDialogBase extends DialogBase implements
|
||||
XPropertyAccess { // Filter ui requires XExecutableDialog + XPropertyAccess
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// The subclass must override the following; and override the
|
||||
// implementation of XDialogEventHandler if needed
|
||||
|
||||
/** Load settings from the registry to the dialog
|
||||
* The subclass must implement this
|
||||
*/
|
||||
protected abstract void loadSettings(XPropertySet xRegistryProps);
|
||||
|
||||
/** Save settings from the dialog to the registry and create FilterData
|
||||
* The subclass must implement this
|
||||
*/
|
||||
protected abstract void saveSettings(XPropertySet xRegistryProps, PropertyHelper filterData);
|
||||
|
||||
/** Return the name of the library containing the dialog
|
||||
*/
|
||||
public abstract String getDialogLibraryName();
|
||||
|
||||
/** Return the name of the dialog within the library
|
||||
*/
|
||||
public abstract String getDialogName();
|
||||
|
||||
/** Return the path to the options in the registry */
|
||||
public abstract String getRegistryPath();
|
||||
|
||||
/** Create a new OptionsDialogBase */
|
||||
public OptionsDialogBase(XComponentContext xContext) {
|
||||
super(xContext);
|
||||
this.xMSF = null; // must be set properly by subclass
|
||||
mediaProps = null;
|
||||
sConfigNames = null;
|
||||
lockedOptions = new HashSet();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Implement some methods required by DialogBase
|
||||
|
||||
/** Initialize the dialog (eg. with settings from the registry)
|
||||
*/
|
||||
public void initialize() {
|
||||
try {
|
||||
// Prepare registry view
|
||||
Object view = getRegistryView(false);
|
||||
XPropertySet xProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,view);
|
||||
|
||||
// Load settings using method from subclass
|
||||
loadSettings(xProps);
|
||||
|
||||
// Dispose the registry view
|
||||
disposeRegistryView(view);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Failed to get registry view
|
||||
}
|
||||
}
|
||||
|
||||
/** Finalize the dialog after execution (eg. save settings to the registry)
|
||||
*/
|
||||
public void finalize() {
|
||||
try {
|
||||
// Prepare registry view
|
||||
Object rwview = getRegistryView(true);
|
||||
XPropertySet xProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,rwview);
|
||||
|
||||
// Save settings and create FilterData using method from subclass
|
||||
PropertyHelper filterData = new PropertyHelper();
|
||||
saveSettings(xProps, filterData);
|
||||
|
||||
// Commit registry changes
|
||||
XChangesBatch xUpdateContext = (XChangesBatch)
|
||||
UnoRuntime.queryInterface(XChangesBatch.class,rwview);
|
||||
try {
|
||||
xUpdateContext.commitChanges();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
// Dispose the registry view
|
||||
disposeRegistryView(rwview);
|
||||
|
||||
// Update the media properties with the FilterData
|
||||
PropertyHelper helper = new PropertyHelper(mediaProps);
|
||||
helper.put("FilterData",filterData.toArray());
|
||||
mediaProps = helper.toArray();
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Failed to get registry view
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Some private global variables
|
||||
|
||||
// The service factory
|
||||
protected XMultiServiceFactory xMSF;
|
||||
|
||||
// The media properties (set/get via XPropertyAccess implementation)
|
||||
private PropertyValue[] mediaProps;
|
||||
|
||||
// Configuration names (stored during execution of dialog)
|
||||
private String[] sConfigNames;
|
||||
|
||||
// Set of locked controls
|
||||
private HashSet lockedOptions;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Some private utility methods
|
||||
|
||||
// Perform macro extansion
|
||||
private String expandMacros(String s) {
|
||||
if (s.startsWith("vnd.sun.star.expand:")) {
|
||||
// The string contains a macro, usually as a result of using %origin% in the registry
|
||||
s = s.substring(20);
|
||||
Object expander = xContext.getValueByName("/singletons/com.sun.star.util.theMacroExpander");
|
||||
XMacroExpander xExpander = (XMacroExpander) UnoRuntime.queryInterface (XMacroExpander.class, expander);
|
||||
try {
|
||||
return xExpander.expandMacros(s);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// Unknown macro name found, proceed and hope for the best
|
||||
return s;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the template name from the document with ui focus
|
||||
private String getTemplateName() {
|
||||
try {
|
||||
// Get current component
|
||||
Object desktop = xContext.getServiceManager()
|
||||
.createInstanceWithContext("com.sun.star.frame.Desktop",xContext);
|
||||
XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class,desktop);
|
||||
XComponent xComponent = xDesktop.getCurrentComponent();
|
||||
|
||||
// Get the document info property set
|
||||
XDocumentInfoSupplier xDocInfoSuppl = (XDocumentInfoSupplier)
|
||||
UnoRuntime.queryInterface(XDocumentInfoSupplier.class, xComponent);
|
||||
Object docInfo = xDocInfoSuppl.getDocumentInfo();
|
||||
XPropertySet xDocInfo = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class, docInfo);
|
||||
|
||||
return getPropertyValueAsString(xDocInfo,"Template");
|
||||
}
|
||||
catch (Exception e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Get a view of the options root in the registry
|
||||
private Object getRegistryView(boolean bUpdate)
|
||||
throws com.sun.star.uno.Exception {
|
||||
Object provider = xMSF.createInstance(
|
||||
"com.sun.star.configuration.ConfigurationProvider");
|
||||
XMultiServiceFactory xProvider = (XMultiServiceFactory)
|
||||
UnoRuntime.queryInterface(XMultiServiceFactory.class,provider);
|
||||
PropertyValue[] args = new PropertyValue[1];
|
||||
args[0] = new PropertyValue();
|
||||
args[0].Name = "nodepath";
|
||||
args[0].Value = getRegistryPath();
|
||||
String sServiceName = bUpdate ?
|
||||
"com.sun.star.configuration.ConfigurationUpdateAccess" :
|
||||
"com.sun.star.configuration.ConfigurationAccess";
|
||||
Object view = xProvider.createInstanceWithArguments(sServiceName,args);
|
||||
return view;
|
||||
}
|
||||
|
||||
// Dispose a previously obtained registry view
|
||||
private void disposeRegistryView(Object view) {
|
||||
XComponent xComponent = (XComponent)
|
||||
UnoRuntime.queryInterface(XComponent.class,view);
|
||||
xComponent.dispose();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Implement uno interfaces
|
||||
|
||||
// Override getTypes() from the interface XTypeProvider
|
||||
public Type[] getTypes() {
|
||||
Type[] typeReturn = {};
|
||||
try {
|
||||
typeReturn = new Type[] {
|
||||
new Type( XServiceName.class ),
|
||||
new Type( XServiceInfo.class ),
|
||||
new Type( XTypeProvider.class ),
|
||||
new Type( XExecutableDialog.class ),
|
||||
new Type( XPropertyAccess.class ),
|
||||
new Type( XDialogEventHandler.class ) };
|
||||
} catch(Exception exception) {
|
||||
}
|
||||
return typeReturn;
|
||||
}
|
||||
|
||||
|
||||
// Implement the interface XPropertyAccess
|
||||
public PropertyValue[] getPropertyValues() {
|
||||
return mediaProps;
|
||||
}
|
||||
|
||||
public void setPropertyValues(PropertyValue[] props) {
|
||||
mediaProps = props;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Various utility methods to be used by the sublasses
|
||||
|
||||
// Helpers to load and save settings
|
||||
|
||||
protected void updateLockedOptions() {
|
||||
lockedOptions.clear();
|
||||
short nItem = getListBoxSelectedItem("Config");
|
||||
int nStdConfigs = getListBoxStringItemList("Config").length - sConfigNames.length;
|
||||
if (nItem>=nStdConfigs) {
|
||||
// Get current configuration name
|
||||
String sName = sConfigNames[nItem-nStdConfigs];
|
||||
|
||||
try {
|
||||
// Prepare registry view
|
||||
Object view = getRegistryView(false);
|
||||
XPropertySet xProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,view);
|
||||
|
||||
// Get the available configurations
|
||||
Object configurations = getPropertyValue(xProps,"Configurations");
|
||||
XNameAccess xConfigurations = (XNameAccess)
|
||||
UnoRuntime.queryInterface(XNameAccess.class,configurations);
|
||||
|
||||
// Get the LockedOptions node from the desired configuration
|
||||
String sLockedOptions = "";
|
||||
Object config = xConfigurations.getByName(sName);
|
||||
XPropertySet xCfgProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,config);
|
||||
sLockedOptions = getPropertyValueAsString(xCfgProps,"LockedOptions");
|
||||
|
||||
// Dispose the registry view
|
||||
disposeRegistryView(view);
|
||||
|
||||
// Feed lockedOptions with the comma separated list of options
|
||||
int nStart = 0;
|
||||
for (int i=0; i<sLockedOptions.length(); i++) {
|
||||
if (sLockedOptions.charAt(i)==',') {
|
||||
lockedOptions.add(sLockedOptions.substring(nStart,i).trim());
|
||||
nStart = i+1;
|
||||
}
|
||||
}
|
||||
if (nStart<sLockedOptions.length()) {
|
||||
lockedOptions.add(sLockedOptions.substring(nStart).trim());
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// no options will be locked...
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected boolean isLocked(String sOptionName) {
|
||||
return lockedOptions.contains(sOptionName);
|
||||
}
|
||||
|
||||
// Configuration
|
||||
protected void loadConfig(XPropertySet xProps) {
|
||||
// The list box is extended with configurations from the registry
|
||||
String[] sStdConfigs = getListBoxStringItemList("Config");
|
||||
int nStdConfigs = sStdConfigs.length;
|
||||
|
||||
Object configurations = getPropertyValue(xProps,"Configurations");
|
||||
XNameAccess xConfigurations = (XNameAccess)
|
||||
UnoRuntime.queryInterface(XNameAccess.class,configurations);
|
||||
sConfigNames = xConfigurations.getElementNames();
|
||||
int nRegConfigs = sConfigNames.length;
|
||||
|
||||
String[] sAllConfigs = new String[nStdConfigs+nRegConfigs];
|
||||
for (short i=0; i<nStdConfigs; i++) {
|
||||
sAllConfigs[i] = sStdConfigs[i];
|
||||
}
|
||||
|
||||
for (short i=0; i<nRegConfigs; i++) {
|
||||
try {
|
||||
Object config = xConfigurations.getByName(sConfigNames[i]);
|
||||
XPropertySet xCfgProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,config);
|
||||
sAllConfigs[nStdConfigs+i] = getPropertyValueAsString(xCfgProps,"DisplayName");
|
||||
}
|
||||
catch (Exception e) {
|
||||
sAllConfigs[nStdConfigs+i] = "";
|
||||
}
|
||||
}
|
||||
|
||||
setListBoxStringItemList("Config",sAllConfigs);
|
||||
if (nStdConfigs+nRegConfigs<=12) {
|
||||
setListBoxLineCount("Config",(short) (nStdConfigs+nRegConfigs));
|
||||
}
|
||||
else {
|
||||
setListBoxLineCount("Config",(short) 12);
|
||||
}
|
||||
|
||||
// Select item based on template name
|
||||
String sTheTemplateName = getTemplateName();
|
||||
Object templates = getPropertyValue(xProps,"Templates");
|
||||
XNameAccess xTemplates = (XNameAccess)
|
||||
UnoRuntime.queryInterface(XNameAccess.class,templates);
|
||||
String[] sTemplateNames = xTemplates.getElementNames();
|
||||
for (int i=0; i<sTemplateNames.length; i++) {
|
||||
try {
|
||||
Object template = xTemplates.getByName(sTemplateNames[i]);
|
||||
XPropertySet xTplProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,template);
|
||||
String sTemplateName = getPropertyValueAsString(xTplProps,"TemplateName");
|
||||
if (sTemplateName.equals(sTheTemplateName)) {
|
||||
String sConfigName = getPropertyValueAsString(xTplProps,"ConfigName");
|
||||
for (short j=0; j<nRegConfigs; j++) {
|
||||
if (sConfigNames[j].equals(sConfigName)) {
|
||||
setListBoxSelectedItem("Config",(short) (nStdConfigs+j));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Select item based on value stored in registry
|
||||
short nConfig = getPropertyValueAsShort(xProps,"Config");
|
||||
if (nConfig<nStdConfigs) {
|
||||
setListBoxSelectedItem("Config",nConfig);
|
||||
}
|
||||
else { // Registry configurations are stored by name
|
||||
String sConfigName = getPropertyValueAsString(xProps,"ConfigName");
|
||||
for (short i=0; i<nRegConfigs; i++) {
|
||||
if (sConfigNames[i].equals(sConfigName)) {
|
||||
setListBoxSelectedItem("Config",(short) (nStdConfigs+i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected short saveConfig(XPropertySet xProps, PropertyHelper filterData) {
|
||||
// The Config list box is common for all dialogs
|
||||
Object configurations = getPropertyValue(xProps,"Configurations");
|
||||
XNameAccess xNameAccess = (XNameAccess)
|
||||
UnoRuntime.queryInterface(XNameAccess.class,configurations);
|
||||
|
||||
boolean bFound = false;
|
||||
short nConfig = getListBoxSelectedItem("Config");
|
||||
int nStdConfigs = getListBoxStringItemList("Config").length - sConfigNames.length;
|
||||
if (nConfig>=nStdConfigs) { // only handle registry configurations
|
||||
int i = nConfig-nStdConfigs;
|
||||
try {
|
||||
Object config = xNameAccess.getByName(sConfigNames[i]);
|
||||
XPropertySet xCfgProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,config);
|
||||
filterData.put("ConfigURL",expandMacros(getPropertyValueAsString(xCfgProps,"ConfigURL")));
|
||||
filterData.put("TemplateURL",expandMacros(getPropertyValueAsString(xCfgProps,"TargetTemplateURL")));
|
||||
setPropertyValue(xProps,"ConfigName",sConfigNames[i]);
|
||||
bFound = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
setPropertyValue(xProps,"Config",nConfig);
|
||||
if (!bFound) { setPropertyValue(xProps,"ConfigName",""); }
|
||||
return nConfig;
|
||||
}
|
||||
|
||||
// Check box option (boolean)
|
||||
protected boolean loadCheckBoxOption(XPropertySet xProps, String sName) {
|
||||
boolean bValue = getPropertyValueAsBoolean(xProps,sName);
|
||||
setCheckBoxStateAsBoolean(sName, bValue);
|
||||
return bValue;
|
||||
}
|
||||
|
||||
protected boolean saveCheckBoxOption(XPropertySet xProps, String sName) {
|
||||
boolean bValue = getCheckBoxStateAsBoolean(sName);
|
||||
setPropertyValue(xProps, sName, bValue);
|
||||
return bValue;
|
||||
}
|
||||
|
||||
protected boolean saveCheckBoxOption(XPropertySet xProps, PropertyHelper filterData,
|
||||
String sName, String sOptionName) {
|
||||
boolean bValue = saveCheckBoxOption(xProps, sName);
|
||||
if (!isLocked(sOptionName)) {
|
||||
filterData.put(sOptionName, Boolean.toString(bValue));
|
||||
}
|
||||
return bValue;
|
||||
}
|
||||
|
||||
// List box option
|
||||
protected short loadListBoxOption(XPropertySet xProps, String sName) {
|
||||
short nValue = getPropertyValueAsShort(xProps, sName);
|
||||
setListBoxSelectedItem(sName ,nValue);
|
||||
return nValue;
|
||||
}
|
||||
|
||||
protected short saveListBoxOption(XPropertySet xProps, String sName) {
|
||||
short nValue = getListBoxSelectedItem(sName);
|
||||
setPropertyValue(xProps, sName, nValue);
|
||||
return nValue;
|
||||
}
|
||||
|
||||
protected short saveListBoxOption(XPropertySet xProps, PropertyHelper filterData,
|
||||
String sName, String sOptionName, String[] sValues) {
|
||||
short nValue = saveListBoxOption(xProps, sName);
|
||||
if (!isLocked(sOptionName) && (nValue>=0) && (nValue<sValues.length)) {
|
||||
filterData.put(sOptionName, sValues[nValue]);
|
||||
}
|
||||
return nValue;
|
||||
}
|
||||
|
||||
// Combo box option
|
||||
protected String loadComboBoxOption(XPropertySet xProps, String sName) {
|
||||
String sValue = getPropertyValueAsString(xProps, sName);
|
||||
setComboBoxText(sName ,sValue);
|
||||
return sValue;
|
||||
}
|
||||
|
||||
protected String saveComboBoxOption(XPropertySet xProps, String sName) {
|
||||
String sValue = getComboBoxText(sName);
|
||||
setPropertyValue(xProps, sName, sValue);
|
||||
return sValue;
|
||||
}
|
||||
|
||||
protected String saveComboBoxOption(XPropertySet xProps, PropertyHelper filterData,
|
||||
String sName, String sOptionName) {
|
||||
String sValue = saveComboBoxOption(xProps, sName);
|
||||
if (!isLocked(sOptionName)) {
|
||||
filterData.put(sOptionName, sValue);
|
||||
}
|
||||
return sValue;
|
||||
}
|
||||
|
||||
// Text Field option
|
||||
protected String loadTextFieldOption(XPropertySet xProps, String sName) {
|
||||
String sValue = getPropertyValueAsString(xProps, sName);
|
||||
setTextFieldText(sName ,sValue);
|
||||
return sValue;
|
||||
}
|
||||
|
||||
protected String saveTextFieldOption(XPropertySet xProps, String sName) {
|
||||
String sValue = getTextFieldText(sName);
|
||||
setPropertyValue(xProps, sName, sValue);
|
||||
return sValue;
|
||||
}
|
||||
|
||||
protected String saveTextFieldOption(XPropertySet xProps, PropertyHelper filterData,
|
||||
String sName, String sOptionName) {
|
||||
String sValue = saveTextFieldOption(xProps, sName);
|
||||
if (!isLocked(sOptionName)) {
|
||||
filterData.put(sOptionName, sValue);
|
||||
}
|
||||
return sValue;
|
||||
}
|
||||
|
||||
// Numeric option
|
||||
protected int loadNumericOption(XPropertySet xProps, String sName) {
|
||||
int nValue = getPropertyValueAsInteger(xProps, sName);
|
||||
setNumericFieldValue(sName, nValue);
|
||||
return nValue;
|
||||
}
|
||||
|
||||
protected int saveNumericOption(XPropertySet xProps, String sName) {
|
||||
int nValue = getNumericFieldValue(sName);
|
||||
setPropertyValue(xProps, sName, nValue);
|
||||
return nValue;
|
||||
}
|
||||
|
||||
protected int saveNumericOptionAsPercentage(XPropertySet xProps,
|
||||
PropertyHelper filterData, String sName, String sOptionName) {
|
||||
int nValue = saveNumericOption(xProps, sName);
|
||||
if (!isLocked(sOptionName)) {
|
||||
filterData.put(sOptionName,Integer.toString(nValue)+"%");
|
||||
}
|
||||
return nValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,503 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* DialogBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-11)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.helper;
|
||||
|
||||
import com.sun.star.awt.XControl;
|
||||
import com.sun.star.awt.XControlContainer;
|
||||
import com.sun.star.awt.XControlModel;
|
||||
import com.sun.star.awt.XDialog;
|
||||
import com.sun.star.awt.XDialogEventHandler;
|
||||
import com.sun.star.awt.XDialogProvider2;
|
||||
import com.sun.star.beans.PropertyVetoException;
|
||||
import com.sun.star.beans.UnknownPropertyException;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.lang.IllegalArgumentException;
|
||||
import com.sun.star.lang.WrappedTargetException;
|
||||
import com.sun.star.lang.XMultiComponentFactory;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XServiceName;
|
||||
import com.sun.star.lang.XTypeProvider;
|
||||
import com.sun.star.ui.dialogs.ExecutableDialogResults;
|
||||
import com.sun.star.ui.dialogs.XExecutableDialog;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
|
||||
/** This class provides an abstract uno component which implements a dialog
|
||||
* from an xml description (using the DialogProvider2 service)
|
||||
*/
|
||||
public abstract class DialogBase implements
|
||||
XTypeProvider, XServiceInfo, XServiceName, // Uno component
|
||||
XExecutableDialog, // Execute the dialog
|
||||
XDialogEventHandler { // Event handling for dialog
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// The subclass must override the following; and override the
|
||||
// implementation of XDialogEventHandler if needed
|
||||
|
||||
/** The component will be registered under this name.
|
||||
* The subclass must override this with a suitable name
|
||||
*/
|
||||
public static String __serviceName = "";
|
||||
|
||||
/** The component should also have an implementation name.
|
||||
* The subclass must override this with a suitable name
|
||||
*/
|
||||
public static String __implementationName = "";
|
||||
|
||||
/** Return the name of the library containing the dialog
|
||||
* The subclass must override this to provide the name of the library
|
||||
*/
|
||||
public abstract String getDialogLibraryName();
|
||||
|
||||
/** Return the name of the dialog within the library
|
||||
* The subclass must override this to provide the name of the dialog
|
||||
*/
|
||||
public abstract String getDialogName();
|
||||
|
||||
/** Initialize the dialog (eg. with settings from the registry)
|
||||
* The subclass must implement this
|
||||
*/
|
||||
protected abstract void initialize();
|
||||
|
||||
/** Finalize the dialog after execution (eg. save settings to the registry)
|
||||
* The subclass must implement this
|
||||
*/
|
||||
protected abstract void finalize();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Some constants
|
||||
|
||||
// State of a checkbox
|
||||
protected static final short CHECKBOX_NOT_CHECKED = 0;
|
||||
protected static final short CHECKBOX_CHECKED = 1;
|
||||
protected static final short CHECKBOX_DONT_KNOW = 2;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Some private global variables
|
||||
|
||||
// The component context (from constructor)
|
||||
protected XComponentContext xContext;
|
||||
|
||||
// The dialog (created by XExecutableDialog implementation)
|
||||
private XDialog xDialog;
|
||||
private String sTitle;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// The constructor
|
||||
|
||||
/** Create a new OptionsDialogBase */
|
||||
public DialogBase(XComponentContext xContext) {
|
||||
this.xContext = xContext;
|
||||
xDialog = null;
|
||||
sTitle = null;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Implement uno interfaces
|
||||
|
||||
// Implement the interface XTypeProvider
|
||||
public Type[] getTypes() {
|
||||
Type[] typeReturn = {};
|
||||
try {
|
||||
typeReturn = new Type[] {
|
||||
new Type( XServiceName.class ),
|
||||
new Type( XServiceInfo.class ),
|
||||
new Type( XTypeProvider.class ),
|
||||
new Type( XExecutableDialog.class ),
|
||||
new Type( XDialogEventHandler.class ) };
|
||||
} catch(Exception exception) {
|
||||
}
|
||||
return typeReturn;
|
||||
}
|
||||
|
||||
public byte[] getImplementationId() {
|
||||
byte[] byteReturn = {};
|
||||
byteReturn = new String( "" + this.hashCode() ).getBytes();
|
||||
return( byteReturn );
|
||||
}
|
||||
|
||||
|
||||
// Implement the interface XServiceName
|
||||
public String getServiceName() {
|
||||
return __serviceName;
|
||||
}
|
||||
|
||||
|
||||
// Implement the interface XServiceInfo
|
||||
public boolean supportsService(String sServiceName) {
|
||||
return sServiceName.equals(__serviceName);
|
||||
}
|
||||
|
||||
public String getImplementationName() {
|
||||
return __implementationName;
|
||||
}
|
||||
|
||||
public String[] getSupportedServiceNames() {
|
||||
String[] sSupportedServiceNames = { __serviceName };
|
||||
return sSupportedServiceNames;
|
||||
}
|
||||
|
||||
|
||||
// Implement the interface XExecutableDialog
|
||||
public void setTitle(String sTitle) {
|
||||
this.sTitle = sTitle;
|
||||
}
|
||||
|
||||
public short execute() {
|
||||
try {
|
||||
// Create the dialog
|
||||
XMultiComponentFactory xMCF = xContext.getServiceManager();
|
||||
Object provider = xMCF.createInstanceWithContext(
|
||||
"com.sun.star.awt.DialogProvider2", xContext);
|
||||
XDialogProvider2 xDialogProvider = (XDialogProvider2)
|
||||
UnoRuntime.queryInterface(XDialogProvider2.class, provider);
|
||||
String sDialogUrl = "vnd.sun.star.script:"+getDialogLibraryName()+"."
|
||||
+getDialogName()+"?location=application";
|
||||
xDialog = xDialogProvider.createDialogWithHandler(sDialogUrl, this);
|
||||
if (sTitle!=null) { xDialog.setTitle(sTitle); }
|
||||
|
||||
// Do initialization using method from subclass
|
||||
initialize();
|
||||
|
||||
// Execute the dialog
|
||||
short nResult = xDialog.execute();
|
||||
|
||||
if (nResult == ExecutableDialogResults.OK) {
|
||||
// Finalize after execution of dialog using method from subclass
|
||||
finalize();
|
||||
}
|
||||
xDialog.endExecute();
|
||||
return nResult;
|
||||
}
|
||||
catch (Exception e) {
|
||||
MessageBox msgBox = new MessageBox(xContext);
|
||||
msgBox.showMessage("Error",e.toString()+" "+e.getStackTrace()[0].toString());
|
||||
|
||||
// continue as if the dialog was executed OK
|
||||
return ExecutableDialogResults.OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Implement the interface XDialogEventHandler
|
||||
public boolean callHandlerMethod(XDialog xDialog, Object event, String sMethod) {
|
||||
// Do nothing, leaving the responsibility to the subclass
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getSupportedMethodNames() {
|
||||
// We do not support any method names, subclass should take care of this
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers to access controls in the dialog (to be used by the subclass)
|
||||
// Note: The helpers fail silently if an exception occurs. Could query the
|
||||
// the ClassId property for the control type and check that the property
|
||||
// exists to ensure a correct behaviour in all cases, but as long as the
|
||||
// helpers are used correctly, this doesn't really matter.
|
||||
|
||||
// Get the properties of a named control in the dialog
|
||||
private XPropertySet getControlProperties(String sControlName) {
|
||||
XControlContainer xContainer = (XControlContainer)
|
||||
UnoRuntime.queryInterface(XControlContainer.class, xDialog);
|
||||
XControl xControl = xContainer.getControl(sControlName);
|
||||
XControlModel xModel = xControl.getModel();
|
||||
XPropertySet xPropertySet = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class, xModel);
|
||||
return xPropertySet;
|
||||
}
|
||||
|
||||
|
||||
protected void setControlEnabled(String sControlName, boolean bEnabled) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("Enabled", new Boolean(bEnabled));
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist
|
||||
}
|
||||
}
|
||||
|
||||
protected short getCheckBoxState(String sControlName) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return ((Short) xPropertySet.getPropertyValue("State")).shortValue();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a checkbox
|
||||
return CHECKBOX_DONT_KNOW;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean getCheckBoxStateAsBoolean(String sControlName) {
|
||||
return getCheckBoxState(sControlName)==CHECKBOX_CHECKED;
|
||||
}
|
||||
|
||||
protected void setCheckBoxState(String sControlName, short nState) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("State",new Short(nState));
|
||||
}
|
||||
catch (Exception e) {
|
||||
// will fail if the control does not exist or is not a checkbox or
|
||||
// nState has an illegal value
|
||||
}
|
||||
}
|
||||
|
||||
protected void setCheckBoxStateAsBoolean(String sControlName, boolean bChecked) {
|
||||
setCheckBoxState(sControlName,bChecked ? CHECKBOX_CHECKED : CHECKBOX_NOT_CHECKED);
|
||||
}
|
||||
|
||||
protected String[] getListBoxStringItemList(String sControlName) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return (String[]) xPropertySet.getPropertyValue("StringItemList");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
protected void setListBoxStringItemList(String sControlName, String[] items) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("StringItemList",items);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box
|
||||
}
|
||||
}
|
||||
|
||||
protected short getListBoxSelectedItem(String sControlName) {
|
||||
// Returns the first selected element in case of a multiselection
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
short[] selection = (short[]) xPropertySet.getPropertyValue("SelectedItems");
|
||||
return selection[0];
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setListBoxSelectedItem(String sControlName, short nIndex) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
short[] selection = new short[1];
|
||||
selection[0] = nIndex;
|
||||
xPropertySet.setPropertyValue("SelectedItems",selection);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box or
|
||||
// nIndex is an illegal value
|
||||
}
|
||||
}
|
||||
|
||||
protected short getListBoxLineCount(String sControlName) {
|
||||
// Returns the first selected element in case of a multiselection
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return ((Short) xPropertySet.getPropertyValue("LineCount")).shortValue();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setListBoxLineCount(String sControlName, short nLineCount) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("LineCount",new Short(nLineCount));
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box or
|
||||
// nLineCount is an illegal value
|
||||
}
|
||||
}
|
||||
|
||||
protected String getComboBoxText(String sControlName) {
|
||||
// Returns the text of a combobox
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return (String) xPropertySet.getPropertyValue("Text");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a combo
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
protected void setComboBoxText(String sControlName, String sText) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("Text", sText);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a combo box or
|
||||
// nText is an illegal value
|
||||
}
|
||||
}
|
||||
|
||||
protected String getTextFieldText(String sControlName) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return (String) xPropertySet.getPropertyValue("Text");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a text field
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
protected void setTextFieldText(String sControlName, String sText) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("Text",sText);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a text field
|
||||
}
|
||||
}
|
||||
|
||||
protected String getFormattedFieldText(String sControlName) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return (String) xPropertySet.getPropertyValue("Text");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a formatted field
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
protected void setFormattedFieldText(String sControlName, String sText) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("Text",sText);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a formatted field
|
||||
}
|
||||
}
|
||||
|
||||
protected int getNumericFieldValue(String sControlName) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return ((Double) xPropertySet.getPropertyValue("Value")).intValue();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a numeric field
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setNumericFieldValue(String sControlName, int nValue) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("Value",new Double(nValue));
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a numeric field
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers for access to an XPropertySet. The helpers will fail silently if
|
||||
// names or data is provided, but the subclass is expected to use them with
|
||||
// correct data only...
|
||||
protected Object getPropertyValue(XPropertySet xProps, String sName) {
|
||||
try {
|
||||
return xProps.getPropertyValue(sName);
|
||||
}
|
||||
catch (UnknownPropertyException e) {
|
||||
return null;
|
||||
}
|
||||
catch (WrappedTargetException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setPropertyValue(XPropertySet xProps, String sName, Object value) {
|
||||
try {
|
||||
xProps.setPropertyValue(sName,value);
|
||||
}
|
||||
catch (UnknownPropertyException e) {
|
||||
}
|
||||
catch (PropertyVetoException e) { // unacceptable value
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
}
|
||||
catch (WrappedTargetException e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected String getPropertyValueAsString(XPropertySet xProps, String sName) {
|
||||
Object value = getPropertyValue(xProps,sName);
|
||||
return value instanceof String ? (String) value : "";
|
||||
}
|
||||
|
||||
protected int getPropertyValueAsInteger(XPropertySet xProps, String sName) {
|
||||
Object value = getPropertyValue(xProps,sName);
|
||||
return value instanceof Integer ? ((Integer) value).intValue() : 0;
|
||||
}
|
||||
|
||||
protected void setPropertyValue(XPropertySet xProps, String sName, int nValue) {
|
||||
setPropertyValue(xProps,sName,new Integer(nValue));
|
||||
}
|
||||
|
||||
protected short getPropertyValueAsShort(XPropertySet xProps, String sName) {
|
||||
Object value = getPropertyValue(xProps,sName);
|
||||
return value instanceof Short ? ((Short) value).shortValue() : 0;
|
||||
}
|
||||
|
||||
protected void setPropertyValue(XPropertySet xProps, String sName, short nValue) {
|
||||
setPropertyValue(xProps,sName,new Short(nValue));
|
||||
}
|
||||
|
||||
protected boolean getPropertyValueAsBoolean(XPropertySet xProps, String sName) {
|
||||
Object value = getPropertyValue(xProps,sName);
|
||||
return value instanceof Boolean ? ((Boolean) value).booleanValue() : false;
|
||||
}
|
||||
|
||||
protected void setPropertyValue(XPropertySet xProps, String sName, boolean bValue) {
|
||||
setPropertyValue(xProps,sName,new Boolean(bValue));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* MessageBox.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.helper;
|
||||
|
||||
import com.sun.star.awt.Rectangle;
|
||||
import com.sun.star.awt.WindowAttribute;
|
||||
import com.sun.star.awt.WindowClass;
|
||||
import com.sun.star.awt.WindowDescriptor;
|
||||
import com.sun.star.awt.XMessageBox;
|
||||
import com.sun.star.awt.XToolkit;
|
||||
import com.sun.star.awt.XWindowPeer;
|
||||
import com.sun.star.frame.XDesktop;
|
||||
import com.sun.star.frame.XFrame;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
/** This class provides simple access to a uno awt message box
|
||||
*/
|
||||
public class MessageBox {
|
||||
|
||||
private XFrame xFrame;
|
||||
private XToolkit xToolkit;
|
||||
|
||||
/** Create a new MessageBox belonging to the current frame
|
||||
*/
|
||||
public MessageBox(XComponentContext xContext) {
|
||||
this(xContext,null);
|
||||
}
|
||||
|
||||
/** Create a new MessageBox belonging to a specific frame
|
||||
*/
|
||||
public MessageBox(XComponentContext xContext, XFrame xFrame) {
|
||||
try {
|
||||
Object toolkit = xContext.getServiceManager()
|
||||
.createInstanceWithContext("com.sun.star.awt.Toolkit",xContext);
|
||||
xToolkit = (XToolkit) UnoRuntime.queryInterface(XToolkit.class,toolkit);
|
||||
if (xFrame==null) {
|
||||
Object desktop = xContext.getServiceManager()
|
||||
.createInstanceWithContext("com.sun.star.frame.Desktop",xContext);
|
||||
XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class,desktop);
|
||||
xFrame = xDesktop.getCurrentFrame();
|
||||
}
|
||||
this.xFrame = xFrame;
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Failed to get toolkit or frame
|
||||
xToolkit = null;
|
||||
xFrame = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void showMessage(String sTitle, String sMessage) {
|
||||
if (xToolkit==null || xFrame==null) { return; }
|
||||
try {
|
||||
WindowDescriptor descriptor = new WindowDescriptor();
|
||||
descriptor.Type = WindowClass.MODALTOP;
|
||||
descriptor.WindowServiceName = "infobox";
|
||||
descriptor.ParentIndex = -1;
|
||||
descriptor.Parent = (XWindowPeer) UnoRuntime.queryInterface(
|
||||
XWindowPeer.class,xFrame.getContainerWindow());
|
||||
descriptor.Bounds = new Rectangle(0,0,300,200);
|
||||
descriptor.WindowAttributes = WindowAttribute.BORDER |
|
||||
WindowAttribute.MOVEABLE | WindowAttribute.CLOSEABLE;
|
||||
XWindowPeer xPeer = xToolkit.createWindow(descriptor);
|
||||
if (xPeer!=null) {
|
||||
XMessageBox xMessageBox = (XMessageBox)
|
||||
UnoRuntime.queryInterface(XMessageBox.class,xPeer);
|
||||
if (xMessageBox!=null) {
|
||||
xMessageBox.setCaptionText(sTitle);
|
||||
xMessageBox.setMessageText(sMessage);
|
||||
xMessageBox.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore, give up...
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* PropertyHelper.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.helper;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
|
||||
/** This class provides access by name to a <code>PropertyValue</code> array
|
||||
*/
|
||||
public class PropertyHelper {
|
||||
|
||||
private Hashtable data;
|
||||
|
||||
public PropertyHelper() {
|
||||
data = new Hashtable();
|
||||
}
|
||||
|
||||
public PropertyHelper(PropertyValue[] props) {
|
||||
data = new Hashtable();
|
||||
int nLen = props.length;
|
||||
for (int i=0; i<nLen; i++) {
|
||||
data.put(props[i].Name,props[i].Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void put(String sName, Object value) {
|
||||
data.put(sName,value);
|
||||
}
|
||||
|
||||
public Object get(String sName) {
|
||||
return data.get(sName);
|
||||
}
|
||||
|
||||
public Enumeration keys() {
|
||||
return data.keys();
|
||||
}
|
||||
|
||||
public PropertyValue[] toArray() {
|
||||
int nSize = data.size();
|
||||
PropertyValue[] props = new PropertyValue[nSize];
|
||||
int i=0;
|
||||
Enumeration keys = keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
String sKey = (String) keys.nextElement();
|
||||
props[i] = new PropertyValue();
|
||||
props[i].Name = sKey;
|
||||
props[i++].Value = get(sKey);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,351 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* LaTeXOptionsDialog.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-18)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2latex;
|
||||
|
||||
import com.sun.star.awt.XDialog;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
//import com.sun.star.frame.XDesktop;
|
||||
//import com.sun.star.lang.XComponent;
|
||||
//import com.sun.star.text.XTextFieldsSupplier;
|
||||
//import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
import org.openoffice.da.comp.w2lcommon.filter.OptionsDialogBase;
|
||||
|
||||
/** This class provides a uno component which implements a filter ui for the
|
||||
* LaTeX export
|
||||
*/
|
||||
public class LaTeXOptionsDialog extends OptionsDialogBase {
|
||||
|
||||
// Translate list box items to configuration option values
|
||||
private static final String[] BACKEND_VALUES =
|
||||
{ "generic", "pdftex", "dvips", "unspecified" };
|
||||
private static final String[] INPUTENCODING_VALUES =
|
||||
{ "ascii", "latin1", "latin2", "iso-8859-7", "cp1250", "cp1251", "koi8-r", "utf8" };
|
||||
private static final String[] NOTES_VALUES =
|
||||
{ "ignore", "comment", "marginpar", "pdfannotation" };
|
||||
private static final String[] FLOATOPTIONS_VALUES =
|
||||
{ "", "tp", "bp", "htp", "hbp" };
|
||||
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static String __serviceName = "org.openoffice.da.writer2latex.LaTeXOptionsDialog";
|
||||
|
||||
/** The component should also have an implementation name.
|
||||
* The subclass should override this with a suitable name
|
||||
*/
|
||||
public static String __implementationName = "org.openoffice.da.comp.writer2latex.LaTeXOptionsDialog";
|
||||
|
||||
public String getDialogLibraryName() { return "W2LDialogs"; }
|
||||
|
||||
|
||||
/** Create a new LaTeXOptionsDialog */
|
||||
public LaTeXOptionsDialog(XComponentContext xContext) {
|
||||
super(xContext);
|
||||
xMSF = W2LRegistration.xMultiServiceFactory;
|
||||
}
|
||||
|
||||
/** Return the name of the dialog within the library
|
||||
*/
|
||||
public String getDialogName() { return "LaTeXOptions"; }
|
||||
|
||||
/** Return the name of the registry path
|
||||
*/
|
||||
public String getRegistryPath() {
|
||||
return "/org.openoffice.da.Writer2LaTeX.Options/LaTeXOptions";
|
||||
}
|
||||
|
||||
/** Load settings from the registry to the dialog */
|
||||
protected void loadSettings(XPropertySet xProps) {
|
||||
// General
|
||||
loadConfig(xProps);
|
||||
loadListBoxOption(xProps,"Backend");
|
||||
loadListBoxOption(xProps,"Inputencoding");
|
||||
loadCheckBoxOption(xProps,"Multilingual");
|
||||
loadCheckBoxOption(xProps,"GreekMath");
|
||||
loadCheckBoxOption(xProps,"AdditionalSymbols");
|
||||
|
||||
// Bibliography
|
||||
loadCheckBoxOption(xProps,"UseBibtex");
|
||||
loadComboBoxOption(xProps,"BibtexStyle");
|
||||
|
||||
// Files
|
||||
loadCheckBoxOption(xProps,"WrapLines");
|
||||
loadNumericOption(xProps,"WrapLinesAfter");
|
||||
loadCheckBoxOption(xProps,"SplitLinkedSections");
|
||||
loadCheckBoxOption(xProps,"SplitToplevelSections");
|
||||
loadCheckBoxOption(xProps,"SaveImagesInSubdir");
|
||||
|
||||
// Special content
|
||||
loadListBoxOption(xProps,"Notes");
|
||||
loadCheckBoxOption(xProps,"Metadata");
|
||||
|
||||
// Figures and tables
|
||||
loadCheckBoxOption(xProps,"OriginalImageSize");
|
||||
loadCheckBoxOption(xProps,"OptimizeSimpleTables");
|
||||
loadNumericOption(xProps,"SimpleTableLimit");
|
||||
loadCheckBoxOption(xProps,"FloatTables");
|
||||
loadCheckBoxOption(xProps,"FloatFigures");
|
||||
loadListBoxOption(xProps,"FloatOptions");
|
||||
|
||||
// AutoCorrect
|
||||
loadCheckBoxOption(xProps,"IgnoreHardPageBreaks");
|
||||
loadCheckBoxOption(xProps,"IgnoreHardLineBreaks");
|
||||
loadCheckBoxOption(xProps,"IgnoreEmptyParagraphs");
|
||||
loadCheckBoxOption(xProps,"IgnoreDoubleSpaces");
|
||||
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
|
||||
/** Save settings from the dialog to the registry and create FilterData */
|
||||
protected void saveSettings(XPropertySet xProps, PropertyHelper filterData) {
|
||||
// General
|
||||
short nConfig = saveConfig(xProps, filterData);
|
||||
switch (nConfig) {
|
||||
case 0: filterData.put("ConfigURL","*ultraclean.xml"); break;
|
||||
case 1: filterData.put("ConfigURL","*clean.xml"); break;
|
||||
case 2: filterData.put("ConfigURL","*default.xml"); break;
|
||||
case 3: filterData.put("ConfigURL","*pdfprint.xml"); break;
|
||||
case 4: filterData.put("ConfigURL","*pdfscreen.xml"); break;
|
||||
case 5: filterData.put("ConfigURL","$(user)/writer2latex.xml");
|
||||
filterData.put("AutoCreate","true");
|
||||
}
|
||||
|
||||
saveListBoxOption(xProps, filterData, "Backend", "backend", BACKEND_VALUES );
|
||||
if (getListBoxSelectedItem("Config")==4) {
|
||||
// pdfscreen locks the backend to pdftex
|
||||
filterData.put("backend","pdftex");
|
||||
}
|
||||
saveListBoxOption(xProps, filterData, "Inputencoding", "inputencoding", INPUTENCODING_VALUES);
|
||||
saveCheckBoxOption(xProps, filterData, "Multilingual", "multilingual");
|
||||
saveCheckBoxOption(xProps, filterData, "GreekMath", "greek_math");
|
||||
// AdditionalSymbols sets 5 different w2l options...
|
||||
saveCheckBoxOption(xProps, filterData, "AdditionalSymbols", "use_pifont");
|
||||
saveCheckBoxOption(xProps, filterData, "AdditionalSymbols", "use_ifsym");
|
||||
saveCheckBoxOption(xProps, filterData, "AdditionalSymbols", "use_wasysym");
|
||||
saveCheckBoxOption(xProps, filterData, "AdditionalSymbols", "use_eurosym");
|
||||
saveCheckBoxOption(xProps, filterData, "AdditionalSymbols", "use_tipa");
|
||||
|
||||
// Bibliography
|
||||
saveCheckBoxOption(xProps, filterData, "UseBibtex", "use_bibtex");
|
||||
saveComboBoxOption(xProps, filterData, "BibtexStyle", "bibtex_style");
|
||||
|
||||
// Files
|
||||
boolean bWrapLines = saveCheckBoxOption(xProps, "WrapLines");
|
||||
int nWrapLinesAfter = saveNumericOption(xProps, "WrapLinesAfter");
|
||||
if (!isLocked("wrap_lines_after")) {
|
||||
if (bWrapLines) {
|
||||
filterData.put("wrap_lines_after",Integer.toString(nWrapLinesAfter));
|
||||
}
|
||||
else {
|
||||
filterData.put("wrap_lines_after","0");
|
||||
}
|
||||
}
|
||||
|
||||
saveCheckBoxOption(xProps, filterData, "SplitLinkedSections", "split_linked_sections");
|
||||
saveCheckBoxOption(xProps, filterData, "SplitToplevelSections", "split_toplevel_sections");
|
||||
saveCheckBoxOption(xProps, filterData, "SaveImagesInSubdir", "save_images_in_subdir");
|
||||
|
||||
// Special content
|
||||
saveListBoxOption(xProps, filterData, "Notes", "notes", NOTES_VALUES);
|
||||
saveCheckBoxOption(xProps, filterData, "Metadata", "metadata");
|
||||
|
||||
// Figures and tables
|
||||
saveCheckBoxOption(xProps, filterData, "OriginalImageSize", "original_image_size");
|
||||
|
||||
boolean bOptimizeSimpleTables = saveCheckBoxOption(xProps,"OptimizeSimpleTables");
|
||||
int nSimpleTableLimit = saveNumericOption(xProps,"SimpleTableLimit");
|
||||
if (!isLocked("simple_table_limit")) {
|
||||
if (bOptimizeSimpleTables) {
|
||||
filterData.put("simple_table_limit",Integer.toString(nSimpleTableLimit));
|
||||
}
|
||||
else {
|
||||
filterData.put("simple_table_limit","0");
|
||||
}
|
||||
}
|
||||
|
||||
saveCheckBoxOption(xProps, filterData, "FloatTables", "float_tables");
|
||||
saveCheckBoxOption(xProps, filterData, "FloatFigures", "float_figures");
|
||||
saveListBoxOption(xProps, filterData, "FloatOptions", "float_options", FLOATOPTIONS_VALUES);
|
||||
|
||||
// AutoCorrect
|
||||
saveCheckBoxOption(xProps, filterData, "IgnoreHardPageBreaks", "ignore_hard_page_breaks");
|
||||
saveCheckBoxOption(xProps, filterData, "IgnoreHardLineBreaks", "ignore_hard_line_breaks");
|
||||
saveCheckBoxOption(xProps, filterData, "IgnoreEmptyParagraphs", "ignore_empty_paragraphs");
|
||||
saveCheckBoxOption(xProps, filterData, "IgnoreDoubleSpaces", "ignore_double_spaces");
|
||||
}
|
||||
|
||||
|
||||
// Implement XDialogEventHandler
|
||||
public boolean callHandlerMethod(XDialog xDialog, Object event, String sMethod) {
|
||||
if (sMethod.equals("ConfigChange")) {
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
else if (sMethod.equals("UseBibtexChange")) {
|
||||
enableBibtexStyle();
|
||||
}
|
||||
else if (sMethod.equals("WrapLinesChange")) {
|
||||
enableWrapLinesAfter();
|
||||
}
|
||||
else if (sMethod.equals("OptimizeSimpleTablesChange")) {
|
||||
enableSimpleTableLimit();
|
||||
}
|
||||
else if (sMethod.equals("FloatTablesChange")) {
|
||||
enableFloatOptions();
|
||||
}
|
||||
else if (sMethod.equals("FloatFiguresChange")) {
|
||||
enableFloatOptions();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getSupportedMethodNames() {
|
||||
String[] sNames = { "ConfigChange", "UseBibtexChange", "WrapLinesChange",
|
||||
"OptimizeSimpleTablesChange", "FloatTablesChange", "FloatFiguresChange" };
|
||||
return sNames;
|
||||
}
|
||||
|
||||
protected boolean isLocked(String sOptionName) {
|
||||
if ("backend".equals(sOptionName)) {
|
||||
// backend must be pdf for pdfscreen
|
||||
return getListBoxSelectedItem("Config")==4 || super.isLocked(sOptionName);
|
||||
}
|
||||
else if ("additional_symbols".equals(sOptionName)) {
|
||||
// additional_symbols is disabled for custom config (where the 5
|
||||
// individual options can be set independently)
|
||||
return getListBoxSelectedItem("Config")==5 || super.isLocked(sOptionName);
|
||||
}
|
||||
else if ("use_pifont".equals(sOptionName)) {
|
||||
return isLocked("additional_symbols");
|
||||
}
|
||||
else if ("use_ifsym".equals(sOptionName)) {
|
||||
return isLocked("additional_symbols");
|
||||
}
|
||||
else if ("use_wasysym".equals(sOptionName)) {
|
||||
return isLocked("additional_symbols");
|
||||
}
|
||||
else if ("use_eurosym".equals(sOptionName)) {
|
||||
return isLocked("additional_symbols");
|
||||
}
|
||||
else if ("use_tipa".equals(sOptionName)) {
|
||||
return isLocked("additional_symbols");
|
||||
}
|
||||
else {
|
||||
return super.isLocked(sOptionName);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableControls() {
|
||||
// General
|
||||
setControlEnabled("BackendLabel",!isLocked("backend"));
|
||||
setControlEnabled("Backend",!isLocked("backend"));
|
||||
setControlEnabled("InputencodingLabel",!isLocked("inputencoding"));
|
||||
setControlEnabled("Inputencoding",!isLocked("inputencoding"));
|
||||
setControlEnabled("Multilingual",!isLocked("multilingual"));
|
||||
setControlEnabled("GreekMath",!isLocked("greek_math"));
|
||||
setControlEnabled("AdditionalSymbols",!isLocked("additional_symbols"));
|
||||
|
||||
// Bibliography
|
||||
setControlEnabled("UseBibtex",!isLocked("use_bibtex"));
|
||||
boolean bUseBibtex = getCheckBoxStateAsBoolean("UseBibtex");
|
||||
setControlEnabled("BibtexStyleLabel",!isLocked("bibtex_style") && bUseBibtex);
|
||||
setControlEnabled("BibtexStyle",!isLocked("bibtex_style") && bUseBibtex);
|
||||
|
||||
// Files
|
||||
setControlEnabled("WrapLines",!isLocked("wrap_lines_after"));
|
||||
boolean bWrapLines = getCheckBoxStateAsBoolean("WrapLines");
|
||||
setControlEnabled("WrapLinesAfterLabel",!isLocked("wrap_lines_after") && bWrapLines);
|
||||
setControlEnabled("WrapLinesAfter",!isLocked("wrap_lines_after") && bWrapLines);
|
||||
setControlEnabled("SplitLinkedSections",!isLocked("split_linked_sections"));
|
||||
setControlEnabled("SplitToplevelSections",!isLocked("split_toplevel_sections"));
|
||||
setControlEnabled("SaveImagesInSubdir",!isLocked("save_images_in_subdir"));
|
||||
|
||||
// Special content
|
||||
setControlEnabled("NotesLabel",!isLocked("notes"));
|
||||
setControlEnabled("Notes",!isLocked("notes"));
|
||||
setControlEnabled("Metadata",!isLocked("metadata"));
|
||||
|
||||
// Figures and tables
|
||||
setControlEnabled("OriginalImageSize",!isLocked("original_image_size"));
|
||||
setControlEnabled("OptimizeSimpleTables",!isLocked("simple_table_limit"));
|
||||
boolean bOptimizeSimpleTables = getCheckBoxStateAsBoolean("OptimizeSimpleTables");
|
||||
setControlEnabled("SimpleTableLimitLabel",!isLocked("simple_table_limit") && bOptimizeSimpleTables);
|
||||
setControlEnabled("SimpleTableLimit",!isLocked("simple_table_limit") && bOptimizeSimpleTables);
|
||||
setControlEnabled("FloatTables",!isLocked("float_tables"));
|
||||
setControlEnabled("FloatFigures",!isLocked("float_figures"));
|
||||
boolean bFloat = getCheckBoxStateAsBoolean("FloatFigures") ||
|
||||
getCheckBoxStateAsBoolean("FloatTables");
|
||||
setControlEnabled("FloatOptionsLabel",!isLocked("float_options") && bFloat);
|
||||
setControlEnabled("FloatOptions",!isLocked("float_options") && bFloat);
|
||||
|
||||
// AutoCorrect
|
||||
setControlEnabled("IgnoreHardPageBreaks",!isLocked("ignore_hard_page_breaks"));
|
||||
setControlEnabled("IgnoreHardLineBreaks",!isLocked("ignore_hard_line_breaks"));
|
||||
setControlEnabled("IgnoreEmptyParagraphs",!isLocked("ignore_empty_paragraphs"));
|
||||
setControlEnabled("IgnoreDoubleSpaces",!isLocked("ignore_double_spaces"));
|
||||
}
|
||||
|
||||
private void enableBibtexStyle() {
|
||||
if (!isLocked("bibtex_style")) {
|
||||
boolean bState = getCheckBoxStateAsBoolean("UseBibtex");
|
||||
setControlEnabled("BibtexStyleLabel",bState);
|
||||
setControlEnabled("BibtexStyle",bState);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableWrapLinesAfter() {
|
||||
if (!isLocked("wrap_lines_after")) {
|
||||
boolean bState = getCheckBoxStateAsBoolean("WrapLines");
|
||||
setControlEnabled("WrapLinesAfterLabel",bState);
|
||||
setControlEnabled("WrapLinesAfter",bState);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableSimpleTableLimit() {
|
||||
if (!isLocked("simple_table_limit")) {
|
||||
boolean bState = getCheckBoxStateAsBoolean("OptimizeSimpleTables");
|
||||
setControlEnabled("SimpleTableLimitLabel",bState);
|
||||
setControlEnabled("SimpleTableLimit",bState);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableFloatOptions() {
|
||||
if (!isLocked("float_options")) {
|
||||
boolean bState = getCheckBoxStateAsBoolean("FloatFigures") ||
|
||||
getCheckBoxStateAsBoolean("FloatTables");
|
||||
setControlEnabled("FloatOptionsLabel",bState);
|
||||
setControlEnabled("FloatOptions",bState);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* W2LExportFilter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2latex;
|
||||
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.filter.ExportFilterBase;
|
||||
|
||||
|
||||
/** This class implements the LaTeX and BibTeX export filter component
|
||||
*/
|
||||
public class W2LExportFilter extends ExportFilterBase {
|
||||
|
||||
/** Service name for the component */
|
||||
public static final String __serviceName = "org.openoffice.da.comp.writer2latex.W2LExportFilter";
|
||||
|
||||
/** Implementation name for the component */
|
||||
public static final String __implementationName = "org.openoffice.da.comp.writer2latex.W2LExportFilter";
|
||||
|
||||
/** Filter name to include in error messages */
|
||||
public static final String __displayName = "Writer2LaTeX";
|
||||
|
||||
public W2LExportFilter(XComponentContext xComponentContext1) {
|
||||
super(xComponentContext1);
|
||||
xMSF = W2LRegistration.xMultiServiceFactory;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* W2LRegistration.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2latex;
|
||||
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
|
||||
/** This class provides a static method to instantiate our uno components
|
||||
* on demand (__getServiceFactory()), and a static method to give
|
||||
* information about the components (__writeRegistryServiceInfo()).
|
||||
* Furthermore, it saves the XMultiServiceFactory provided to the
|
||||
* __getServiceFactory method for future reference by the componentes.
|
||||
*/
|
||||
public class W2LRegistration {
|
||||
|
||||
public static XMultiServiceFactory xMultiServiceFactory;
|
||||
|
||||
/**
|
||||
* Returns a factory for creating the service.
|
||||
* This method is called by the <code>JavaLoader</code>
|
||||
*
|
||||
* @return returns a <code>XSingleServiceFactory</code> for creating the
|
||||
* component
|
||||
*
|
||||
* @param implName the name of the implementation for which a
|
||||
* service is desired
|
||||
* @param multiFactory the service manager to be used if needed
|
||||
* @param regKey the registryKey
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(String implName,
|
||||
XMultiServiceFactory multiFactory, XRegistryKey regKey) {
|
||||
xMultiServiceFactory = multiFactory;
|
||||
XSingleServiceFactory xSingleServiceFactory = null;
|
||||
if (implName.equals(W2LExportFilter.class.getName()) ) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(W2LExportFilter.class,
|
||||
W2LExportFilter.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(LaTeXOptionsDialog.__implementationName)) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(LaTeXOptionsDialog.class,
|
||||
LaTeXOptionsDialog.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(W2LStarMathConverter.__implementationName)) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(W2LStarMathConverter.class,
|
||||
W2LStarMathConverter.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
|
||||
return xSingleServiceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the service information into the given registry key.
|
||||
* This method is called by the <code>JavaLoader</code>
|
||||
* <p>
|
||||
* @return returns true if the operation succeeded
|
||||
* @param regKey the registryKey
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) {
|
||||
return
|
||||
FactoryHelper.writeRegistryServiceInfo(W2LExportFilter.__implementationName,
|
||||
W2LExportFilter.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(LaTeXOptionsDialog.__implementationName,
|
||||
LaTeXOptionsDialog.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(W2LStarMathConverter.__implementationName,
|
||||
W2LStarMathConverter.__serviceName, regKey);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* W2LStarMathConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
// Version 1.0 (2008-11-22)
|
||||
|
||||
package org.openoffice.da.comp.writer2latex;
|
||||
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XTypeProvider;
|
||||
import com.sun.star.uno.Type;
|
||||
//import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.lang.XServiceName;
|
||||
|
||||
import writer2latex.api.ConverterFactory;
|
||||
import writer2latex.api.StarMathConverter;
|
||||
|
||||
// Import interface as defined in uno idl
|
||||
import org.openoffice.da.writer2latex.XW2LStarMathConverter;
|
||||
|
||||
/** This class provides a uno component which implements the interface
|
||||
* org.openoffice.da.writer2latex.XW2LConverter
|
||||
*/
|
||||
public class W2LStarMathConverter implements
|
||||
XW2LStarMathConverter,
|
||||
XServiceName,
|
||||
XServiceInfo,
|
||||
XTypeProvider {
|
||||
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static final String __serviceName = "org.openoffice.da.writer2latex.W2LStarMathConverter";
|
||||
|
||||
public static final String __implementationName = "org.openoffice.da.comp.writer2latex.W2LStarMathConverter";
|
||||
|
||||
//private static XComponentContext xComponentContext = null;
|
||||
private static StarMathConverter starMathConverter;
|
||||
|
||||
public W2LStarMathConverter(XComponentContext xComponentContext1) {
|
||||
starMathConverter = ConverterFactory.createStarMathConverter();
|
||||
}
|
||||
|
||||
// Implementation of XW2LConverter:
|
||||
public String convertFormula(String sStarMathFormula) {
|
||||
return starMathConverter.convert(sStarMathFormula);
|
||||
}
|
||||
|
||||
public String getPreamble() {
|
||||
return starMathConverter.getPreamble();
|
||||
}
|
||||
|
||||
|
||||
// Implement methods from interface XTypeProvider
|
||||
// Implementation of XTypeProvider
|
||||
|
||||
public com.sun.star.uno.Type[] getTypes() {
|
||||
Type[] typeReturn = {};
|
||||
|
||||
try {
|
||||
typeReturn = new Type[] {
|
||||
new Type( XW2LStarMathConverter.class ),
|
||||
new Type( XTypeProvider.class ),
|
||||
new Type( XServiceName.class ),
|
||||
new Type( XServiceInfo.class ) };
|
||||
}
|
||||
catch( Exception exception ) {
|
||||
|
||||
}
|
||||
|
||||
return( typeReturn );
|
||||
}
|
||||
|
||||
|
||||
public byte[] getImplementationId() {
|
||||
byte[] byteReturn = {};
|
||||
|
||||
byteReturn = new String( "" + this.hashCode() ).getBytes();
|
||||
|
||||
return( byteReturn );
|
||||
}
|
||||
|
||||
// Implement method from interface XServiceName
|
||||
public String getServiceName() {
|
||||
return( __serviceName );
|
||||
}
|
||||
|
||||
// Implement methods from interface XServiceInfo
|
||||
public boolean supportsService(String stringServiceName) {
|
||||
return( stringServiceName.equals( __serviceName ) );
|
||||
}
|
||||
|
||||
public String getImplementationName() {
|
||||
return( __implementationName );
|
||||
}
|
||||
|
||||
public String[] getSupportedServiceNames() {
|
||||
String[] stringSupportedServiceNames = { __serviceName };
|
||||
return( stringSupportedServiceNames );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,541 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-16)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import com.sun.star.lib.uno.adapter.XInputStreamToInputStreamAdapter;
|
||||
import com.sun.star.lib.uno.adapter.XOutputStreamToOutputStreamAdapter;
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.beans.UnknownPropertyException;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.document.XDocumentInfoSupplier;
|
||||
import com.sun.star.frame.XComponentLoader;
|
||||
import com.sun.star.frame.XStorable;
|
||||
import com.sun.star.io.NotConnectedException;
|
||||
import com.sun.star.io.XInputStream;
|
||||
import com.sun.star.io.XOutputStream;
|
||||
import com.sun.star.lang.WrappedTargetException;
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XServiceName;
|
||||
import com.sun.star.lang.XTypeProvider;
|
||||
import com.sun.star.sheet.XSpreadsheetDocument;
|
||||
import com.sun.star.text.XTextDocument;
|
||||
import com.sun.star.ucb.CommandAbortedException;
|
||||
import com.sun.star.ucb.XSimpleFileAccess2;
|
||||
import com.sun.star.uno.AnyConverter;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
//import writer2latex.api.BatchConverter;
|
||||
//import writer2latex.api.BatchHandler;
|
||||
//import writer2latex.api.Converter;
|
||||
import writer2latex.api.ConverterFactory;
|
||||
import writer2latex.api.IndexPageEntry;
|
||||
import writer2latex.api.MIMETypes;
|
||||
import writer2latex.api.OutputFile;
|
||||
|
||||
// Import interfaces as defined in uno idl
|
||||
import org.openoffice.da.writer2xhtml.XBatchConverter;
|
||||
import org.openoffice.da.writer2xhtml.XBatchHandler;
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
|
||||
/** This class provides a uno component which implements the interface
|
||||
* org.openoffice.da.writer2xhtml.XBatchConverter
|
||||
*/
|
||||
public class BatchConverter implements
|
||||
XBatchConverter,
|
||||
XServiceName,
|
||||
XServiceInfo,
|
||||
XTypeProvider {
|
||||
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static final String __serviceName = "org.openoffice.da.writer2xhtml.BatchConverter";
|
||||
|
||||
public static final String __implementationName = "org.openoffice.da.comp.writer2xhtml.BatchConverter";
|
||||
|
||||
private XComponentContext xComponentContext = null;
|
||||
|
||||
private XSimpleFileAccess2 sfa2 = null;
|
||||
private writer2latex.api.BatchConverter batchConverter = null;
|
||||
|
||||
private XBatchHandler handler;
|
||||
|
||||
// Based on convert arguments
|
||||
private boolean bRecurse = true;
|
||||
private String sWriterFilterName = "org.openoffice.da.writer2xhtml";
|
||||
private Object writerFilterData = null;
|
||||
private String sCalcFilterName = "org.openoffice.da.calc2xhtml";
|
||||
private Object calcFilterData = null;
|
||||
private boolean bIncludePdf = true;
|
||||
private boolean bIncludeOriginal = false;
|
||||
private boolean bUseTitle = true;
|
||||
private boolean bUseDescription = true;
|
||||
private String sUplink = "";
|
||||
private String sDirectoryIcon = "";
|
||||
private String sDocumentIcon = "";
|
||||
private String sTemplateURL = null;
|
||||
|
||||
public BatchConverter(XComponentContext xComponentContext) {
|
||||
this.xComponentContext = xComponentContext;
|
||||
// Get the SimpleFileAccess service
|
||||
try {
|
||||
Object sfaObject = xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.ucb.SimpleFileAccess", xComponentContext);
|
||||
sfa2 = (XSimpleFileAccess2) UnoRuntime.queryInterface(XSimpleFileAccess2.class, sfaObject);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// failed to get SimpleFileAccess service (should not happen)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper: Get a string from an any
|
||||
private String getValue(Object any) {
|
||||
if (AnyConverter.isString(any)) {
|
||||
try {
|
||||
return AnyConverter.toString(any);
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of XBatchConverter:
|
||||
public void convert(String sSourceURL, String sTargetURL, PropertyValue[] lArguments, XBatchHandler handler) {
|
||||
// Create batch converter (currently we don't need to set a converter)
|
||||
batchConverter = ConverterFactory.createBatchConverter(MIMETypes.XHTML);
|
||||
|
||||
this.handler = handler;
|
||||
|
||||
// Read the arguments
|
||||
int nSize = lArguments.length;
|
||||
for (int i=0; i<nSize; i++) {
|
||||
String sName = lArguments[i].Name;
|
||||
Object value = lArguments[i].Value;
|
||||
if ("Recurse".equals(sName)) {
|
||||
bRecurse = !"false".equals(getValue(value));
|
||||
}
|
||||
else if ("IncludePdf".equals(sName)) {
|
||||
bIncludePdf = !"false".equals(getValue(value));
|
||||
}
|
||||
else if ("IncludeOriginal".equals(sName)) {
|
||||
bIncludeOriginal = "true".equals(getValue(value));
|
||||
|
||||
}
|
||||
else if ("UseTitle".equals(sName)) {
|
||||
bUseTitle = !"false".equals(getValue(value));
|
||||
}
|
||||
else if ("UseDescription".equals(sName)) {
|
||||
bUseDescription = !"false".equals(getValue(value));
|
||||
}
|
||||
else if ("Uplink".equals(sName)) {
|
||||
sUplink = getValue(value);
|
||||
}
|
||||
else if ("DirectoryIcon".equals(sName)) {
|
||||
sDirectoryIcon = getValue(value);
|
||||
}
|
||||
else if ("DocumentIcon".equals(sName)) {
|
||||
sDocumentIcon = getValue(value);
|
||||
}
|
||||
else if ("TemplateURL".equals(sName)) {
|
||||
sTemplateURL = getValue(value);
|
||||
}
|
||||
else if ("WriterFilterName".equals(sName)) {
|
||||
sWriterFilterName = getValue(value);
|
||||
}
|
||||
else if ("WriterFilterData".equals(sName)) {
|
||||
writerFilterData = lArguments[i].Value;
|
||||
}
|
||||
else if ("CalcFilterName".equals(sName)) {
|
||||
sCalcFilterName = getValue(value);
|
||||
}
|
||||
else if ("CalcFilterData".equals(sName)) {
|
||||
calcFilterData = lArguments[i].Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Set arguments on batch converter
|
||||
batchConverter.getConfig().setOption("uplink", sUplink);
|
||||
batchConverter.getConfig().setOption("directory_icon", sDirectoryIcon);
|
||||
batchConverter.getConfig().setOption("document_icon", sDocumentIcon);
|
||||
if (sTemplateURL!=null) {
|
||||
try {
|
||||
XInputStream xis = sfa2.openFileRead(sTemplateURL);
|
||||
XInputStreamToInputStreamAdapter isa = new XInputStreamToInputStreamAdapter(xis);
|
||||
batchConverter.readTemplate(isa);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// The batchconverter failed to read the template
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// The sfa could not execute the command
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Unspecified uno exception
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the directory
|
||||
handler.startConversion();
|
||||
convertDirectory(sSourceURL, sTargetURL, getName(sSourceURL));
|
||||
handler.endConversion();
|
||||
}
|
||||
|
||||
// Convert a directory - return true if not cancelled
|
||||
private boolean convertDirectory(String sSourceURL, String sTargetURL, String sHeading) {
|
||||
handler.startDirectory(sSourceURL);
|
||||
|
||||
// Step 1: Get the directory
|
||||
String[] contents;
|
||||
try {
|
||||
contents = sfa2.getFolderContents(sSourceURL, true);
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
int nLen = contents.length;
|
||||
IndexPageEntry[] entries = new IndexPageEntry[nLen];
|
||||
|
||||
// Step 2: Traverse subdirectories, if allowed
|
||||
if (bRecurse) {
|
||||
String sUplink = batchConverter.getConfig().getOption("uplink");
|
||||
for (int i=0; i<nLen; i++) {
|
||||
boolean bIsDirectory = false;
|
||||
try {
|
||||
bIsDirectory = sfa2.isFolder(contents[i]);
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// Considered non critical, ignore
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Considered non critical, ignore
|
||||
}
|
||||
if (bIsDirectory) {
|
||||
batchConverter.getConfig().setOption("uplink","../index.html");
|
||||
String sNewTargetURL = ensureSlash(sTargetURL) + getName(contents[i]);
|
||||
String sNewHeading = sHeading + " - " + decodeURL(getName(contents[i]));
|
||||
boolean bResult = convertDirectory(contents[i],sNewTargetURL,sNewHeading);
|
||||
batchConverter.getConfig().setOption("uplink", sUplink);
|
||||
if (!bResult) { return false; }
|
||||
// Create entry for this subdirectory
|
||||
IndexPageEntry entry = new IndexPageEntry(ensureSlash(sNewTargetURL)+"index.html",true);
|
||||
entry.setDisplayName(decodeURL(getName(contents[i])));
|
||||
entries[i]=entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Traverse documents
|
||||
for (int i=0; i<nLen; i++) {
|
||||
boolean bIsFile = false;
|
||||
try {
|
||||
bIsFile = sfa2.exists(contents[i]) && !sfa2.isFolder(contents[i]);
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// Considered non critical, ignore
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Considered non critical, ignore
|
||||
}
|
||||
if (bIsFile) {
|
||||
IndexPageEntry entry = convertFile(contents[i],sTargetURL);
|
||||
if (entry!=null) { entries[i]=entry; }
|
||||
if (handler.cancel()) { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Create and write out the index file
|
||||
OutputFile indexFile = batchConverter.createIndexFile(sHeading, entries);
|
||||
|
||||
try {
|
||||
if (!sfa2.exists(sTargetURL)) { sfa2.createFolder(sTargetURL); }
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
// writeFile demands an InputStream, so we need a pipe
|
||||
Object xPipeObj=xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.io.Pipe",xComponentContext);
|
||||
XInputStream xInStream
|
||||
= (XInputStream) UnoRuntime.queryInterface(XInputStream.class, xPipeObj );
|
||||
XOutputStream xOutStream
|
||||
= (XOutputStream) UnoRuntime.queryInterface(XOutputStream.class, xPipeObj );
|
||||
OutputStream outStream = new XOutputStreamToOutputStreamAdapter(xOutStream);
|
||||
// Feed the pipe with content...
|
||||
indexFile.write(outStream);
|
||||
outStream.flush();
|
||||
outStream.close();
|
||||
xOutStream.closeOutput();
|
||||
// ...and then write the content to the url
|
||||
sfa2.writeFile(ensureSlash(sTargetURL)+"index.html",xInStream);
|
||||
}
|
||||
catch (IOException e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
catch (NotConnectedException e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
|
||||
handler.endDirectory(sSourceURL, true);
|
||||
|
||||
return !handler.cancel();
|
||||
}
|
||||
|
||||
private IndexPageEntry convertFile(String sSourceFileURL, String sTargetURL) {
|
||||
handler.startFile(sSourceFileURL);
|
||||
|
||||
String sTargetFileURL = ensureSlash(sTargetURL) + getBaseName(sSourceFileURL) + ".html";
|
||||
|
||||
IndexPageEntry entry = new IndexPageEntry(getName(sTargetFileURL),false);
|
||||
entry.setDisplayName(decodeURL(getBaseName(sTargetFileURL)));
|
||||
|
||||
// Load component
|
||||
XComponent xDocument;
|
||||
try {
|
||||
Object desktop = xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.frame.Desktop", xComponentContext);
|
||||
|
||||
XComponentLoader xComponentLoader = (XComponentLoader)
|
||||
UnoRuntime.queryInterface(XComponentLoader.class, desktop);
|
||||
|
||||
PropertyValue[] fileProps = new PropertyValue[1];
|
||||
fileProps[0] = new PropertyValue();
|
||||
fileProps[0].Name = "Hidden";
|
||||
fileProps[0].Value = new Boolean(true);
|
||||
|
||||
xDocument = xComponentLoader.loadComponentFromURL(sSourceFileURL, "_blank", 0, fileProps);
|
||||
}
|
||||
catch (com.sun.star.io.IOException e) {
|
||||
handler.endFile(sSourceFileURL,false);
|
||||
return null;
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
handler.endFile(sSourceFileURL,false);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the title and the description of the document
|
||||
XDocumentInfoSupplier docInfo = (XDocumentInfoSupplier) UnoRuntime.queryInterface(XDocumentInfoSupplier.class, xDocument);
|
||||
XPropertySet infoProps = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, docInfo.getDocumentInfo());
|
||||
if (infoProps!=null) {
|
||||
try {
|
||||
Object loadedTitle = infoProps.getPropertyValue("Title");
|
||||
if (AnyConverter.isString(loadedTitle)) {
|
||||
String sLoadedTitle = AnyConverter.toString(loadedTitle);
|
||||
if (bUseTitle && sLoadedTitle.length()>0) {
|
||||
entry.setDisplayName(sLoadedTitle);
|
||||
}
|
||||
}
|
||||
|
||||
Object loadedDescription = infoProps.getPropertyValue("Description");
|
||||
if (AnyConverter.isString(loadedDescription)) {
|
||||
String sLoadedDescription = AnyConverter.toString(loadedDescription);
|
||||
if (bUseDescription && sLoadedDescription.length()>0) {
|
||||
entry.setDescription(sLoadedDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (UnknownPropertyException e) {
|
||||
}
|
||||
catch (WrappedTargetException e) {
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the type of the component
|
||||
boolean bText = false;
|
||||
boolean bSpreadsheet = false;
|
||||
if (UnoRuntime.queryInterface(XTextDocument.class, xDocument)!=null) { bText=true; }
|
||||
else if (UnoRuntime.queryInterface(XSpreadsheetDocument.class, xDocument)!=null) { bSpreadsheet=true; }
|
||||
if (!bText && !bSpreadsheet) {
|
||||
handler.endFile(sSourceFileURL,false);
|
||||
xDocument.dispose();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert using requested filter
|
||||
boolean bHtmlSuccess = true;
|
||||
|
||||
PropertyHelper exportProps = new PropertyHelper();
|
||||
exportProps.put("FilterName", bText ? sWriterFilterName : sCalcFilterName);
|
||||
exportProps.put("Overwrite", new Boolean(true));
|
||||
if (bText && writerFilterData!=null) { exportProps.put("FilterData", writerFilterData); }
|
||||
if (bSpreadsheet && calcFilterData!=null) { exportProps.put("FilterData", calcFilterData); }
|
||||
|
||||
try {
|
||||
XStorable xStore = (XStorable) UnoRuntime.queryInterface (XStorable.class, xDocument);
|
||||
xStore.storeToURL (sTargetFileURL, exportProps.toArray());
|
||||
}
|
||||
catch (com.sun.star.io.IOException e) {
|
||||
// Failed to convert; continue anyway, but don't link to the file name
|
||||
entry.setFile(null);
|
||||
bHtmlSuccess = false;
|
||||
}
|
||||
|
||||
// Convet to pdf if requested
|
||||
boolean bPdfSuccess = true;
|
||||
|
||||
if (bIncludePdf) {
|
||||
PropertyValue[] pdfProps = new PropertyValue[2];
|
||||
pdfProps[0] = new PropertyValue();
|
||||
pdfProps[0].Name = "FilterName";
|
||||
pdfProps[0].Value = bText ? "writer_pdf_Export" : "calc_pdf_Export";
|
||||
pdfProps[1] = new PropertyValue();
|
||||
pdfProps[1].Name = "Overwrite";
|
||||
pdfProps[1].Value = new Boolean(true);
|
||||
|
||||
String sPdfFileURL = ensureSlash(sTargetURL) + getBaseName(sSourceFileURL) + ".pdf";
|
||||
|
||||
try {
|
||||
XStorable xStore = (XStorable) UnoRuntime.queryInterface (XStorable.class, xDocument);
|
||||
xStore.storeToURL (sPdfFileURL, pdfProps);
|
||||
entry.setPdfFile(sPdfFileURL);
|
||||
}
|
||||
catch (com.sun.star.io.IOException e) {
|
||||
// Not critical, continue without pdf
|
||||
bPdfSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
xDocument.dispose();
|
||||
|
||||
// Include original document if required
|
||||
if (bIncludeOriginal) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Report a failure to the user if either of the exports failed
|
||||
handler.endFile(sSourceFileURL,bHtmlSuccess && bPdfSuccess);
|
||||
// But return the index entry even if only one succeded
|
||||
if (bHtmlSuccess || bPdfSuccess) { return entry; }
|
||||
else { return null; }
|
||||
}
|
||||
|
||||
private String getName(String sURL) {
|
||||
int n = sURL.lastIndexOf("/");
|
||||
return n>-1 ? sURL.substring(n+1) : sURL;
|
||||
}
|
||||
|
||||
private String getBaseName(String sURL) {
|
||||
String sName = getName(sURL);
|
||||
int n = sName.lastIndexOf(".");
|
||||
return n>-1 ? sName.substring(0,n) : sName;
|
||||
}
|
||||
|
||||
private String ensureSlash(String sURL) {
|
||||
return sURL.endsWith("/") ? sURL : sURL+"/";
|
||||
}
|
||||
|
||||
private String decodeURL(String sURL) {
|
||||
try {
|
||||
return new URI(sURL).getPath();
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
return sURL;
|
||||
}
|
||||
}
|
||||
|
||||
// Implement methods from interface XTypeProvider
|
||||
|
||||
public com.sun.star.uno.Type[] getTypes() {
|
||||
Type[] typeReturn = {};
|
||||
try {
|
||||
typeReturn = new Type[] {
|
||||
new Type( XBatchConverter.class ),
|
||||
new Type( XTypeProvider.class ),
|
||||
new Type( XServiceName.class ),
|
||||
new Type( XServiceInfo.class ) };
|
||||
}
|
||||
catch( Exception exception ) {
|
||||
|
||||
}
|
||||
|
||||
return( typeReturn );
|
||||
}
|
||||
|
||||
|
||||
public byte[] getImplementationId() {
|
||||
byte[] byteReturn = {};
|
||||
|
||||
byteReturn = new String( "" + this.hashCode() ).getBytes();
|
||||
|
||||
return( byteReturn );
|
||||
}
|
||||
|
||||
// Implement method from interface XServiceName
|
||||
public String getServiceName() {
|
||||
return( __serviceName );
|
||||
}
|
||||
|
||||
// Implement methods from interface XServiceInfo
|
||||
public boolean supportsService(String stringServiceName) {
|
||||
return( stringServiceName.equals( __serviceName ) );
|
||||
}
|
||||
|
||||
public String getImplementationName() {
|
||||
return( __implementationName );
|
||||
}
|
||||
|
||||
public String[] getSupportedServiceNames() {
|
||||
String[] stringSupportedServiceNames = { __serviceName };
|
||||
return( stringSupportedServiceNames );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchHandlerAdapter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-05)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import writer2latex.api.BatchHandler;
|
||||
import org.openoffice.da.writer2xhtml.XBatchHandler;
|
||||
|
||||
/** The uno interface provides an XBatchHandler implementation, the java
|
||||
* interface requires a BatchHandler implementation. This simple class
|
||||
* implements the latter using an instance of the former.
|
||||
*/
|
||||
public class BatchHandlerAdapter implements BatchHandler {
|
||||
|
||||
private XBatchHandler unoHandler;
|
||||
|
||||
public BatchHandlerAdapter(XBatchHandler unoHandler) {
|
||||
this.unoHandler = unoHandler;
|
||||
}
|
||||
|
||||
public void startConversion() {
|
||||
unoHandler.startConversion();
|
||||
}
|
||||
|
||||
public void endConversion() {
|
||||
unoHandler.endConversion();
|
||||
}
|
||||
|
||||
public void startDirectory(String sName) {
|
||||
unoHandler.startDirectory(sName);
|
||||
}
|
||||
|
||||
public void endDirectory(String sName, boolean bSuccess) {
|
||||
unoHandler.endDirectory(sName, bSuccess);
|
||||
}
|
||||
|
||||
public void startFile(String sName) {
|
||||
unoHandler.startFile(sName);
|
||||
}
|
||||
|
||||
public void endFile(String sName, boolean bSuccess) {
|
||||
unoHandler.endFile(sName, bSuccess);
|
||||
}
|
||||
|
||||
public boolean cancel() {
|
||||
return unoHandler.cancel();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* W2XExportFilter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.filter.ExportFilterBase;
|
||||
|
||||
|
||||
/** This class implements the xhtml export filter component
|
||||
*/
|
||||
public class W2XExportFilter extends ExportFilterBase {
|
||||
|
||||
/** Service name for the component */
|
||||
public static final String __serviceName = "org.openoffice.da.comp.writer2xhtml.W2XExportFilter";
|
||||
|
||||
/** Implementation name for the component */
|
||||
public static final String __implementationName = "org.openoffice.da.comp.writer2xhtml.W2XExportFilter";
|
||||
|
||||
/** Filter name to include in error messages */
|
||||
public static final String __displayName = "Writer2xhtml";
|
||||
|
||||
public W2XExportFilter(XComponentContext xComponentContext1) {
|
||||
super(xComponentContext1);
|
||||
xMSF = W2XRegistration.xMultiServiceFactory;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* W2XRegistration.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-04)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
|
||||
/** This class provides a static method to instantiate our uno components
|
||||
* on demand (__getServiceFactory()), and a static method to give
|
||||
* information about the components (__writeRegistryServiceInfo()).
|
||||
* Furthermore, it saves the XMultiServiceFactory provided to the
|
||||
* __getServiceFactory method for future reference by the componentes.
|
||||
*/
|
||||
public class W2XRegistration {
|
||||
|
||||
public static XMultiServiceFactory xMultiServiceFactory;
|
||||
|
||||
/**
|
||||
* Returns a factory for creating the service.
|
||||
* This method is called by the <code>JavaLoader</code>
|
||||
*
|
||||
* @return returns a <code>XSingleServiceFactory</code> for creating the
|
||||
* component
|
||||
*
|
||||
* @param implName the name of the implementation for which a
|
||||
* service is desired
|
||||
* @param multiFactory the service manager to be used if needed
|
||||
* @param regKey the registryKey
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(String implName,
|
||||
XMultiServiceFactory multiFactory, XRegistryKey regKey) {
|
||||
xMultiServiceFactory = multiFactory;
|
||||
XSingleServiceFactory xSingleServiceFactory = null;
|
||||
if (implName.equals(W2XExportFilter.class.getName()) ) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(W2XExportFilter.class,
|
||||
W2XExportFilter.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(BatchConverter.__implementationName) ) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(BatchConverter.class,
|
||||
BatchConverter.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(XhtmlOptionsDialog.__implementationName)) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(XhtmlOptionsDialog.class,
|
||||
XhtmlOptionsDialog.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(XhtmlOptionsDialogXsl.__implementationName)) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(XhtmlOptionsDialogXsl.class,
|
||||
XhtmlOptionsDialogXsl.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(XhtmlOptionsDialogCalc.__implementationName)) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(XhtmlOptionsDialogCalc.class,
|
||||
XhtmlOptionsDialogCalc.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
|
||||
return xSingleServiceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the service information into the given registry key.
|
||||
* This method is called by the <code>JavaLoader</code>
|
||||
* <p>
|
||||
* @return returns true if the operation succeeded
|
||||
* @param regKey the registryKey
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) {
|
||||
return
|
||||
FactoryHelper.writeRegistryServiceInfo(BatchConverter.__implementationName,
|
||||
BatchConverter.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(W2XExportFilter.__implementationName,
|
||||
W2XExportFilter.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(XhtmlOptionsDialog.__implementationName,
|
||||
XhtmlOptionsDialog.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(XhtmlOptionsDialogXsl.__implementationName,
|
||||
XhtmlOptionsDialogXsl.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(XhtmlOptionsDialogCalc.__implementationName,
|
||||
XhtmlOptionsDialogCalc.__serviceName, regKey);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* XhtmlOptionsDialog.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-16)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import com.sun.star.awt.XDialog;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
import org.openoffice.da.comp.w2lcommon.filter.OptionsDialogBase;
|
||||
|
||||
/** This class provides a uno component which implements a filter ui for the
|
||||
* Xhtml export
|
||||
*/
|
||||
public class XhtmlOptionsDialog extends OptionsDialogBase {
|
||||
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static String __serviceName = "org.openoffice.da.writer2xhtml.XhtmlOptionsDialog";
|
||||
|
||||
/** The component should also have an implementation name.
|
||||
*/
|
||||
public static String __implementationName = "org.openoffice.da.comp.writer2xhtml.XhtmlOptionsDialog";
|
||||
|
||||
public String getDialogLibraryName() { return "W2XDialogs"; }
|
||||
|
||||
/** Return the name of the dialog within the library
|
||||
*/
|
||||
public String getDialogName() { return "XhtmlOptions"; }
|
||||
|
||||
/** Return the name of the registry path
|
||||
*/
|
||||
public String getRegistryPath() {
|
||||
return "/org.openoffice.da.Writer2xhtml.Options/XhtmlOptions";
|
||||
}
|
||||
|
||||
/** Create a new XhtmlOptionsDialog */
|
||||
public XhtmlOptionsDialog(XComponentContext xContext) {
|
||||
super(xContext);
|
||||
xMSF = W2XRegistration.xMultiServiceFactory;
|
||||
}
|
||||
|
||||
/** Load settings from the registry to the dialog */
|
||||
protected void loadSettings(XPropertySet xProps) {
|
||||
// Style
|
||||
loadConfig(xProps);
|
||||
loadCheckBoxOption(xProps, "ConvertToPx");
|
||||
loadNumericOption(xProps, "Scaling");
|
||||
loadNumericOption(xProps, "ColumnScaling");
|
||||
loadCheckBoxOption(xProps, "OriginalImageSize");
|
||||
|
||||
// Special content
|
||||
loadCheckBoxOption(xProps, "Notes");
|
||||
loadCheckBoxOption(xProps, "UseDublinCore");
|
||||
|
||||
// AutoCorrect
|
||||
loadCheckBoxOption(xProps, "IgnoreHardLineBreaks");
|
||||
loadCheckBoxOption(xProps, "IgnoreEmptyParagraphs");
|
||||
loadCheckBoxOption(xProps, "IgnoreDoubleSpaces");
|
||||
|
||||
// Files
|
||||
loadCheckBoxOption(xProps, "Split");
|
||||
loadListBoxOption(xProps, "SplitLevel");
|
||||
loadListBoxOption(xProps, "RepeatLevels");
|
||||
loadCheckBoxOption(xProps, "SaveImagesInSubdir");
|
||||
loadTextFieldOption(xProps, "XsltPath");
|
||||
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
|
||||
/** Save settings from the dialog to the registry and create FilterData */
|
||||
protected void saveSettings(XPropertySet xProps, PropertyHelper helper) {
|
||||
// Style
|
||||
short nConfig = saveConfig(xProps, helper);
|
||||
String[] sCoreStyles = { "Chocolate", "Midnight", "Modernist",
|
||||
"Oldstyle", "Steely", "Swiss", "Traditional", "Ultramarine" };
|
||||
switch (nConfig) {
|
||||
case 0: helper.put("ConfigURL","*default.xml"); break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8: helper.put("ConfigURL","*cleanxhtml.xml");
|
||||
helper.put("custom_stylesheet",
|
||||
"http://www.w3.org/StyleSheets/Core/"+sCoreStyles[nConfig-1]);
|
||||
break;
|
||||
case 9: helper.put("ConfigURL","$(user)/writer2xhtml.xml");
|
||||
helper.put("AutoCreate","true");
|
||||
}
|
||||
|
||||
saveCheckBoxOption(xProps, helper, "ConvertToPx", "convert_to_px");
|
||||
saveNumericOptionAsPercentage(xProps, helper, "Scaling", "scaling");
|
||||
saveNumericOptionAsPercentage(xProps, helper, "ColumnScaling", "column_scaling");
|
||||
saveCheckBoxOption(xProps, helper, "OriginalImageSize", "original_image_size");
|
||||
|
||||
// Special content
|
||||
saveCheckBoxOption(xProps, helper, "Notes", "notes");
|
||||
saveCheckBoxOption(xProps, helper, "UseDublinCore", "use_dublin_core");
|
||||
|
||||
// AutoCorrect
|
||||
saveCheckBoxOption(xProps, helper, "IgnoreHardLineBreaks", "ignore_hard_line_breaks");
|
||||
saveCheckBoxOption(xProps, helper, "IgnoreEmptyParagraphs", "ignore_empty_paragraphs");
|
||||
saveCheckBoxOption(xProps, helper, "IgnoreDoubleSpaces", "ignore_double_spaces");
|
||||
|
||||
// Files
|
||||
boolean bSplit = saveCheckBoxOption(xProps, "Split");
|
||||
short nSplitLevel = saveListBoxOption(xProps, "SplitLevel");
|
||||
short nRepeatLevels = saveListBoxOption(xProps, "RepeatLevels");
|
||||
if (!isLocked("split_level")) {
|
||||
if (bSplit) {
|
||||
helper.put("split_level",Integer.toString(nSplitLevel+1));
|
||||
helper.put("repeat_levels",Integer.toString(nRepeatLevels));
|
||||
}
|
||||
else {
|
||||
helper.put("split_level","0");
|
||||
}
|
||||
}
|
||||
|
||||
saveCheckBoxOption(xProps, helper, "SaveImagesInSubdir", "save_images_in_subdir");
|
||||
saveTextFieldOption(xProps, helper, "XsltPath", "xslt_path");
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Implement XDialogEventHandler
|
||||
public boolean callHandlerMethod(XDialog xDialog, Object event, String sMethod) {
|
||||
if (sMethod.equals("ConfigChange")) {
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
else if (sMethod.equals("SplitChange")) {
|
||||
enableSplitLevel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getSupportedMethodNames() {
|
||||
String[] sNames = { "ConfigChange", "SplitChange" };
|
||||
return sNames;
|
||||
}
|
||||
|
||||
private void enableControls() {
|
||||
// Style
|
||||
setControlEnabled("ScalingLabel",!isLocked("scaling"));
|
||||
setControlEnabled("Scaling",!isLocked("scaling"));
|
||||
setControlEnabled("ColumnScalingLabel",!isLocked("column_scaling"));
|
||||
setControlEnabled("ColumnScaling",!isLocked("column_scaling"));
|
||||
setControlEnabled("ConvertToPx",!isLocked("convert_to_px"));
|
||||
setControlEnabled("OriginalImageSize",!isLocked("original_image_size"));
|
||||
|
||||
// Special content
|
||||
setControlEnabled("Notes",!isLocked("notes"));
|
||||
setControlEnabled("UseDublinCore",!isLocked("use_dublin_core"));
|
||||
|
||||
// AutoCorrect
|
||||
setControlEnabled("IgnoreHardLineBreaks",!isLocked("ignore_hard_line_breaks"));
|
||||
setControlEnabled("IgnoreEmptyParagraphs",!isLocked("ignore_empty_paragraphs"));
|
||||
setControlEnabled("IgnoreDoubleSpaces",!isLocked("ignore_double_spaces"));
|
||||
|
||||
// Files
|
||||
boolean bSplit = getCheckBoxStateAsBoolean("Split");
|
||||
setControlEnabled("Split",!isLocked("split_level"));
|
||||
setControlEnabled("SplitLevelLabel",!isLocked("split_level") && bSplit);
|
||||
setControlEnabled("SplitLevel",!isLocked("split_level") && bSplit);
|
||||
setControlEnabled("RepeatLevelsLabel",!isLocked("repeat_levels") && !isLocked("split_level") && bSplit);
|
||||
setControlEnabled("RepeatLevels",!isLocked("repeat_levels") && !isLocked("split_level") && bSplit);
|
||||
setControlEnabled("SaveImagesInSubdir",!isLocked("save_images_in_subdir"));
|
||||
setControlEnabled("XsltPathLabel",(this instanceof XhtmlOptionsDialogXsl) && !isLocked("xslt_path"));
|
||||
setControlEnabled("XsltPath",(this instanceof XhtmlOptionsDialogXsl) && !isLocked("xslt_path"));
|
||||
}
|
||||
|
||||
private void enableSplitLevel() {
|
||||
if (!isLocked("split_level")) {
|
||||
boolean bState = getCheckBoxStateAsBoolean("Split");
|
||||
setControlEnabled("SplitLevelLabel",bState);
|
||||
setControlEnabled("SplitLevel",bState);
|
||||
if (!isLocked("repeat_levels")) {
|
||||
setControlEnabled("RepeatLevelsLabel",bState);
|
||||
setControlEnabled("RepeatLevels",bState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* XhtmlOptionsDialogCalc.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-18)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import com.sun.star.awt.XDialog;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
import org.openoffice.da.comp.w2lcommon.filter.OptionsDialogBase;
|
||||
|
||||
/** This class provides a uno component which implements a filter ui for the
|
||||
* Xhtml export in Calc
|
||||
*/
|
||||
public class XhtmlOptionsDialogCalc extends OptionsDialogBase {
|
||||
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static String __serviceName = "org.openoffice.da.writerxhtml.XhtmlOptionsDialogCalc";
|
||||
|
||||
/** The component should also have an implementation name.
|
||||
*/
|
||||
public static String __implementationName = "org.openoffice.da.comp.writer2xhtml.XhtmlOptionsDialogCalc";
|
||||
|
||||
public String getDialogLibraryName() { return "W2XDialogs"; }
|
||||
|
||||
/** Return the name of the dialog within the library
|
||||
*/
|
||||
public String getDialogName() { return "XhtmlOptionsCalc"; }
|
||||
|
||||
/** Return the name of the registry path
|
||||
*/
|
||||
public String getRegistryPath() {
|
||||
return "/org.openoffice.da.Writer2xhtml.Options/XhtmlOptionsCalc";
|
||||
}
|
||||
|
||||
/** Create a new XhtmlOptionsDialogCalc */
|
||||
public XhtmlOptionsDialogCalc(XComponentContext xContext) {
|
||||
super(xContext);
|
||||
xMSF = W2XRegistration.xMultiServiceFactory;
|
||||
}
|
||||
|
||||
/** Load settings from the registry to the dialog */
|
||||
protected void loadSettings(XPropertySet xProps) {
|
||||
// Style
|
||||
loadConfig(xProps);
|
||||
loadCheckBoxOption(xProps, "ConvertToPx");
|
||||
loadNumericOption(xProps, "Scaling");
|
||||
loadNumericOption(xProps, "ColumnScaling");
|
||||
loadCheckBoxOption(xProps, "OriginalImageSize");
|
||||
|
||||
// Special content
|
||||
loadCheckBoxOption(xProps, "Notes");
|
||||
loadCheckBoxOption(xProps, "UseDublinCore");
|
||||
|
||||
// Sheets
|
||||
loadCheckBoxOption(xProps, "DisplayHiddenSheets");
|
||||
loadCheckBoxOption(xProps, "DisplayHiddenRowsCols");
|
||||
loadCheckBoxOption(xProps, "DisplayFilteredRowsCols");
|
||||
loadCheckBoxOption(xProps, "ApplyPrintRanges");
|
||||
loadCheckBoxOption(xProps, "UseTitleAsHeading");
|
||||
loadCheckBoxOption(xProps, "UseSheetNamesAsHeadings");
|
||||
|
||||
// Files
|
||||
loadCheckBoxOption(xProps, "CalcSplit");
|
||||
loadCheckBoxOption(xProps, "SaveImagesInSubdir");
|
||||
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
|
||||
/** Save settings from the dialog to the registry and create FilterData */
|
||||
protected void saveSettings(XPropertySet xProps, PropertyHelper helper) {
|
||||
// Style
|
||||
short nConfig = saveConfig(xProps, helper);
|
||||
if (nConfig==0) {
|
||||
helper.put("ConfigURL","*default.xml");
|
||||
}
|
||||
else if (nConfig==1) {
|
||||
helper.put("ConfigURL","$(user)/writer2xhtml.xml");
|
||||
helper.put("AutoCreate","true");
|
||||
}
|
||||
|
||||
saveCheckBoxOption(xProps, helper, "ConvertToPx", "convert_to_px");
|
||||
saveNumericOptionAsPercentage(xProps, helper, "Scaling", "scaling");
|
||||
saveNumericOptionAsPercentage(xProps, helper, "ColumnScaling", "column_scaling");
|
||||
saveCheckBoxOption(xProps, helper, "OriginalImageSize", "original_image_size");
|
||||
|
||||
// Special content
|
||||
saveCheckBoxOption(xProps, helper, "Notes", "notes");
|
||||
saveCheckBoxOption(xProps, helper, "UseDublinCore", "use_dublin_core");
|
||||
|
||||
// Sheets
|
||||
saveCheckBoxOption(xProps, helper, "DisplayHiddenSheets", "display_hidden_sheets");
|
||||
saveCheckBoxOption(xProps, helper, "DisplayHiddenRowsCols", "display_hidden_rows_cols");
|
||||
saveCheckBoxOption(xProps, helper, "DisplayFilteredRowsCols", "display_filtered_rows_cols");
|
||||
saveCheckBoxOption(xProps, helper, "ApplyPrintRanges", "apply_print_ranges");
|
||||
saveCheckBoxOption(xProps, helper, "UseTitleAsHeading", "use_title_as_heading");
|
||||
saveCheckBoxOption(xProps, helper, "UseSheetNamesAsHeadings", "use_sheet_names_as_headings");
|
||||
|
||||
// Files
|
||||
saveCheckBoxOption(xProps, helper, "CalcSplit", "calc_split");
|
||||
saveCheckBoxOption(xProps, helper, "SaveImagesInSubdir", "save_images_in_subdir");
|
||||
|
||||
}
|
||||
|
||||
// Implement XDialogEventHandler
|
||||
public boolean callHandlerMethod(XDialog xDialog, Object event, String sMethod) {
|
||||
if (sMethod.equals("ConfigChange")) {
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getSupportedMethodNames() {
|
||||
String[] sNames = { "ConfigChange" };
|
||||
return sNames;
|
||||
}
|
||||
|
||||
private void enableControls() {
|
||||
// Style
|
||||
setControlEnabled("ConvertToPx",!isLocked("convert_to_px"));
|
||||
setControlEnabled("ScalingLabel",!isLocked("scaling"));
|
||||
setControlEnabled("Scaling",!isLocked("scaling"));
|
||||
setControlEnabled("ColumnScalingLabel",!isLocked("column_scaling"));
|
||||
setControlEnabled("ColumnScaling",!isLocked("column_scaling"));
|
||||
setControlEnabled("OriginalImageSize",!isLocked("original_image_size"));
|
||||
|
||||
// Special content
|
||||
setControlEnabled("Notes",!isLocked("notes"));
|
||||
setControlEnabled("UseDublinCore",!isLocked("use_dublin_core"));
|
||||
|
||||
// Sheets
|
||||
setControlEnabled("DisplayHiddenSheets", !isLocked("display_hidden_sheets"));
|
||||
setControlEnabled("DisplayHiddenRowsCols", !isLocked("display_hidden_rows_cols"));
|
||||
setControlEnabled("DisplayFilteredRowsCols", !isLocked("display_filtered_rows_cols"));
|
||||
setControlEnabled("ApplyPrintRanges", !isLocked("apply_print_ranges"));
|
||||
setControlEnabled("UseTitleAsHeading", !isLocked("use_title_as_heading"));
|
||||
setControlEnabled("UseSheetNamesAsHeadings", !isLocked("use_sheet_names_as_headings"));
|
||||
|
||||
// Files
|
||||
setControlEnabled("CalcSplit",!isLocked("calc_split"));
|
||||
setControlEnabled("SaveImagesInSubdir",!isLocked("save_images_in_subdir"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* XhtmlOptionsDialogXsl.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-11)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
/** This class provides a uno component which implements a filter ui for the
|
||||
* Xhtml export (xsl variant)
|
||||
* This variant of the dialog has the XsltPath setting enabled
|
||||
*/
|
||||
public class XhtmlOptionsDialogXsl extends XhtmlOptionsDialog {
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static String __serviceName = "org.openoffice.da.writer2xhtml.XhtmlOptionsDialogXsl";
|
||||
|
||||
/** The component should also have an implementation name.
|
||||
*/
|
||||
public static String __implementationName = "org.openoffice.da.comp.writer2xhtml.XhtmlOptionsDialogXsl";
|
||||
|
||||
/** Create a new XhtmlOptionsDialogXsl */
|
||||
public XhtmlOptionsDialogXsl(XComponentContext xContext) {
|
||||
super(xContext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
382
source/java/writer2latex/Application.java
Normal file
382
source/java/writer2latex/Application.java
Normal file
|
@ -0,0 +1,382 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Application.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
//import java.io.FileOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
import writer2latex.api.BatchConverter;
|
||||
import writer2latex.api.Converter;
|
||||
import writer2latex.api.ConverterFactory;
|
||||
import writer2latex.api.ConverterResult;
|
||||
import writer2latex.api.MIMETypes;
|
||||
//import writer2latex.api.OutputFile;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/**
|
||||
* <p>Commandline utility to convert an OpenOffice.org Writer XML file into XHTML/LaTeX/BibTeX</p>
|
||||
* <p>The utility is invoked with the following command line:</p>
|
||||
* <pre>java -jar writer2latex.jar [options] source [target]</pre>
|
||||
* <p>Where the available options are
|
||||
* <ul>
|
||||
* <li><code>-latex</code>, <code>-bibtex</code>, <code>-xhtml</code>,
|
||||
<code>-xhtml+mathml</code>, <code>-xhtml+mathml+xsl</code>
|
||||
* <li><code>-recurse</code>
|
||||
* <li><code>-ultraclean</code>, <code>-clean</code>, <code>-pdfscreen</code>,
|
||||
* <code>-pdfprint</code>, <code>-cleanxhtml</code>
|
||||
* <li><code>-config[=]filename</code>
|
||||
* <li><code>-template[=]filename</code>
|
||||
* <li><code>-option[=]value</code>
|
||||
* </ul>
|
||||
* <p>where <code>option</code> can be any simple option known to Writer2LaTeX
|
||||
* (see documentation for the configuration file).</p>
|
||||
*/
|
||||
public final class Application {
|
||||
|
||||
/* Based on command-line parameters. */
|
||||
private String sTargetMIME = MIMETypes.LATEX;
|
||||
private boolean bRecurse = false;
|
||||
private Vector configFileNames = new Vector();
|
||||
private String sTemplateFileName = null;
|
||||
private Hashtable options = new Hashtable();
|
||||
private String sSource = null;
|
||||
private String sTarget = null;
|
||||
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args The argument passed on the command line.
|
||||
*/
|
||||
public static final void main (String[] args){
|
||||
try {
|
||||
Application app = new Application();
|
||||
app.parseCommandLine(args);
|
||||
app.doConversion();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String msg = ex.getMessage();
|
||||
showUsage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the directory or file
|
||||
private void doConversion() {
|
||||
// Step 1: Say hello...
|
||||
String sOutputFormat;
|
||||
if (MIMETypes.LATEX.equals(sTargetMIME)) { sOutputFormat = "LaTeX"; }
|
||||
else if (MIMETypes.BIBTEX.equals(sTargetMIME)) { sOutputFormat = "BibTeX"; }
|
||||
else { sOutputFormat = "xhtml"; }
|
||||
System.out.println();
|
||||
System.out.println("This is Writer2" + sOutputFormat +
|
||||
", Version " + ConverterFactory.getVersion() +
|
||||
" (" + ConverterFactory.getDate() + ")");
|
||||
System.out.println();
|
||||
System.out.println("Starting conversion...");
|
||||
|
||||
// Step 2: Examine source
|
||||
File source = new File(sSource);
|
||||
if (!source.exists()) {
|
||||
System.out.println("I'm sorry, I can't find "+sSource);
|
||||
System.exit(1);
|
||||
}
|
||||
if (!source.canRead()) {
|
||||
System.out.println("I'm sorry, I can't read "+sSource);
|
||||
System.exit(1);
|
||||
}
|
||||
boolean bBatch = source.isDirectory();
|
||||
|
||||
// Step 3: Examine target
|
||||
File target;
|
||||
if (bBatch) {
|
||||
if (sTarget==null) {
|
||||
target=source;
|
||||
}
|
||||
else {
|
||||
target = new File(sTarget);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sTarget==null) {
|
||||
target = new File(source.getParent(),Misc.removeExtension(source.getName()));
|
||||
}
|
||||
else {
|
||||
target = new File(sTarget);
|
||||
if (sTarget.endsWith(File.separator)) {
|
||||
target = new File(target,Misc.removeExtension(source.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Create converters
|
||||
Converter converter = ConverterFactory.createConverter(sTargetMIME);
|
||||
if (converter==null) {
|
||||
System.out.println("Failed to create converter for "+sTargetMIME);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
BatchConverter batchCv = null;
|
||||
if (bBatch) {
|
||||
batchCv = ConverterFactory.createBatchConverter(MIMETypes.XHTML);
|
||||
if (batchCv==null) {
|
||||
System.out.println("Failed to create batch converter");
|
||||
System.exit(1);
|
||||
}
|
||||
batchCv.setConverter(converter);
|
||||
}
|
||||
|
||||
// Step 5: Read template
|
||||
if (sTemplateFileName!=null) {
|
||||
try {
|
||||
System.out.println("Reading template "+sTemplateFileName);
|
||||
byte [] templateBytes = Misc.inputStreamToByteArray(new FileInputStream(sTemplateFileName));
|
||||
converter.readTemplate(new ByteArrayInputStream(templateBytes));
|
||||
if (batchCv!=null) {
|
||||
// Currently we use the same template for the directory and the files
|
||||
batchCv.readTemplate(new ByteArrayInputStream(templateBytes));
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
System.out.println("--> This file does not exist!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("--> Failed to read the template file!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6: Read config
|
||||
for (int i=0; i<configFileNames.size(); i++) {
|
||||
String sConfigFileName = (String) configFileNames.get(i);
|
||||
if (sConfigFileName.startsWith("*")) {
|
||||
sConfigFileName = sConfigFileName.substring(1);
|
||||
System.out.println("Reading default configuration "+sConfigFileName);
|
||||
try {
|
||||
converter.getConfig().readDefaultConfig(sConfigFileName);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
System.err.println("--> This configuration is unknown!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
System.out.println("Reading configuration file "+sConfigFileName);
|
||||
try {
|
||||
byte[] configBytes = Misc.inputStreamToByteArray(new FileInputStream(sConfigFileName));
|
||||
converter.getConfig().read(new ByteArrayInputStream(configBytes));
|
||||
if (bBatch) {
|
||||
// Currently we use the same configuration for the directory and the files
|
||||
batchCv.getConfig().read(new ByteArrayInputStream(configBytes));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println("--> Failed to read the configuration!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7: Set options from command line
|
||||
Enumeration keys = options.keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
String sKey = (String) keys.nextElement();
|
||||
String sValue = (String) options.get(sKey);
|
||||
converter.getConfig().setOption(sKey,sValue);
|
||||
if (batchCv!=null) {
|
||||
batchCv.getConfig().setOption(sKey,sValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 8: Perform conversion
|
||||
if (bBatch) {
|
||||
batchCv.convert(source,target,bRecurse, new BatchHandlerImpl());
|
||||
}
|
||||
else {
|
||||
System.out.println("Converting "+source.getPath());
|
||||
ConverterResult dataOut = null;
|
||||
|
||||
try {
|
||||
dataOut = converter.convert(source,target.getName());
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
System.out.println("--> The file "+source.getPath()+" does not exist!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("--> Failed to convert the file "+source.getPath()+"!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// TODO: Should do some further checking on the feasability of writing
|
||||
// the directory and the files.
|
||||
File targetDir = target.getParentFile();
|
||||
if (targetDir!=null && !targetDir.exists()) { targetDir.mkdirs(); }
|
||||
try {
|
||||
dataOut.write(targetDir);
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("--> Error writing out file!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Step 9: Say goodbye!
|
||||
System.out.println("Done!");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display usage.
|
||||
*/
|
||||
private static void showUsage(String msg) {
|
||||
System.out.println();
|
||||
System.out.println("This is Writer2LaTeX, Version " + ConverterFactory.getVersion()
|
||||
+ " (" + ConverterFactory.getDate() + ")");
|
||||
System.out.println();
|
||||
if (msg != null) System.out.println(msg);
|
||||
System.out.println();
|
||||
System.out.println("Usage:");
|
||||
System.out.println(" java -jar <path>/writer2latex.jar <options> <source file/directory> [<target file/directory>]");
|
||||
System.out.println("where the available options are:");
|
||||
System.out.println(" -latex");
|
||||
System.out.println(" -bibtex");
|
||||
System.out.println(" -xhtml");
|
||||
System.out.println(" -xhtml+mathml");
|
||||
System.out.println(" -xhtml+mathml+xsl");
|
||||
System.out.println(" -recurse");
|
||||
System.out.println(" -template[=]<template file>");
|
||||
System.out.println(" -ultraclean");
|
||||
System.out.println(" -clean");
|
||||
System.out.println(" -pdfprint");
|
||||
System.out.println(" -pdfscreen");
|
||||
System.out.println(" -cleanxhtml");
|
||||
System.out.println(" -config[=]<configuration file>");
|
||||
System.out.println(" -<configuration option>[=]<value>");
|
||||
System.out.println("See the documentation for the available configuration options");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line arguments.
|
||||
*
|
||||
* @param args Array of command line arguments.
|
||||
*
|
||||
* @throws IllegalArgumentException If an argument is invalid.
|
||||
*/
|
||||
private void parseCommandLine(String sArgs[])
|
||||
throws IllegalArgumentException {
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (i<sArgs.length) {
|
||||
String sArg = getArg(i++,sArgs);
|
||||
if (sArg.startsWith("-")) { // found an option
|
||||
if ("-latex".equals(sArg)) { sTargetMIME = MIMETypes.LATEX; }
|
||||
else if ("-bibtex".equals(sArg)) { sTargetMIME = MIMETypes.BIBTEX; }
|
||||
else if ("-xhtml".equals(sArg)) { sTargetMIME = MIMETypes.XHTML; }
|
||||
else if ("-xhtml+mathml".equals(sArg)) { sTargetMIME = MIMETypes.XHTML_MATHML; }
|
||||
else if ("-xhtml+mathml+xsl".equals(sArg)) { sTargetMIME = MIMETypes.XHTML_MATHML_XSL; }
|
||||
else if ("-recurse".equals(sArg)) { bRecurse = true; }
|
||||
else if ("-ultraclean".equals(sArg)) { configFileNames.add("*ultraclean.xml"); }
|
||||
else if ("-clean".equals(sArg)) { configFileNames.add("*clean.xml"); }
|
||||
else if ("-pdfprint".equals(sArg)) { configFileNames.add("*pdfprint.xml"); }
|
||||
else if ("-pdfscreen".equals(sArg)) { configFileNames.add("*pdfscreen.xml"); }
|
||||
else if ("-cleanxhtml".equals(sArg)) { configFileNames.add("*cleanxhtml.xml"); }
|
||||
else { // option with argument
|
||||
int j=sArg.indexOf("=");
|
||||
String sArg2;
|
||||
if (j>-1) { // argument is separated by =
|
||||
sArg2 = sArg.substring(j+1);
|
||||
sArg = sArg.substring(0,j);
|
||||
}
|
||||
else { // argument is separated by space
|
||||
sArg2 = getArg(i++,sArgs);
|
||||
}
|
||||
if ("-config".equals(sArg)) { configFileNames.add(sArg2); }
|
||||
else if ("-template".equals(sArg)) { sTemplateFileName = sArg2; }
|
||||
else { // configuration option
|
||||
options.put(sArg.substring(1),sArg2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // not an option, so this must be the source
|
||||
sSource = sArg;
|
||||
// Possibly followed by the target
|
||||
if (i<sArgs.length) {
|
||||
String sArgument = getArg(i++,sArgs);
|
||||
if (sArgument.length()>0) { sTarget = sArgument; }
|
||||
}
|
||||
// Skip any trailing empty arguments and signal an error if there's more
|
||||
while (i<sArgs.length) {
|
||||
String sArgument = getArg(i++,sArgs);
|
||||
if (sArgument.length()>0) {
|
||||
throw new IllegalArgumentException("I didn't expect "+sArgument+"?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sSource==null) {
|
||||
throw new IllegalArgumentException("Please specify a source document/directory!");
|
||||
}
|
||||
// Parsing of command line ended successfully!
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract the next argument from the array, while checking to see
|
||||
* that the array size is not exceeded. Throw a friendly error
|
||||
* message in case the arg is missing.
|
||||
*
|
||||
* @param i Argument index.
|
||||
* @param args Array of command line arguments.
|
||||
*
|
||||
* @return The argument with the specified index.
|
||||
*
|
||||
* @throws IllegalArgumentException If an argument is invalid.
|
||||
*/
|
||||
private String getArg(int i, String args[])
|
||||
throws IllegalArgumentException {
|
||||
|
||||
if (i < args.length) {
|
||||
return args[i];
|
||||
}
|
||||
else throw new
|
||||
IllegalArgumentException("I'm sorry, the commandline ended abnormally");
|
||||
}
|
||||
|
||||
|
||||
}
|
94
source/java/writer2latex/BatchHandlerImpl.java
Normal file
94
source/java/writer2latex/BatchHandlerImpl.java
Normal file
|
@ -0,0 +1,94 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchHandlerImpl.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-03)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import writer2latex.api.BatchHandler;
|
||||
|
||||
/** This class implements a <code>BatchHandler</code> for command line usage
|
||||
*/
|
||||
public class BatchHandlerImpl implements BatchHandler {
|
||||
private int nIndent = 0;
|
||||
|
||||
private void writeMessage(String sMsg) {
|
||||
for (int i=0; i<nIndent; i++) {
|
||||
System.out.print(" ");
|
||||
}
|
||||
System.out.println(sMsg);
|
||||
}
|
||||
|
||||
public void startConversion() {
|
||||
System.out.println("Press Enter to cancel the conversion");
|
||||
}
|
||||
|
||||
public void endConversion() {
|
||||
// No message
|
||||
}
|
||||
|
||||
public void startDirectory(String sName) {
|
||||
writeMessage("Converting directory "+sName);
|
||||
nIndent++;
|
||||
}
|
||||
|
||||
public void endDirectory(String sName, boolean bSuccess) {
|
||||
nIndent--;
|
||||
if (!bSuccess) {
|
||||
writeMessage("--> Conversion of the directory "+sName+" failed!");
|
||||
}
|
||||
}
|
||||
|
||||
public void startFile(String sName) {
|
||||
writeMessage("Converting file "+sName);
|
||||
nIndent++;
|
||||
}
|
||||
|
||||
public void endFile(String sName, boolean bSuccess) {
|
||||
nIndent--;
|
||||
if (!bSuccess) {
|
||||
writeMessage("--> Conversion of the file "+sName+" failed!");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean cancel() {
|
||||
try {
|
||||
if (System.in.available()>0) {
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
in.readLine();
|
||||
System.out.print("Do you want to cancel the conversion (y/n)? ");
|
||||
String s = in.readLine();
|
||||
if (s!= null && s.toLowerCase().startsWith("y")) { return true; }
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
96
source/java/writer2latex/api/BatchConverter.java
Normal file
96
source/java/writer2latex/api/BatchConverter.java
Normal file
|
@ -0,0 +1,96 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/** This is an interface for a converter, which offers conversion of
|
||||
* all OpenDocument (or OpenOffice.org 1.x) documents in a directory
|
||||
* (and optionally subdirectories), creating index pages in a specific format.
|
||||
* Instances of this interface are created using the
|
||||
* {@link ConverterFactory}
|
||||
*/
|
||||
public interface BatchConverter {
|
||||
|
||||
/** Get the configuration interface for this batch converter
|
||||
*
|
||||
* @return the configuration
|
||||
*/
|
||||
public Config getConfig();
|
||||
|
||||
/** Define a <code>Converter</code> implementation to use for
|
||||
* conversion of the individual documents.
|
||||
* If no converter is given, the <code>convert</code> method cannot
|
||||
* convert documents (but can still create index pages).
|
||||
*
|
||||
* @param converter the <code>Converter</code> to use
|
||||
*/
|
||||
public void setConverter(Converter converter);
|
||||
|
||||
/** Read a template to use as a base for the index pages.
|
||||
* The format of the template depends on the <code>BatchConverter</code>
|
||||
* implementation.
|
||||
*
|
||||
* @param is an <code>InputStream</code> from which to read the template
|
||||
* @throws IOException if some exception occurs while reading the template
|
||||
*/
|
||||
public void readTemplate(InputStream is) throws IOException;
|
||||
|
||||
/** Read a template to use as a base for the index pages.
|
||||
* The format of the template depends on the <code>BatchConverter</code>
|
||||
* implementation.
|
||||
*
|
||||
* @param file the file from which to read the template
|
||||
* @throws IOException if the file does not exist or some exception occurs
|
||||
* while reading the template
|
||||
*/
|
||||
public void readTemplate(File file) throws IOException;
|
||||
|
||||
/** Create an index page with specific entries
|
||||
*
|
||||
* @param sHeading a heading describing the index page
|
||||
* @param entries an array of <code>IndexPageEntry</code> objects (null entries
|
||||
* are allowed, and will be ignored) describing the individual directories
|
||||
* and documents
|
||||
*/
|
||||
public OutputFile createIndexFile(String sHeading, IndexPageEntry[] entries);
|
||||
|
||||
/** Convert a directory using the given <code>Converter</code> (if none is given,
|
||||
* all files will be ignored).
|
||||
* This method fails silently if you haven't set a converter.
|
||||
*
|
||||
* @param source a <code>File</code> representing the directory to convert
|
||||
* @param target a <code>File</code> representing the directory to contain
|
||||
* the converted documents
|
||||
* @param bRecurse determines wether or not to recurse into subdirectories
|
||||
* @param handler a </code>BatchHandler</code>
|
||||
*/
|
||||
public void convert(File source, File target, boolean bRecurse, BatchHandler handler);
|
||||
|
||||
}
|
77
source/java/writer2latex/api/BatchHandler.java
Normal file
77
source/java/writer2latex/api/BatchHandler.java
Normal file
|
@ -0,0 +1,77 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchHandler.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
/** This is a call back interface to handle user interaction during a
|
||||
* batch conversion with a {@link BatchConverter}
|
||||
*/
|
||||
public interface BatchHandler {
|
||||
|
||||
/** Notification that the conversion is started */
|
||||
public void startConversion();
|
||||
|
||||
/** Notification that the conversion has finished */
|
||||
public void endConversion();
|
||||
|
||||
/** Notification that a directory conversion starts
|
||||
*
|
||||
* @param sName the name of the directory to convert
|
||||
*/
|
||||
public void startDirectory(String sName);
|
||||
|
||||
/** Notification that a directory conversion has finished
|
||||
*
|
||||
* @param sName the name of the directory
|
||||
* @param bSuccess true if the conversion was successful (this only means
|
||||
* that the index page was created with success, not that the conversion
|
||||
* of files and subdirectories was successful)
|
||||
*/
|
||||
public void endDirectory(String sName, boolean bSuccess);
|
||||
|
||||
/** Notification that a file conversion starts
|
||||
*
|
||||
* @param sName the name of the file to convert
|
||||
*/
|
||||
public void startFile(String sName);
|
||||
|
||||
/** Notification that a file conversion has finished
|
||||
*
|
||||
* @param sName the name of the file
|
||||
* @param bSuccess true if the conversion of this file was successful
|
||||
*/
|
||||
public void endFile(String sName, boolean bSuccess);
|
||||
|
||||
/** Notification that the conversion may be cancelled. The
|
||||
* {@link BatchConverter} fires this event once per document.
|
||||
* Cancelling the conversion does not delete files that was already
|
||||
* converted
|
||||
*
|
||||
* @return true if the handler wants to cancel the conversion
|
||||
*/
|
||||
public boolean cancel();
|
||||
|
||||
}
|
99
source/java/writer2latex/api/Config.java
Normal file
99
source/java/writer2latex/api/Config.java
Normal file
|
@ -0,0 +1,99 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Config.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.IllegalArgumentException;
|
||||
|
||||
/** This is an interface for configuration of a {@link Converter}.
|
||||
* A configuration always supports simple name/value options.
|
||||
* In addition, you can read and write configurations using streams
|
||||
* or abstract file names. The format depends on the {@link Converter}
|
||||
* implementation, cf. the user's manual.
|
||||
*/
|
||||
public interface Config {
|
||||
|
||||
/** Read a default configuration: The available configurations depend on the
|
||||
* {@link Converter} implementation
|
||||
*
|
||||
* @param sName the name of the configuration
|
||||
* @throws IllegalArgumentException if the configuration does not exist
|
||||
*/
|
||||
public void readDefaultConfig(String sName) throws IllegalArgumentException;
|
||||
|
||||
/** Read a configuration (stream based version)
|
||||
*
|
||||
* @param is the <code>InputStream</code> to read from
|
||||
* @throws IOException if an error occurs reading the stream, or the data
|
||||
* is not in the right format
|
||||
*/
|
||||
public void read(InputStream is) throws IOException;
|
||||
|
||||
/** Read a configuration (file based version)
|
||||
*
|
||||
* @param file the <code>File</code> to read from
|
||||
* @throws IOException if the file does not exist, an error occurs reading
|
||||
* the file, or the data is not in the right format
|
||||
*/
|
||||
public void read(File file) throws IOException;
|
||||
|
||||
/** Write the configuration (stream based version)
|
||||
*
|
||||
* @param os the <code>OutputStream</code> to write to
|
||||
* @throws IOException if an error occurs writing to the stream
|
||||
*/
|
||||
public void write(OutputStream os) throws IOException;
|
||||
|
||||
/** Write the configuration (file based version)
|
||||
*
|
||||
* @param file the <code>File</code> to write to
|
||||
* @throws IOException if an error occurs writing to the file
|
||||
*/
|
||||
public void write(File file) throws IOException;
|
||||
|
||||
/** Set a name/value option. Options that are not defined by the
|
||||
* {@link Converter} implementation as well as null values are
|
||||
* silently ignored
|
||||
*
|
||||
* @param sName the name of the option
|
||||
* @param sValue the value of the option
|
||||
*/
|
||||
public void setOption(String sName, String sValue);
|
||||
|
||||
/** Get a named option
|
||||
*
|
||||
* @param sName the name of the option
|
||||
* @return the value of the option, or <code>null</code> if the option does
|
||||
* not exist or the given name is null
|
||||
*/
|
||||
public String getOption(String sName);
|
||||
|
||||
}
|
||||
|
99
source/java/writer2latex/api/Converter.java
Normal file
99
source/java/writer2latex/api/Converter.java
Normal file
|
@ -0,0 +1,99 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Converter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/** This is an interface for a converter, which offers conversion of
|
||||
* OpenDocument (or OpenOffice.org 1.x) documents into a specific format.
|
||||
* Instances of this interface are created using the
|
||||
* <code>ConverterFactory</code>
|
||||
*/
|
||||
public interface Converter {
|
||||
|
||||
/** Get the interface for the configuration of this converter
|
||||
*
|
||||
* @return the configuration
|
||||
*/
|
||||
public Config getConfig();
|
||||
|
||||
/** Define a <code>GraphicConverter</code> implementation to use for
|
||||
* conversion of graphic files. If no converter is specified, graphic
|
||||
* files will not be converted into other formats.
|
||||
*
|
||||
* @param gc the <code>GraphicConverter</code> to use
|
||||
*/
|
||||
public void setGraphicConverter(GraphicConverter gc);
|
||||
|
||||
/** Read a template to use as a base for the converted document.
|
||||
* The format of the template depends on the <code>Converter</code>
|
||||
* implementation.
|
||||
*
|
||||
* @param is an <code>InputStream</code> from which to read the template
|
||||
* @throws IOException if some exception occurs while reading the template
|
||||
*/
|
||||
public void readTemplate(InputStream is) throws IOException;
|
||||
|
||||
/** Read a template to use as a base for the converted document.
|
||||
* The format of the template depends on the <code>Converter</code>
|
||||
* implementation.
|
||||
*
|
||||
* @param file a file from which to read the template
|
||||
* @throws IOException if the file does not exist or some exception occurs
|
||||
* while reading the template
|
||||
*/
|
||||
public void readTemplate(File file) throws IOException;
|
||||
|
||||
/** Convert a document
|
||||
*
|
||||
* @param is an <code>InputStream</code> from which to read the source document.
|
||||
* @param sTargetFileName the file name to use for the converted document
|
||||
* (if the converted document is a compound document consisting consisting
|
||||
* of several files, this name will be used for the master document)
|
||||
* @return a <code>ConverterResult</code> containing the converted document
|
||||
* @throws IOException if some exception occurs while reading the document
|
||||
*/
|
||||
public ConverterResult convert(InputStream is, String sTargetFileName)
|
||||
throws IOException;
|
||||
|
||||
/** Convert a document
|
||||
*
|
||||
* @param source a <code>File</code> from which to read the source document.
|
||||
* @param sTargetFileName the file name to use for the converted document
|
||||
* (if the converted document is a compound document consisting consisting
|
||||
* of several files, this name will be used for the master document)
|
||||
* @return a <code>ConverterResult</code> containing the converted document
|
||||
* @throws FileNotFoundException if the file does not exist
|
||||
* @throws IOException if some exception occurs while reading the document
|
||||
*/
|
||||
public ConverterResult convert(File source, String sTargetFileName)
|
||||
throws FileNotFoundException, IOException;
|
||||
|
||||
}
|
126
source/java/writer2latex/api/ConverterFactory.java
Normal file
126
source/java/writer2latex/api/ConverterFactory.java
Normal file
|
@ -0,0 +1,126 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConverterFactory.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-18)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
/** This is a factory class which provides static methods to create converters
|
||||
* for documents in OpenDocument (or OpenOffice.org 1.x) format into a specific MIME type
|
||||
*/
|
||||
public class ConverterFactory {
|
||||
|
||||
// Version information
|
||||
private static final String VERSION = "0.9.4";
|
||||
private static final String DATE = "2008-02-19";
|
||||
|
||||
/** Return version information
|
||||
* @return the Writer2LaTeX version in the form
|
||||
* (major version).(minor version).(development version).(patch level)
|
||||
*/
|
||||
public static String getVersion() { return VERSION; }
|
||||
|
||||
/** Return date information
|
||||
* @return the release date for this Writer2LaTeX version
|
||||
*/
|
||||
public static String getDate() { return DATE; }
|
||||
|
||||
/** <p>Create a <code>Converter</code> implementation which supports
|
||||
* conversion into the specified MIME type.</p>
|
||||
* <p>Currently supported MIME types are:</p>
|
||||
* <ul>
|
||||
* <li><code>application/x-latex</code> for LaTeX format</li>
|
||||
* <li><code>application/x-bibtex</code> for BibTeX format</li>
|
||||
* <li><code>text/html</code> for XHTML 1.0 strict format</li>
|
||||
* <li><code>application/xhtml+xml</code> for XHTML+MathML</li>
|
||||
* <li><code>application/xml</code> for XHTML+MathML using stylesheets from w3c's
|
||||
* math working group</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param sMIME the MIME type of the target format
|
||||
* @return the required <code>Converter</code> or null if a converter for
|
||||
* the requested MIME type could not be created
|
||||
*/
|
||||
public static Converter createConverter(String sMIME) {
|
||||
Object converter = null;
|
||||
if (MIMETypes.LATEX.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.latex.ConverterPalette");
|
||||
}
|
||||
else if (MIMETypes.BIBTEX.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.bibtex.Converter");
|
||||
}
|
||||
else if (MIMETypes.XHTML.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.xhtml.Xhtml10Converter");
|
||||
}
|
||||
else if (MIMETypes.XHTML_MATHML.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.xhtml.XhtmlMathMLConverter");
|
||||
}
|
||||
else if (MIMETypes.XHTML_MATHML_XSL.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.xhtml.XhtmlMathMLXSLConverter");
|
||||
}
|
||||
return converter instanceof Converter ? (Converter) converter : null;
|
||||
}
|
||||
|
||||
/** <p>Create a <code>BatchConverter</code> implementation which supports
|
||||
* conversion into the specified MIME type</p>
|
||||
* <p>The only currently supported MIME type is <code>text/html</code>
|
||||
* (XHTML 1.0 strict)</p>
|
||||
*
|
||||
* @param sMIME the MIME type of the target format
|
||||
* @return the required <code>BatchConverter</code> or null if a converter
|
||||
* for the requested MIME type could not be created
|
||||
*/
|
||||
public static BatchConverter createBatchConverter(String sMIME) {
|
||||
Object converter = null;
|
||||
if (MIMETypes.XHTML.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.xhtml.BatchConverterImpl");
|
||||
}
|
||||
return converter instanceof BatchConverter ? (BatchConverter) converter : null;
|
||||
}
|
||||
|
||||
/** Create a <code>StarMathConverter</code> implementation
|
||||
*
|
||||
* @return the converter
|
||||
*/
|
||||
public static StarMathConverter createStarMathConverter() {
|
||||
Object converter = createInstance("writer2latex.latex.StarMathConverter");
|
||||
return converter instanceof StarMathConverter ? (StarMathConverter) converter : null;
|
||||
}
|
||||
|
||||
private static Object createInstance(String sClassName) {
|
||||
try {
|
||||
return Class.forName(sClassName).newInstance();
|
||||
}
|
||||
catch (java.lang.ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
catch (java.lang.InstantiationException e) {
|
||||
return null;
|
||||
}
|
||||
catch (java.lang.IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
59
source/java/writer2latex/api/ConverterResult.java
Normal file
59
source/java/writer2latex/api/ConverterResult.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConverterResult.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-24)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
/** A <code>ConverterResult</code> represent a document, which is the result
|
||||
* of a conversion performed by a <code>Converter</code>implementation.
|
||||
*/
|
||||
public interface ConverterResult {
|
||||
|
||||
/** Get the master document
|
||||
* @return <code>OutputFile</code> the master document
|
||||
*/
|
||||
public OutputFile getMasterDocument();
|
||||
|
||||
/** Gets an <code>Iterator</code> to access all files in the
|
||||
* <code>ConverterResult</code>. This <em>includes</em> the master document.
|
||||
* @return an <code>Iterator</code> of all files
|
||||
*/
|
||||
public Iterator iterator();
|
||||
|
||||
/** Write all files of the <code>ConverterResult</code> to a directory.
|
||||
* Subdirectories are created as required by the individual
|
||||
* <code>OutputFile</code>s.
|
||||
* @param dir the directory to write to (this directory must exist).
|
||||
If the parameter is null, the default directory is used
|
||||
* @throws IOException if the directory does not exist or one or more files
|
||||
* could not be written
|
||||
*/
|
||||
public void write(File dir) throws IOException;
|
||||
|
||||
}
|
58
source/java/writer2latex/api/GraphicConverter.java
Normal file
58
source/java/writer2latex/api/GraphicConverter.java
Normal file
|
@ -0,0 +1,58 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* GraphicConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
/** A simple interface for a graphic converter which converts between various
|
||||
* graphics formats
|
||||
*/
|
||||
public interface GraphicConverter {
|
||||
|
||||
/** Check whether a certain conversion is supported by the converter
|
||||
*
|
||||
* @param sSourceMime a string containing the source Mime type
|
||||
* @param sTargetMime a string containing the target Mime type
|
||||
* @param bCrop true if the target graphic should be cropped
|
||||
* @param bResize true if the target graphic should be resized
|
||||
* (the last two parameters are for future use)
|
||||
* @return true if the conversion is supported
|
||||
*/
|
||||
public boolean supportsConversion(String sSourceMime, String sTargetMime, boolean bCrop, boolean bResize);
|
||||
|
||||
/** Convert a graphics file from one format to another
|
||||
*
|
||||
* @param source a byte array containing the source graphic
|
||||
* @param sSourceMime a string containing the Mime type of the source
|
||||
* @param sTargetMime a string containing the desired Mime type of the target
|
||||
* @return a byte array containing the converted graphic. Returns null
|
||||
* if the conversion failed.
|
||||
*/
|
||||
public byte[] convert(byte[] source, String sSourceMime, String sTargetMime);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
141
source/java/writer2latex/api/IndexPageEntry.java
Normal file
141
source/java/writer2latex/api/IndexPageEntry.java
Normal file
|
@ -0,0 +1,141 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* IndexPageEntry.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
/** This class represents a single entry on an index page created by a batch converter
|
||||
*/
|
||||
public class IndexPageEntry {
|
||||
|
||||
private String sFile;
|
||||
private String sDisplayName;
|
||||
private String sDescription = null;
|
||||
private String sPdfFile = null;
|
||||
private String sOriginalFile = null;
|
||||
private boolean bIsDirectory;
|
||||
|
||||
/** Construct a new <code>IndexPageEntry</code> based on a file name.
|
||||
* The file name is also used as display name.
|
||||
*
|
||||
* @param sFile the file name for this entry
|
||||
* @param bIsDirectory true if this is a directory, false if it is a file
|
||||
*/
|
||||
public IndexPageEntry(String sFile, boolean bIsDirectory) {
|
||||
this.sFile = sFile;
|
||||
this.sDisplayName = sFile;
|
||||
this.bIsDirectory = bIsDirectory;
|
||||
}
|
||||
|
||||
/** Set the file name
|
||||
*
|
||||
* @param sFile the file name
|
||||
*/
|
||||
public void setFile(String sFile) {
|
||||
this.sFile = sFile;
|
||||
}
|
||||
|
||||
/** Set the display name for this entry. The display name is the
|
||||
* name presented on the index page.
|
||||
*
|
||||
* @param sDisplayName the display name
|
||||
*/
|
||||
public void setDisplayName(String sDisplayName) {
|
||||
this.sDisplayName = sDisplayName;
|
||||
}
|
||||
|
||||
/** Set the description of this file (additional information about the file)
|
||||
*
|
||||
* @param sDescription the description
|
||||
*/
|
||||
public void setDescription(String sDescription) {
|
||||
this.sDescription = sDescription;
|
||||
}
|
||||
|
||||
/** Set the file name for a pdf file associated with this file
|
||||
*
|
||||
* @param sPdfFile the file name
|
||||
*/
|
||||
public void setPdfFile(String sPdfFile) {
|
||||
this.sPdfFile = sPdfFile;
|
||||
}
|
||||
|
||||
/** Set the file name for the original file
|
||||
*
|
||||
* @param sOriginalFile the origianl file name
|
||||
*/
|
||||
public void setOriginalFile(String sOriginalFile) {
|
||||
this.sOriginalFile = sOriginalFile;
|
||||
}
|
||||
|
||||
/** Get the file name
|
||||
*
|
||||
* @return the file name
|
||||
*/
|
||||
public String getFile() {
|
||||
return sFile;
|
||||
}
|
||||
|
||||
/** Get the display name
|
||||
*
|
||||
* @return the display name
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return sDisplayName;
|
||||
}
|
||||
|
||||
/** Get the description
|
||||
*
|
||||
* @return the description, or null if there is no description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return sDescription;
|
||||
}
|
||||
|
||||
/** Get the pdf file name
|
||||
*
|
||||
* @return the file name or null if there is none
|
||||
*/
|
||||
public String getPdfFile() {
|
||||
return sPdfFile;
|
||||
}
|
||||
|
||||
/** Get the original file name
|
||||
*
|
||||
* @return the file name or null if there is none
|
||||
*/
|
||||
public String getOriginalFile() {
|
||||
return sOriginalFile;
|
||||
}
|
||||
|
||||
/** Check whether this is a file or a directory
|
||||
*
|
||||
* @return true for a directory, false for a file
|
||||
*/
|
||||
public boolean isDirectory() {
|
||||
return bIsDirectory;
|
||||
}
|
||||
|
||||
}
|
55
source/java/writer2latex/api/MIMETypes.java
Normal file
55
source/java/writer2latex/api/MIMETypes.java
Normal file
|
@ -0,0 +1,55 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* MIMETypes.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
/* Some helpers to handle the MIME types used by OOo
|
||||
*/
|
||||
|
||||
public class MIMETypes {
|
||||
// Various graphics formats, see
|
||||
// http://api.openoffice.org/docs/common/ref/com/sun/star/graphic/MediaProperties.html#MimeType
|
||||
public static final String PNG="image/png";
|
||||
public static final String JPEG="image/jpeg";
|
||||
public static final String GIF="image/gif";
|
||||
public static final String TIFF="image/tiff";
|
||||
public static final String BMP="image/bmp";
|
||||
public static final String WMF="image/x-wmf";
|
||||
public static final String EPS="image/x-eps";
|
||||
// MIME type for SVM has changed
|
||||
//public static final String SVM="image/x-svm";
|
||||
public static final String SVM="application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"";
|
||||
public static final String PDF="application/pdf";
|
||||
|
||||
// Desitination formats
|
||||
public static final String XHTML="text/html";
|
||||
public static final String XHTML_MATHML="application/xhtml+xml";
|
||||
public static final String XHTML_MATHML_XSL="application/xml";
|
||||
public static final String LATEX="application/x-latex";
|
||||
public static final String BIBTEX="application/x-bibtex";
|
||||
public static final String TEXT="text";
|
||||
|
||||
}
|
53
source/java/writer2latex/api/OutputFile.java
Normal file
53
source/java/writer2latex/api/OutputFile.java
Normal file
|
@ -0,0 +1,53 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* OutputFile.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/** An <code>OutputFile</code> represent a single file in a
|
||||
* {@link ConverterResult}, which is output from a {@link Converter}
|
||||
* implementation.
|
||||
*/
|
||||
public interface OutputFile {
|
||||
|
||||
/** Writes the <code>OutputFile</code> to an <code>OutputStream</code>.
|
||||
*
|
||||
* @param os <code>OutputStream</code> to which the content should be written
|
||||
* @throws IOException if any I/O error occurs
|
||||
*/
|
||||
public void write(OutputStream os) throws IOException;
|
||||
|
||||
/** Returns the file name of the <code>OutputFile</code>. This includes
|
||||
* the file extension and may also include a relative path, always using
|
||||
* / as separator.
|
||||
*
|
||||
* @return the file name of this <code>OutputFile</code>
|
||||
*/
|
||||
public String getFileName();
|
||||
|
||||
}
|
13
source/java/writer2latex/api/Package.html
Normal file
13
source/java/writer2latex/api/Package.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The package writer2latex.api</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>This package contains the api for using Writer2LaTeX.</p>
|
||||
<p>The api consitst of a factory class and a number of interfaces, and is
|
||||
used by the command line application as well as by the filters.
|
||||
</body>
|
||||
</html>
|
61
source/java/writer2latex/api/StarMathConverter.java
Normal file
61
source/java/writer2latex/api/StarMathConverter.java
Normal file
|
@ -0,0 +1,61 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* StarMathConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
//import java.io.InputStream;
|
||||
//import java.io.IOException;
|
||||
|
||||
/** This is an interface for a converter, which offers conversion of
|
||||
* a StarMath formula into LaTeX
|
||||
* Instances of this interface are created using the
|
||||
* {@link ConverterFactory}
|
||||
*/
|
||||
public interface StarMathConverter {
|
||||
|
||||
/** Get the configuration used when converting.
|
||||
*
|
||||
* @return the configuration used by this converter
|
||||
*/
|
||||
public Config getConfig();
|
||||
|
||||
/** Convert a StarMath formula
|
||||
*
|
||||
* @param sStarMathFormula is a string containing the StarMath formula
|
||||
* @return a string containing the converted LaTeX formula
|
||||
*/
|
||||
public String convert(String sStarMathFormula);
|
||||
|
||||
/** Create a suitable LaTeX preamble to process the formulas converted so far
|
||||
*
|
||||
* @return a string containg the entire LaTeX preamble
|
||||
*/
|
||||
public String getPreamble();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
182
source/java/writer2latex/base/BatchConverterBase.java
Normal file
182
source/java/writer2latex/base/BatchConverterBase.java
Normal file
|
@ -0,0 +1,182 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchConverterBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-15)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import writer2latex.api.BatchConverter;
|
||||
import writer2latex.api.BatchHandler;
|
||||
import writer2latex.api.Converter;
|
||||
import writer2latex.api.ConverterResult;
|
||||
import writer2latex.api.IndexPageEntry;
|
||||
import writer2latex.api.OutputFile;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/**
|
||||
* Abstract base implementation of <code>writer2latex.api.BatchConverter</code>.
|
||||
* The base implementation handles the traversal of directories and files, and
|
||||
* leaves the handling of indexpages to the subclass.
|
||||
*/
|
||||
public abstract class BatchConverterBase implements BatchConverter {
|
||||
|
||||
private Converter converter;
|
||||
|
||||
public BatchConverterBase() {
|
||||
converter = null;
|
||||
}
|
||||
|
||||
// Partial implementation of the interface
|
||||
|
||||
public void setConverter(Converter converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public void convert(File source, File target, boolean bRecurse, BatchHandler handler) {
|
||||
handler.startConversion();
|
||||
convertDirectory(source, target, bRecurse, source.getName(), handler);
|
||||
handler.endConversion();
|
||||
}
|
||||
|
||||
protected abstract String getIndexFileName();
|
||||
|
||||
// Convert files and directories in the directory indir
|
||||
// (return false if conversion has been cancelled by the BatchHandler)
|
||||
private boolean convertDirectory(File indir, File outdir, boolean bRecurse, String sHeading, BatchHandler handler) {
|
||||
handler.startDirectory(indir.getPath());
|
||||
|
||||
// Step 1: Get the directory
|
||||
File[] contents = indir.listFiles();
|
||||
int nLen = contents.length;
|
||||
IndexPageEntry[] entries = new IndexPageEntry[nLen];
|
||||
|
||||
// Step 2: Traverse subdirectories, if allowed
|
||||
if (bRecurse) {
|
||||
String sUplink = getConfig().getOption("uplink");
|
||||
for (int i=0; i<nLen; i++) {
|
||||
if (contents[i].isDirectory()) {
|
||||
getConfig().setOption("uplink","../"+getIndexFileName());
|
||||
File newOutdir = new File(outdir,contents[i].getName());
|
||||
String sNewHeading = sHeading + " - " + contents[i].getName();
|
||||
boolean bResult = convertDirectory(contents[i],newOutdir,bRecurse,sNewHeading,handler);
|
||||
getConfig().setOption("uplink", sUplink);
|
||||
if (!bResult) { return false; }
|
||||
// Create entry for this subdirectory
|
||||
IndexPageEntry entry = new IndexPageEntry(Misc.makeHref(contents[i].getName()+"/"+getIndexFileName()),true);
|
||||
entry.setDisplayName(contents[i].getName());
|
||||
entries[i]=entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Traverse documents, if we have a converter
|
||||
if (converter!=null) {
|
||||
String sUplink = getConfig().getOption("uplink");
|
||||
for (int i=0; i<nLen; i++) {
|
||||
if (contents[i].isFile()) {
|
||||
getConfig().setOption("uplink",getIndexFileName());
|
||||
String sLinkFile = convertFile(contents[i],outdir,handler);
|
||||
getConfig().setOption("uplink", sUplink);
|
||||
if (sLinkFile!=null) {
|
||||
// Create entry for this file
|
||||
IndexPageEntry entry = new IndexPageEntry(Misc.makeHref(sLinkFile),false);
|
||||
entry.setDisplayName(Misc.removeExtension(sLinkFile));
|
||||
entries[i]=entry;
|
||||
if (handler.cancel()) { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Create and write out the index file
|
||||
OutputFile indexFile = createIndexFile(sHeading, entries);
|
||||
|
||||
if (!outdir.exists()) { outdir.mkdirs(); }
|
||||
|
||||
boolean bSuccess = true;
|
||||
File outfile = new File(outdir,indexFile.getFileName());
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(outfile);
|
||||
indexFile.write(fos);
|
||||
fos.flush();
|
||||
fos.close();
|
||||
} catch (Exception writeExcept) {
|
||||
bSuccess = false;
|
||||
}
|
||||
|
||||
handler.endDirectory(indir.getPath(), bSuccess);
|
||||
|
||||
return !handler.cancel();
|
||||
}
|
||||
|
||||
// Convert a single file, returning the name of the master file
|
||||
// Returns null if conversion fails
|
||||
private String convertFile(File infile, File outdir, BatchHandler handler) {
|
||||
handler.startFile(infile.getPath());
|
||||
|
||||
// Currently we discriminate based on file extension
|
||||
if (!(infile.getName().endsWith(".odt") || infile.getName().endsWith(".ods") || infile.getName().endsWith(".odp"))) {
|
||||
handler.endFile(infile.getPath(),false);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Do conversion
|
||||
ConverterResult dataOut = null;
|
||||
try {
|
||||
// The target file name is always the same as the source
|
||||
dataOut = converter.convert(infile,Misc.removeExtension(infile.getName()));
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
handler.endFile(infile.getPath(),false);
|
||||
return null;
|
||||
}
|
||||
catch (IOException e) {
|
||||
handler.endFile(infile.getPath(),false);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Write out files
|
||||
if (!outdir.exists()) { outdir.mkdirs(); }
|
||||
|
||||
try {
|
||||
dataOut.write(outdir);
|
||||
}
|
||||
catch (IOException e) {
|
||||
handler.endFile(infile.getPath(),false);
|
||||
return null;
|
||||
}
|
||||
|
||||
handler.endFile(infile.getPath(),true);
|
||||
|
||||
return dataOut.getMasterDocument().getFileName();
|
||||
}
|
||||
|
||||
|
||||
}
|
44
source/java/writer2latex/base/BooleanOption.java
Normal file
44
source/java/writer2latex/base/BooleanOption.java
Normal file
|
@ -0,0 +1,44 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BooleanOption.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
// A BooleanOption interprets the values as booleans
|
||||
public class BooleanOption extends Option {
|
||||
private boolean bValue;
|
||||
|
||||
public boolean getValue() { return bValue; }
|
||||
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
bValue = "true".equals(sValue);
|
||||
}
|
||||
|
||||
public BooleanOption(String sName, String sDefaultValue) {
|
||||
super(sName,sDefaultValue);
|
||||
}
|
||||
}
|
||||
|
170
source/java/writer2latex/base/ConfigBase.java
Normal file
170
source/java/writer2latex/base/ConfigBase.java
Normal file
|
@ -0,0 +1,170 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConfigBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
/** Base implementation of writer2latex.api.Config
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
|
||||
import writer2latex.xmerge.NewDOMDocument;
|
||||
|
||||
public abstract class ConfigBase implements writer2latex.api.Config {
|
||||
|
||||
protected abstract int getOptionCount();
|
||||
protected abstract String getDefaultConfigPath();
|
||||
|
||||
protected Option[] options;
|
||||
|
||||
public ConfigBase() {
|
||||
options = new Option[getOptionCount()];
|
||||
}
|
||||
|
||||
public void setOption(String sName,String sValue) {
|
||||
if (sName!=null && sValue!=null) {
|
||||
for (int j=0; j<getOptionCount(); j++) {
|
||||
if (sName.equals(options[j].getName())) {
|
||||
options[j].setString(sValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getOption(String sName) {
|
||||
if (sName!=null) {
|
||||
for (int j=0; j<getOptionCount(); j++) {
|
||||
if (sName.equals(options[j].getName())) {
|
||||
return options[j].getString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void readDefaultConfig(String sName) throws IllegalArgumentException {
|
||||
InputStream is = this.getClass().getResourceAsStream(getDefaultConfigPath()+sName);
|
||||
if (is==null) {
|
||||
throw new IllegalArgumentException("The internal configuration '"+sName+ "' does not exist");
|
||||
}
|
||||
try {
|
||||
read(is);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// This would imply a bug in the configuration file!
|
||||
throw new IllegalArgumentException("The internal configuration '"+sName+ "' is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** <p>Read configuration from a specified input stream</p>
|
||||
* @param is the input stream to read the configuration from
|
||||
*/
|
||||
public void read(InputStream is) throws IOException {
|
||||
NewDOMDocument doc = new NewDOMDocument("config",".xml");
|
||||
doc.read(is); // may throw an IOException
|
||||
Document dom = doc.getContentDOM();
|
||||
if (dom==null) {
|
||||
throw new IOException("Failed to parse configuration");
|
||||
}
|
||||
|
||||
Node root = dom.getDocumentElement();
|
||||
Node child = root.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (child.getNodeType()==Node.ELEMENT_NODE) {
|
||||
Element elm = (Element)child;
|
||||
if (elm.getTagName().equals("option")) {
|
||||
String sName = elm.getAttribute("name");
|
||||
String sValue = elm.getAttribute("value");
|
||||
if (sName!="") { setOption(sName,sValue); }
|
||||
}
|
||||
else {
|
||||
readInner(elm);
|
||||
}
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
public void read(File file) throws IOException {
|
||||
read(new FileInputStream(file));
|
||||
}
|
||||
|
||||
/** Read configuration information from an xml element.
|
||||
* The subclass must define this to read richer configuration data
|
||||
*/
|
||||
protected abstract void readInner(Element elm);
|
||||
|
||||
public void write(OutputStream os) throws IOException {
|
||||
NewDOMDocument doc = new NewDOMDocument("config",".xml");
|
||||
Document dom = null;
|
||||
try {
|
||||
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = builderFactory.newDocumentBuilder();
|
||||
DOMImplementation domImpl = builder.getDOMImplementation();
|
||||
dom = domImpl.createDocument("","config",null);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
Element rootElement = dom.getDocumentElement();
|
||||
|
||||
for (int i=0; i<getOptionCount(); i++) {
|
||||
Element optionNode = dom.createElement("option");
|
||||
optionNode.setAttribute("name",options[i].getName());
|
||||
optionNode.setAttribute("value",options[i].getString());
|
||||
rootElement.appendChild(optionNode);
|
||||
}
|
||||
|
||||
writeInner(dom);
|
||||
|
||||
doc.setContentDOM(dom);
|
||||
doc.write(os); // may throw an IOException
|
||||
}
|
||||
|
||||
public void write(File file) throws IOException {
|
||||
write(new FileOutputStream(file));
|
||||
}
|
||||
|
||||
/** Write configuration information to an xml document.
|
||||
* The subclass must define this to write richer configuration data
|
||||
*/
|
||||
protected abstract void writeInner(Document dom);
|
||||
|
||||
}
|
||||
|
117
source/java/writer2latex/base/ConverterBase.java
Normal file
117
source/java/writer2latex/base/ConverterBase.java
Normal file
|
@ -0,0 +1,117 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConverterBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import writer2latex.api.GraphicConverter;
|
||||
import writer2latex.api.Converter;
|
||||
import writer2latex.api.ConverterResult;
|
||||
import writer2latex.api.OutputFile;
|
||||
import writer2latex.office.ImageLoader;
|
||||
import writer2latex.office.MetaData;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.xmerge.EmbeddedObject;
|
||||
import writer2latex.xmerge.ConvertData;
|
||||
import writer2latex.xmerge.OfficeDocument;
|
||||
|
||||
/**<p>Abstract base implementation of <code>writer2latex.api.Converter</code></p>
|
||||
*/
|
||||
public abstract class ConverterBase implements Converter {
|
||||
|
||||
// Helper
|
||||
protected GraphicConverter graphicConverter;
|
||||
|
||||
// The source document
|
||||
protected OfficeDocument odDoc;
|
||||
protected OfficeReader ofr;
|
||||
protected MetaData metaData;
|
||||
protected ImageLoader imageLoader;
|
||||
|
||||
// The output file(s)
|
||||
protected String sTargetFileName;
|
||||
protected ConvertData convertData;
|
||||
|
||||
// Constructor
|
||||
public ConverterBase() {
|
||||
graphicConverter = null;
|
||||
convertData = new ConvertData();
|
||||
}
|
||||
|
||||
// Implement the interface
|
||||
public void setGraphicConverter(GraphicConverter graphicConverter) {
|
||||
this.graphicConverter = graphicConverter;
|
||||
}
|
||||
|
||||
// Provide a do noting fallback method
|
||||
public void readTemplate(InputStream is) throws IOException { }
|
||||
|
||||
// Provide a do noting fallback method
|
||||
public void readTemplate(File file) throws IOException { }
|
||||
|
||||
public ConverterResult convert(File source, String sTargetFileName) throws FileNotFoundException,IOException {
|
||||
return convert(new FileInputStream(source), sTargetFileName);
|
||||
}
|
||||
|
||||
public ConverterResult convert(InputStream is, String sTargetFileName) throws IOException {
|
||||
// Read document
|
||||
odDoc = new OfficeDocument("InFile");
|
||||
odDoc.read(is);
|
||||
ofr = new OfficeReader(odDoc,false);
|
||||
metaData = new MetaData(odDoc);
|
||||
imageLoader = new ImageLoader(odDoc,sTargetFileName,true);
|
||||
imageLoader.setGraphicConverter(graphicConverter);
|
||||
|
||||
// Prepare output
|
||||
this.sTargetFileName = sTargetFileName;
|
||||
convertData.reset();
|
||||
|
||||
convertInner();
|
||||
|
||||
return convertData;
|
||||
}
|
||||
|
||||
// The subclass must provide the implementation
|
||||
public abstract void convertInner() throws IOException;
|
||||
|
||||
public MetaData getMetaData() { return metaData; }
|
||||
|
||||
public ImageLoader getImageLoader() { return imageLoader; }
|
||||
|
||||
public void addDocument(OutputFile doc) { convertData.addDocument(doc); }
|
||||
|
||||
public EmbeddedObject getEmbeddedObject(String sHref) {
|
||||
return odDoc.getEmbeddedObject(sHref);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
40
source/java/writer2latex/base/IntegerOption.java
Normal file
40
source/java/writer2latex/base/IntegerOption.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* IntegerOption.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
|
||||
// An IntegerOption must always be subclassed (must override setString)
|
||||
public abstract class IntegerOption extends Option {
|
||||
protected int nValue;
|
||||
|
||||
public int getValue() { return nValue; }
|
||||
|
||||
public IntegerOption(String sName, String sDefaultValue) {
|
||||
super(sName,sDefaultValue);
|
||||
}
|
||||
}
|
||||
|
45
source/java/writer2latex/base/Option.java
Normal file
45
source/java/writer2latex/base/Option.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Option.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
// The mother of all options; reads and writes string values
|
||||
public class Option {
|
||||
protected String sValue;
|
||||
private String sName;
|
||||
|
||||
public void setString(String sValue) { this.sValue = sValue; }
|
||||
|
||||
public String getString() { return sValue; }
|
||||
|
||||
public String getName() { return sName; }
|
||||
|
||||
public Option(String sName, String sDefaultValue) {
|
||||
this.sName = sName;
|
||||
setString(sDefaultValue);
|
||||
}
|
||||
}
|
||||
|
17
source/java/writer2latex/base/Package.html
Normal file
17
source/java/writer2latex/base/Package.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The package writer2latex.base</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>This package contains (abstract) base implementations of some of the
|
||||
interfaces in writer2latex.api</p>
|
||||
|
||||
<p>They are intended to be subclassed by converters into specific formats
|
||||
e.g. LaTeX, xhtml</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
238
source/java/writer2latex/bibtex/BibTeXDocument.java
Normal file
238
source/java/writer2latex/bibtex/BibTeXDocument.java
Normal file
|
@ -0,0 +1,238 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BibTeXDocument.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.bibtex;
|
||||
|
||||
import writer2latex.xmerge.Document;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Enumeration;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import writer2latex.api.ConverterFactory;
|
||||
import writer2latex.latex.LaTeXConfig;
|
||||
import writer2latex.latex.i18n.ClassicI18n;
|
||||
import writer2latex.latex.i18n.I18n;
|
||||
import writer2latex.util.ExportNameCollection;
|
||||
//import writer2latex.util.Misc;
|
||||
import writer2latex.office.BibMark;
|
||||
|
||||
/**
|
||||
* <p>Class representing a BibTeX document.</p>
|
||||
*
|
||||
*/
|
||||
public class BibTeXDocument implements Document {
|
||||
private static final String FILE_EXTENSION = ".bib";
|
||||
|
||||
private String sName;
|
||||
private Hashtable entries = new Hashtable();
|
||||
private ExportNameCollection exportNames = new ExportNameCollection(true);
|
||||
private I18n i18n;
|
||||
|
||||
/**
|
||||
* <p>Constructs a new BibTeX Document.</p>
|
||||
*
|
||||
* <p>This new document is empty. Bibliographic data must added
|
||||
* using the <code>put</code> method.</p>
|
||||
*
|
||||
* @param sName The name of the <code>BibTeXDocument</code>.
|
||||
*/
|
||||
public BibTeXDocument(String sName) {
|
||||
this.sName = trimDocumentName(sName);
|
||||
// Use default config (only ascii, no extra font packages)
|
||||
i18n = new ClassicI18n(new LaTeXConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This method is supposed to read <code>byte</code> data from the InputStream.
|
||||
* Currently it does nothing, since we don't need it.</p>
|
||||
*
|
||||
* @param is InputStream containing a BibTeX data file.
|
||||
*
|
||||
* @throws IOException In case of any I/O errors.
|
||||
*/
|
||||
public void read(InputStream is) throws IOException {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the <code>Document</code> name with no file extension.</p>
|
||||
*
|
||||
* @return The <code>Document</code> name with no file extension.
|
||||
*/
|
||||
public String getName() {
|
||||
return sName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the <code>Document</code> name with file extension.</p>
|
||||
*
|
||||
* @return The <code>Document</code> name with file extension.
|
||||
*/
|
||||
public String getFileName() {
|
||||
return new String(sName + FILE_EXTENSION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Writes out the <code>Document</code> content to the specified
|
||||
* <code>OutputStream</code>.</p>
|
||||
*
|
||||
* <p>This method may not be thread-safe.
|
||||
* Implementations may or may not synchronize this
|
||||
* method. User code (i.e. caller) must make sure that
|
||||
* calls to this method are thread-safe.</p>
|
||||
*
|
||||
* @param os <code>OutputStream</code> to write out the
|
||||
* <code>Document</code> content.
|
||||
*
|
||||
* @throws IOException If any I/O error occurs.
|
||||
*/
|
||||
public void write(OutputStream os) throws IOException {
|
||||
// BibTeX files are plain ascii
|
||||
OutputStreamWriter osw = new OutputStreamWriter(os,"ASCII");
|
||||
osw.write("%% This file was converted to BibTeX by Writer2BibTeX ver. "+ConverterFactory.getVersion()+".\n");
|
||||
osw.write("%% See http://www.hj-gym.dk/~hj/writer2latex for more info.\n");
|
||||
osw.write("\n");
|
||||
Enumeration enumeration = entries.elements();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
BibMark entry = (BibMark) enumeration.nextElement();
|
||||
osw.write("@");
|
||||
osw.write(entry.getEntryType().toUpperCase());
|
||||
osw.write("{");
|
||||
osw.write(exportNames.getExportName(entry.getIdentifier()));
|
||||
osw.write(",\n");
|
||||
for (int i=0; i<BibMark.FIELD_COUNT; i++) {
|
||||
String sValue = entry.getField(i);
|
||||
if (sValue!=null) {
|
||||
if (i==BibMark.AUTHOR || i==BibMark.EDITOR) {
|
||||
// OOo uses ; to separate authors and editors - BibTeX uses and
|
||||
sValue = sValue.replaceAll(";" , " and ");
|
||||
}
|
||||
osw.write(" ");
|
||||
osw.write(getFieldName(i).toUpperCase());
|
||||
osw.write(" = {");
|
||||
for (int j=0; j<sValue.length(); j++) {
|
||||
String s = i18n.convert(Character.toString(sValue.charAt(j)),false,"en");
|
||||
if (s.charAt(0)=='\\') { osw.write("{"); }
|
||||
osw.write(s);
|
||||
if (s.charAt(0)=='\\') { osw.write("}"); }
|
||||
}
|
||||
osw.write("},\n");
|
||||
}
|
||||
}
|
||||
osw.write("}\n\n");
|
||||
}
|
||||
osw.flush();
|
||||
osw.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Return BibTeX name of field </p>
|
||||
*/
|
||||
public static final String getFieldName(int nField) {
|
||||
switch (nField) {
|
||||
case BibMark.ADDRESS: return "address";
|
||||
case BibMark.ANNOTE: return "annote";
|
||||
case BibMark.AUTHOR: return "author";
|
||||
case BibMark.BOOKTITLE: return "booktitle";
|
||||
case BibMark.CHAPTER: return "chapter";
|
||||
// case BibMark.CROSSREF: return "croosref"; // not in OOo
|
||||
case BibMark.EDITION: return "edition";
|
||||
case BibMark.EDITOR: return "editor";
|
||||
case BibMark.HOWPUBLISHED: return "howpublished";
|
||||
case BibMark.INSTITUTION: return "institution";
|
||||
case BibMark.JOURNAL: return "journal";
|
||||
// case BibMark.KEY: return "key"; // not in OOo
|
||||
case BibMark.MONTH: return "month";
|
||||
case BibMark.NOTE: return "note";
|
||||
case BibMark.NUMBER: return "number";
|
||||
case BibMark.ORGANIZATIONS: return "organization";
|
||||
case BibMark.PAGES: return "pages";
|
||||
case BibMark.PUBLISHER: return "publisher";
|
||||
case BibMark.SCHOOL: return "school";
|
||||
case BibMark.SERIES: return "series";
|
||||
case BibMark.TITLE: return "title";
|
||||
case BibMark.REPORT_TYPE: return "type";
|
||||
case BibMark.VOLUME: return "volume";
|
||||
case BibMark.YEAR: return "year";
|
||||
case BibMark.URL: return "url";
|
||||
case BibMark.CUSTOM1: return "custom1";
|
||||
case BibMark.CUSTOM2: return "custom2";
|
||||
case BibMark.CUSTOM3: return "custom3";
|
||||
case BibMark.CUSTOM4: return "custom4";
|
||||
case BibMark.CUSTOM5: return "custom5";
|
||||
case BibMark.ISBN: return "isbn";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* <p>Check if this entry exists</p>
|
||||
*/
|
||||
public boolean containsKey(String sIdentifier) {
|
||||
return entries.containsKey(sIdentifier);
|
||||
}
|
||||
|
||||
/*
|
||||
* <p>Add an entry</p>
|
||||
*/
|
||||
public void put(BibMark entry) {
|
||||
entries.put(entry.getIdentifier(),entry);
|
||||
exportNames.addName(entry.getIdentifier());
|
||||
}
|
||||
|
||||
/*
|
||||
* <p>Get export name for an identifier</p>
|
||||
*/
|
||||
public String getExportName(String sIdentifier) {
|
||||
return exportNames.getExportName(sIdentifier);
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility method to make sure the document name is stripped of any file
|
||||
* extensions before use.
|
||||
*/
|
||||
private String trimDocumentName(String name) {
|
||||
String temp = name.toLowerCase();
|
||||
|
||||
if (temp.endsWith(FILE_EXTENSION)) {
|
||||
// strip the extension
|
||||
int nlen = name.length();
|
||||
int endIndex = nlen - FILE_EXTENSION.length();
|
||||
name = name.substring(0,endIndex);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
91
source/java/writer2latex/bibtex/Converter.java
Normal file
91
source/java/writer2latex/bibtex/Converter.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Converter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2001-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.bibtex;
|
||||
|
||||
import writer2latex.api.Config;
|
||||
//import writer2latex.api.ConverterResult;
|
||||
import writer2latex.base.ConverterBase;
|
||||
import writer2latex.latex.LaTeXConfig;
|
||||
import writer2latex.office.BibMark;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
//import writer2latex.xmerge.ConvertData;
|
||||
//import writer2latex.xmerge.OfficeDocument;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* <p>BibTeX export</p>
|
||||
*
|
||||
* <p>This class extracts bibliographic information from an OpenDocument text file to a BibTeX data file.</p>
|
||||
*
|
||||
*/
|
||||
public final class Converter extends ConverterBase {
|
||||
|
||||
// Configuration - TODO: Doesn't really use it - should use some fake config
|
||||
private LaTeXConfig config;
|
||||
|
||||
public Config getConfig() { return config; }
|
||||
|
||||
// Constructor
|
||||
public Converter() {
|
||||
super();
|
||||
config = new LaTeXConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Convert the data passed into the <code>InputStream</code>
|
||||
* into BibTeX format.</p>
|
||||
*
|
||||
* @throws IOException If any I/O error occurs.
|
||||
*/
|
||||
public void convertInner() throws IOException {
|
||||
sTargetFileName = Misc.trimDocumentName(sTargetFileName,".bib");
|
||||
|
||||
BibTeXDocument bibDoc = new BibTeXDocument(sTargetFileName);
|
||||
|
||||
// Collect all text:bibliography-mark elements from the content
|
||||
Element doc = ofr.getContent();
|
||||
NodeList list;
|
||||
list = doc.getElementsByTagName(XMLString.TEXT_BIBLIOGRAPHY_MARK);
|
||||
int nLen = list.getLength();
|
||||
for (int i=0; i<nLen; i++) {
|
||||
String sIdentifier = Misc.getAttribute(list.item(i),XMLString.TEXT_IDENTIFIER);
|
||||
if (sIdentifier!=null && !bibDoc.containsKey(sIdentifier)) {
|
||||
bibDoc.put(new BibMark(list.item(i)));
|
||||
}
|
||||
}
|
||||
|
||||
// Add result
|
||||
convertData.addDocument(bibDoc);
|
||||
}
|
||||
|
||||
}
|
14
source/java/writer2latex/bibtex/Package.html
Normal file
14
source/java/writer2latex/bibtex/Package.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The package writer2latex.bibtex</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>This package contains BibTeX specific code.</p>
|
||||
<p>It contains a <code>writerlatex.api.Converter</code> implementation for
|
||||
conversion into BibTeX, as well as code to convert to BibTeX as part of a
|
||||
conversion into LaTeX.</p>
|
||||
</body>
|
||||
</html>
|
157
source/java/writer2latex/latex/BibConverter.java
Normal file
157
source/java/writer2latex/latex/BibConverter.java
Normal file
|
@ -0,0 +1,157 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BibConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import writer2latex.bibtex.BibTeXDocument;
|
||||
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
import writer2latex.office.BibMark;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.XMLString;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/**
|
||||
* This class handles the bibliography. The result depends on these
|
||||
* configuration options. The citations will be treated like this:
|
||||
* <ul>
|
||||
* <li><code>use_bibtex</code>: If true, citations will be exported as \cite
|
||||
* commands. If false, citations will be exported as static text</li>
|
||||
* </ul>
|
||||
* The bibliography will be treated like this:
|
||||
* <ul>
|
||||
* <li><code>use_index</code>: If false, the bibliography will be omitted</li>
|
||||
* <li><code>use_bibtex</code> true and <code>external_bibtex_files</code>
|
||||
* empty: The citations will be exported to a BibTeX file, which will be used
|
||||
* for the bibliography</li>
|
||||
* <li><code>use_bibtex</code> true and <code>external_bibtex_files</code>
|
||||
* non-empty: The citations will be not be exported to a BibTeX file, the
|
||||
* files referred to by the option will be used instead</li>
|
||||
* <li><code>use_bibtex</code> false: The bibliography will be exported as
|
||||
* static text.
|
||||
* <li><code>bibtex_style</code> If BibTeX is used, this style will be applied
|
||||
* </ul>
|
||||
*/
|
||||
public class BibConverter extends ConverterHelper {
|
||||
|
||||
private BibTeXDocument bibDoc;
|
||||
|
||||
/** Construct a new BibConverter.
|
||||
* @param config the configuration to use
|
||||
* @param palette the ConverterPalette to use
|
||||
*/
|
||||
public BibConverter(OfficeReader ofr,LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
/** Append declarations needed by the <code>BibConverter</code> to
|
||||
* the preamble.
|
||||
* @param pack the LaTeXDocumentPortion to which
|
||||
* declarations of packages should be added (\\usepackage).
|
||||
* @param decl the LaTeXDocumentPortion to which
|
||||
* other declarations should be added.
|
||||
*/
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
// Currently nothing; may add support for eg. natbib later
|
||||
}
|
||||
|
||||
/** Process a bibliography (text:bibliography tag)
|
||||
* @param node The element containing the Bibliography
|
||||
* @param ldp the LaTeXDocumentPortion to which LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleBibliography (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
if (config.useBibtex()) {
|
||||
// Use the style given in the configuration
|
||||
// TODO: Create a bst file from the settings of the text:bibliography
|
||||
ldp.append("\\bibliographystyle{")
|
||||
.append(config.bibtexStyle())
|
||||
.append("}").nl();
|
||||
|
||||
// Use BibTeX file from configuration, or exported BibTeX file
|
||||
if (config.externalBibtexFiles().length()>0) {
|
||||
ldp.append("\\bibliography{")
|
||||
.append(config.externalBibtexFiles())
|
||||
.append("}").nl();
|
||||
}
|
||||
else {
|
||||
if (bibDoc==null) { bibDoc = new BibTeXDocument(palette.getOutFileName()); }
|
||||
ldp.append("\\bibliography{")
|
||||
.append(bibDoc.getName())
|
||||
.append("}").nl();
|
||||
}
|
||||
}
|
||||
else { // typeset current content
|
||||
Element body = Misc.getChildByTagName(node,XMLString.TEXT_INDEX_BODY);
|
||||
if (body!=null) {
|
||||
Element title = Misc.getChildByTagName(body,XMLString.TEXT_INDEX_TITLE);
|
||||
if (title!=null) { palette.getBlockCv().traverseBlockText(title,ldp,oc); }
|
||||
palette.getBlockCv().traverseBlockText(body,ldp,oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Process a Bibliography Mark (text:bibliography-mark tag)
|
||||
* @param node The element containing the Mark
|
||||
* @param ldp the LaTeXDocumentPortion to which LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleBibliographyMark(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.useBibtex()) {
|
||||
String sIdentifier = node.getAttribute(XMLString.TEXT_IDENTIFIER);
|
||||
if (sIdentifier!=null) {
|
||||
if (config.externalBibtexFiles().length()==0) {
|
||||
if (bibDoc==null) { bibDoc = new BibTeXDocument(palette.getOutFileName()); }
|
||||
if (!bibDoc.containsKey(sIdentifier)) {
|
||||
bibDoc.put(new BibMark(node));
|
||||
}
|
||||
}
|
||||
ldp.append("\\cite{")
|
||||
.append(bibDoc.getExportName(sIdentifier))
|
||||
.append("}");
|
||||
}
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the BibTeX document, if any (the document is only created if it's
|
||||
* specified in the configuration *and* the document contains bibliographic
|
||||
* data *and* the configuration does not specify external BibTeX files
|
||||
* @return the BiBTeXDocument, or null if it does not exist).
|
||||
*/
|
||||
public BibTeXDocument getBibTeXDocument () {
|
||||
return bibDoc;
|
||||
}
|
||||
|
||||
|
||||
}
|
378
source/java/writer2latex/latex/BlockConverter.java
Normal file
378
source/java/writer2latex/latex/BlockConverter.java
Normal file
|
@ -0,0 +1,378 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BlockConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
//import writer2latex.latex.util.HeadingMap;
|
||||
import writer2latex.latex.util.StyleMap;
|
||||
import writer2latex.office.ListStyle;
|
||||
import writer2latex.office.OfficeReader;
|
||||
//import writer2latex.office.TableReader;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/**
|
||||
* <p>This class handles basic block content, including the main text body,
|
||||
* sections, tables, lists, headings and paragraphs.</p>
|
||||
*/
|
||||
public class BlockConverter extends ConverterHelper {
|
||||
|
||||
public BlockConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
// currently do nothing..
|
||||
}
|
||||
|
||||
|
||||
/** <p> Traverse block text (eg. content of body, section, list item).
|
||||
* This is traversed in logical order and dedicated handlers take care of
|
||||
* each block element.</p>
|
||||
* <p> (Note: As a rule, all handling of block level elements should add a
|
||||
* newline to the LaTeX document at the end of the block)</p>
|
||||
* @param node The element containing the block text
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void traverseBlockText(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Context ic = (Context) oc.clone();
|
||||
|
||||
// The current paragraph block:
|
||||
StyleMap blockMap = config.getParBlockStyleMap();
|
||||
String sBlockName = null;
|
||||
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList list = node.getChildNodes();
|
||||
int nLen = list.getLength();
|
||||
|
||||
for (int i = 0; i < nLen; i++) {
|
||||
Node childNode = list.item(i);
|
||||
|
||||
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element child = (Element)childNode;
|
||||
String sTagName = child.getTagName();
|
||||
|
||||
// Start/End a paragraph block (not in tables)
|
||||
if (!ic.isInTable()) {
|
||||
if (sTagName.equals(XMLString.TEXT_P)) {
|
||||
String sStyleName = ofr.getParStyles().getDisplayName(child.getAttribute(XMLString.TEXT_STYLE_NAME));
|
||||
if (sBlockName!=null && !blockMap.isNext(sBlockName,sStyleName)) {
|
||||
// end current block
|
||||
String sAfter = blockMap.getAfter(sBlockName);
|
||||
if (sAfter.length()>0) ldp.append(sAfter).nl();
|
||||
sBlockName = null;
|
||||
ic.setVerbatim(false);
|
||||
}
|
||||
if (sBlockName==null && blockMap.contains(sStyleName)) {
|
||||
// start a new block
|
||||
sBlockName = sStyleName;
|
||||
String sBefore = blockMap.getBefore(sBlockName);
|
||||
if (sBefore.length()>0) ldp.append(sBefore).nl();
|
||||
ic.setVerbatim(blockMap.getVerbatim(sStyleName));
|
||||
}
|
||||
}
|
||||
else if (sBlockName!=null) {
|
||||
// non-paragraph: end current block
|
||||
String sAfter = blockMap.getAfter(sBlockName);
|
||||
if (sAfter.length()>0) ldp.append(sAfter).nl();
|
||||
sBlockName = null;
|
||||
ic.setVerbatim(false);
|
||||
}
|
||||
}
|
||||
|
||||
palette.getFieldCv().flushReferenceMarks(ldp,ic);
|
||||
palette.getIndexCv().flushIndexMarks(ldp,ic);
|
||||
|
||||
palette.getInfo().addDebugInfo(child,ldp);
|
||||
|
||||
// Basic block content; handle by this class
|
||||
if (sTagName.equals(XMLString.TEXT_P)) {
|
||||
// is this a caption?
|
||||
String sSequence = ofr.getSequenceName(child);
|
||||
if (ofr.isFigureSequenceName(sSequence)) {
|
||||
palette.getDrawCv().handleCaption(child,ldp,ic);
|
||||
}
|
||||
else if (ofr.isTableSequenceName(sSequence)) {
|
||||
// Next node *should* be a table
|
||||
if (i+1<nLen && Misc.isElement(list.item(i+1),XMLString.TABLE_TABLE)) {
|
||||
// Found table with caption above
|
||||
palette.getTableCv().handleTable((Element)list.item(++i),child,true,ldp,ic);
|
||||
}
|
||||
else {
|
||||
// Found lonely caption
|
||||
palette.getTableCv().handleCaption(child,ldp,ic);
|
||||
}
|
||||
}
|
||||
else {
|
||||
palette.getParCv().handleParagraph(child,ldp,ic,i==nLen-1);
|
||||
}
|
||||
}
|
||||
|
||||
else if(sTagName.equals(XMLString.TEXT_H)) {
|
||||
palette.getHeadingCv().handleHeading(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_LIST)) { // oasis
|
||||
handleList(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_UNORDERED_LIST)) {
|
||||
handleList(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_ORDERED_LIST)) {
|
||||
handleList(child,ldp,ic);
|
||||
}
|
||||
else if (sTagName.equals(XMLString.TABLE_TABLE)) {
|
||||
// Next node *could* be a caption
|
||||
if (i+1<nLen && Misc.isElement(list.item(i+1),XMLString.TEXT_P) &&
|
||||
ofr.isTableSequenceName(ofr.getSequenceName((Element)list.item(i+1)))) {
|
||||
// Found table with caption below
|
||||
palette.getTableCv().handleTable(child,(Element)list.item(++i),false,ldp,oc);
|
||||
}
|
||||
else {
|
||||
// Found table without caption
|
||||
palette.getTableCv().handleTable(child,null,false,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TABLE_SUB_TABLE)) {
|
||||
palette.getTableCv().handleTable(child,null,true,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_SECTION)) {
|
||||
palette.getSectionCv().handleSection(child,ldp,ic);
|
||||
}
|
||||
|
||||
// Draw elements may appear in block context if they are
|
||||
// anchored to page
|
||||
else if (sTagName.startsWith("draw:")) {
|
||||
palette.getDrawCv().handleDrawElement(child,ldp,ic);
|
||||
}
|
||||
|
||||
// Indexes
|
||||
else if (sTagName.equals(XMLString.TEXT_TABLE_OF_CONTENT)) {
|
||||
palette.getIndexCv().handleTOC(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_ILLUSTRATION_INDEX)) {
|
||||
palette.getIndexCv().handleLOF(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_TABLE_INDEX)) {
|
||||
palette.getIndexCv().handleLOT(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_OBJECT_INDEX)) {
|
||||
palette.getIndexCv().handleObjectIndex(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_USER_INDEX)) {
|
||||
palette.getIndexCv().handleUserIndex(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_ALPHABETICAL_INDEX)) {
|
||||
palette.getIndexCv().handleAlphabeticalIndex(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_BIBLIOGRAPHY)) {
|
||||
palette.getBibCv().handleBibliography(child,ldp,ic);
|
||||
}
|
||||
|
||||
// Sequence declarations appear in the main text body (before the actual content)
|
||||
else if (sTagName.equals(XMLString.TEXT_SEQUENCE_DECLS)) {
|
||||
palette.getFieldCv().handleSequenceDecls(child);
|
||||
}
|
||||
// other tags are ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!oc.isInTable() && sBlockName!=null) {
|
||||
// end current block
|
||||
String sAfter = blockMap.getAfter(sBlockName);
|
||||
if (sAfter.length()>0) ldp.append(sAfter).nl();
|
||||
sBlockName = null;
|
||||
}
|
||||
palette.getFieldCv().flushReferenceMarks(ldp,ic);
|
||||
palette.getIndexCv().flushIndexMarks(ldp,ic);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** <p> Process a list (text:ordered-lst or text:unordered-list tag)</p>
|
||||
* @param node The element containing the list
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleList(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Set up new context
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.incListLevel();
|
||||
|
||||
// Get the style name, if we don't know it already
|
||||
if (ic.getListStyleName()==null) {
|
||||
ic.setListStyleName(node.getAttribute(XMLString.TEXT_STYLE_NAME));
|
||||
}
|
||||
|
||||
// Use the style to determine the type of list
|
||||
ListStyle style = ofr.getListStyle(ic.getListStyleName());
|
||||
boolean bOrdered = style!=null && style.isNumber(ic.getListLevel());
|
||||
|
||||
// If the list contains headings, ignore it!
|
||||
if (ic.isIgnoreLists() || listContainsHeadings(node)) {
|
||||
ic.setIgnoreLists(true);
|
||||
traverseList(node,ldp,ic);
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply the style
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
palette.getListSc().applyListStyle(ic.getListStyleName(),ic.getListLevel(),
|
||||
bOrdered,"true".equals(node.getAttribute(XMLString.TEXT_CONTINUE_NUMBERING)),
|
||||
ba);
|
||||
|
||||
// Export the list
|
||||
if (ba.getBefore().length()>0) { ldp.append(ba.getBefore()).nl(); }
|
||||
traverseList(node,ldp,ic);
|
||||
if (ba.getAfter().length()>0) { ldp.append(ba.getAfter()).nl(); }
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the contents of a list
|
||||
*/
|
||||
private void traverseList (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList list = node.getChildNodes();
|
||||
int nLen = list.getLength();
|
||||
|
||||
for (int i = 0; i < nLen; i++) {
|
||||
Node child = list.item(i);
|
||||
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
||||
String nodeName = child.getNodeName();
|
||||
|
||||
palette.getInfo().addDebugInfo((Element)child,ldp);
|
||||
|
||||
if (nodeName.equals(XMLString.TEXT_LIST_ITEM)) {
|
||||
handleListItem((Element)child,ldp,oc);
|
||||
}
|
||||
if (nodeName.equals(XMLString.TEXT_LIST_HEADER)) {
|
||||
handleListItem((Element)child,ldp,oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleListItem(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Are we ignoring this list?
|
||||
if (oc.isIgnoreLists()) {
|
||||
traverseBlockText(node,ldp,oc);
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply the style
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
palette.getListSc().applyListItemStyle(
|
||||
oc.getListStyleName(), oc.getListLevel(),
|
||||
node.getNodeName().equals(XMLString.TEXT_LIST_HEADER),
|
||||
"true".equals(node.getAttribute(XMLString.TEXT_RESTART_NUMBERING)),
|
||||
Misc.getPosInteger(node.getAttribute(XMLString.TEXT_START_VALUE),1)-1,
|
||||
ba);
|
||||
|
||||
// export the list item
|
||||
if (ba.getBefore().length()>0) {
|
||||
ldp.append(ba.getBefore());
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) { ldp.nl(); }
|
||||
}
|
||||
traverseBlockText(node,ldp,oc);
|
||||
if (ba.getAfter().length()>0) { ldp.append(ba.getAfter()).nl(); }
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper: Check to see, if this list contains headings
|
||||
* (in that case we will ignore the list!)
|
||||
*/
|
||||
private boolean listContainsHeadings (Node node) {
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList nList = node.getChildNodes();
|
||||
int len = nList.getLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Node child = nList.item(i);
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
||||
String nodeName = child.getNodeName();
|
||||
if (nodeName.equals(XMLString.TEXT_LIST_ITEM)) {
|
||||
if (listItemContainsHeadings(child)) return true;
|
||||
}
|
||||
if (nodeName.equals(XMLString.TEXT_LIST_HEADER)) {
|
||||
if (listItemContainsHeadings(child)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean listItemContainsHeadings(Node node) {
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList nList = node.getChildNodes();
|
||||
int len = nList.getLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Node child = nList.item(i);
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
||||
String nodeName = child.getNodeName();
|
||||
if(nodeName.equals(XMLString.TEXT_H)) {
|
||||
return true;
|
||||
}
|
||||
if (nodeName.equals(XMLString.TEXT_LIST)) {
|
||||
if (listContainsHeadings(child)) return true;
|
||||
}
|
||||
if (nodeName.equals(XMLString.TEXT_ORDERED_LIST)) {
|
||||
if (listContainsHeadings(child)) return true;
|
||||
}
|
||||
if (nodeName.equals(XMLString.TEXT_UNORDERED_LIST)) {
|
||||
if (listContainsHeadings(child)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
163
source/java/writer2latex/latex/CaptionConverter.java
Normal file
163
source/java/writer2latex/latex/CaptionConverter.java
Normal file
|
@ -0,0 +1,163 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* CaptionConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.XMLString;
|
||||
|
||||
/**
|
||||
* <p>This class converts captions (for figures and tables) to LaTeX.</p>
|
||||
* <p>Packages:
|
||||
* <ul><li>caption.sty is used implement non-floating captions</li></ul>
|
||||
* <p>Options:
|
||||
* <ul><li>use_caption is a boolean option to determine whether or not
|
||||
* to use caption.sty. If this option is set to false, a simple definition of
|
||||
* \captionof (borrowed from capt-of.sty) is inserted in the preamble</li></ul>
|
||||
* <p>TODO: Implement formatting of captions using the features of caption.sty
|
||||
* (only if formatting>=CONVERT_BASIC)
|
||||
*/
|
||||
public class CaptionConverter extends ConverterHelper {
|
||||
|
||||
private boolean bNeedCaptionOf = false;
|
||||
|
||||
private Element seqField = null; // the sequence field within the current caption
|
||||
|
||||
public CaptionConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bNeedCaptionOf) {
|
||||
if (config.useCaption()) {
|
||||
pack.append("\\usepackage{caption}").nl();
|
||||
}
|
||||
else { // use definition borrowed from capt-of.sty
|
||||
decl.append("% Non-floating captions").nl()
|
||||
.append("\\makeatletter").nl()
|
||||
.append("\\newcommand\\captionof[1]{\\def\\@captype{#1}\\caption}").nl()
|
||||
.append("\\makeatother").nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Process content of a text:p tag as a caption body (inluding label)</p>
|
||||
* @param node The text:p element node containing the caption
|
||||
* @param ldp The <code>LaTeXDocumentPortion</code> to add LaTeX code to
|
||||
* @param oc The current context
|
||||
* @param bIsCaptionOf true if this is caption uses captionof
|
||||
*/
|
||||
public void handleCaptionBody(Element node,LaTeXDocumentPortion ldp, Context oc, boolean bIsCaptionOf) {
|
||||
bNeedCaptionOf|=bIsCaptionOf;
|
||||
|
||||
// Get rid of the caption label before converting
|
||||
removeCaptionLabel(node,0);
|
||||
Element label = seqField;
|
||||
seqField = null;
|
||||
|
||||
// Get the stylename of the paragraph and push the font used
|
||||
String sStyleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getParStyle(sStyleName)));
|
||||
|
||||
if (palette.getHeadingCv().containsElements(node)) {
|
||||
ldp.append("[");
|
||||
palette.getInlineCv().traversePlainInlineText(node,ldp,oc);
|
||||
ldp.append("]");
|
||||
}
|
||||
// Update context before traversing text
|
||||
Context ic = (Context) oc.clone();
|
||||
ldp.append("{");
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,ic);
|
||||
ldp.append("}").nl();
|
||||
|
||||
// Insert label
|
||||
palette.getFieldCv().handleSequence(label,ldp,oc);
|
||||
|
||||
// Flush any index marks
|
||||
palette.getIndexCv().flushIndexMarks(ldp,oc);
|
||||
|
||||
// pop the font name
|
||||
palette.getI18n().popSpecialTable();
|
||||
|
||||
}
|
||||
|
||||
// In OpenDocument a caption is an ordinary paragraph with a text:seqence
|
||||
// element. For example
|
||||
// Table <text:sequence>3</text:sequence>: Caption text
|
||||
// The first part is the caption label which is autogenerated by LaTeX.
|
||||
// Before converting, we remove this in 3 steps:
|
||||
// nStep = 0: Remove all text before the text:sequence
|
||||
// nStep = 1: Remove all text up to the first alphanumeric character
|
||||
// after the text:sequence
|
||||
// nStep = 2: Finished!
|
||||
private int removeCaptionLabel(Element node, int nStep) {
|
||||
if (nStep==2) { return 2; }
|
||||
|
||||
Node removeMe = null;
|
||||
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (child.getNodeType()==Node.ELEMENT_NODE) {
|
||||
if (nStep==0 && child.getNodeName().equals(XMLString.TEXT_SEQUENCE)) {
|
||||
removeMe = child;
|
||||
seqField = (Element) child; // remember me...
|
||||
nStep = 1;
|
||||
}
|
||||
else if (nStep<2 && !OfficeReader.isDrawElement(child)) {
|
||||
// draw elements (frames) should not be touched..
|
||||
nStep = removeCaptionLabel((Element)child,nStep);
|
||||
}
|
||||
}
|
||||
else if (child.getNodeType()==Node.TEXT_NODE) {
|
||||
if (nStep==0) {
|
||||
child.setNodeValue("");
|
||||
}
|
||||
else if (nStep==1) {
|
||||
String s = child.getNodeValue();
|
||||
int n = s.length();
|
||||
for (int j=0; j<n; j++) {
|
||||
if (Character.isLetterOrDigit(s.charAt(j))) {
|
||||
child.setNodeValue(s.substring(j));
|
||||
nStep = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
|
||||
if (removeMe!=null) { node.removeChild(removeMe); }
|
||||
return nStep;
|
||||
}
|
||||
|
||||
|
||||
}
|
507
source/java/writer2latex/latex/CharStyleConverter.java
Normal file
507
source/java/writer2latex/latex/CharStyleConverter.java
Normal file
|
@ -0,0 +1,507 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* CharStyleConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-12-03)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.latex.util.StyleMap;
|
||||
|
||||
/** This class creates LaTeX code from OOo character formatting
|
||||
Character formatting in OOo includes font, font effects/decorations and color.
|
||||
In addition it includes color and language/country information, this is however handled
|
||||
by the classes <code>writer2latex.latex.ColorConverter</code> and
|
||||
<code>writer2latex.latex.style.I18n</code>
|
||||
*/
|
||||
public class CharStyleConverter extends StyleConverter {
|
||||
|
||||
// Cache of converted font declarations
|
||||
private Hashtable fontDecls = new Hashtable();
|
||||
|
||||
// Which formatting should we export?
|
||||
private boolean bIgnoreHardFontsize;
|
||||
private boolean bIgnoreFontsize;
|
||||
private boolean bIgnoreFont;
|
||||
private boolean bIgnoreAll;
|
||||
private boolean bUseUlem;
|
||||
// Do we need actually use ulem.sty or \textsubscript?
|
||||
private boolean bNeedUlem = false;
|
||||
private boolean bNeedSubscript = false;
|
||||
|
||||
/** <p>Constructs a new <code>CharStyleConverter</code>.</p>
|
||||
*/
|
||||
public CharStyleConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
|
||||
bUseUlem = config.useUlem();
|
||||
|
||||
// No character formatting at all:
|
||||
bIgnoreAll = config.formatting()==LaTeXConfig.IGNORE_ALL;
|
||||
// No font family or size:
|
||||
bIgnoreFont = config.formatting()<=LaTeXConfig.IGNORE_MOST;
|
||||
// No fontsize:
|
||||
bIgnoreFontsize = config.formatting()<=LaTeXConfig.CONVERT_BASIC;
|
||||
// No hard fontsize
|
||||
bIgnoreHardFontsize = config.formatting()<=LaTeXConfig.CONVERT_MOST;
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bNeedUlem) {
|
||||
pack.append("\\usepackage[normalem]{ulem}").nl();
|
||||
}
|
||||
if (bNeedSubscript && !config.getTextAttributeStyleMap().contains("subscript")) {
|
||||
decl.append("\\newcommand\\textsubscript[1]{\\ensuremath{{}_{\\text{#1}}}}").nl();
|
||||
}
|
||||
if (!styleNames.isEmpty()) {
|
||||
decl.append("% Text styles").nl().append(declarations);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Use a text style in LaTeX.</p>
|
||||
* @param sName the name of the text style
|
||||
* @param ba a <code>BeforeAfter</code> to put code into
|
||||
*/
|
||||
public void applyTextStyle(String sName, BeforeAfter ba, Context context) {
|
||||
if (sName==null) { return; }
|
||||
String sDisplayName = ofr.getTextStyles().getDisplayName(sName);
|
||||
|
||||
if (bIgnoreAll) {
|
||||
// Even if all is ignored, we still apply style maps from config..
|
||||
StyleMap sm = config.getTextStyleMap();
|
||||
if (sm.contains(sDisplayName)) {
|
||||
ba.add(sm.getBefore(sDisplayName),sm.getAfter(sDisplayName));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Style already converted?
|
||||
if (styleMap.contains(sName)) {
|
||||
ba.add(styleMap.getBefore(sName),styleMap.getAfter(sName));
|
||||
context.updateFormattingFromStyle(ofr.getTextStyle(sName));
|
||||
// it's verbatim if specified as such in the configuration
|
||||
StyleMap sm = config.getTextStyleMap();
|
||||
boolean bIsVerbatim = sm.contains(sDisplayName) && sm.getVerbatim(sDisplayName);
|
||||
context.setVerbatim(bIsVerbatim);
|
||||
context.setNoLineBreaks(bIsVerbatim);
|
||||
return;
|
||||
}
|
||||
|
||||
// The style may already be declared in the configuration:
|
||||
StyleMap sm = config.getTextStyleMap();
|
||||
if (sm.contains(sDisplayName)) {
|
||||
styleMap.put(sName,sm.getBefore(sDisplayName),sm.getAfter(sDisplayName));
|
||||
applyTextStyle(sName,ba,context);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the style, if it exists:
|
||||
StyleWithProperties style = ofr.getTextStyle(sName);
|
||||
if (style==null) {
|
||||
styleMap.put(sName,"","");
|
||||
applyTextStyle(sName,ba,context);
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert automatic style
|
||||
if (style.isAutomatic()) {
|
||||
palette.getI18n().applyLanguage(style,false,true,ba);
|
||||
applyFont(style,false,true,ba,context);
|
||||
applyFontEffects(style,true,ba);
|
||||
context.updateFormattingFromStyle(ofr.getTextStyle(sName));
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert soft style:
|
||||
// This must be converted relative to a blank context!
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
palette.getI18n().applyLanguage(style,false,true,baText);
|
||||
applyFont(style,false,true,baText,new Context());
|
||||
applyFontEffects(style,true,baText);
|
||||
// declare the text style (\newcommand)
|
||||
String sTeXName = styleNames.getExportName(ofr.getTextStyles().getDisplayName(sName));
|
||||
styleMap.put(sName,"\\textstyle"+sTeXName+"{","}");
|
||||
declarations.append("\\newcommand\\textstyle")
|
||||
.append(sTeXName).append("[1]{")
|
||||
.append(baText.getBefore()).append("#1").append(baText.getAfter())
|
||||
.append("}").nl();
|
||||
applyTextStyle(sName,ba,context);
|
||||
}
|
||||
|
||||
public String getFontName(StyleWithProperties style) {
|
||||
if (style!=null) {
|
||||
String sName = style.getProperty(XMLString.STYLE_FONT_NAME);
|
||||
if (sName!=null) {
|
||||
FontDeclaration fd = ofr.getFontDeclaration(sName);
|
||||
if (fd!=null) {
|
||||
return fd.getFontFamily();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the font name from a char style
|
||||
public String getFontName(String sStyleName) {
|
||||
return getFontName(ofr.getTextStyle(sStyleName));
|
||||
}
|
||||
|
||||
/** <p>Apply hard character formatting (no inheritance).</p>
|
||||
* <p>This is used in sections and {foot|end}notes</p>
|
||||
* @param style the style to use
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to
|
||||
*/
|
||||
public void applyHardCharFormatting(StyleWithProperties style, BeforeAfter ba) {
|
||||
palette.getI18n().applyLanguage(style,true,false,ba);
|
||||
applyFont(style,true,false,ba,new Context());
|
||||
if (!ba.isEmpty()) { ba.add(" ",""); }
|
||||
}
|
||||
|
||||
/** <p>Apply all font attributes (family, series, shape, size and color).</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyFont(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (style==null) { return; }
|
||||
applyNfssSize(style,bDecl,bInherit,ba,context);
|
||||
applyNfssFamily(style,bDecl,bInherit,ba,context);
|
||||
applyNfssSeries(style,bDecl,bInherit,ba,context);
|
||||
applyNfssShape(style,bDecl,bInherit,ba,context);
|
||||
palette.getColorCv().applyColor(style,bDecl,bInherit,ba,context);
|
||||
}
|
||||
|
||||
/** <p>Reset to normal font, size and color.</p>
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyNormalFont(BeforeAfter ba) {
|
||||
ba.add("\\normalfont\\normalsize","");
|
||||
palette.getColorCv().applyNormalColor(ba);
|
||||
}
|
||||
|
||||
/** <p>Apply default font attributes (family, series, shape, size and color).</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyDefaultFont(StyleWithProperties style, LaTeXDocumentPortion ldp) {
|
||||
if (style==null) { return; }
|
||||
|
||||
String s = convertFontDeclaration(style.getProperty(XMLString.STYLE_FONT_NAME));
|
||||
if (s!=null){
|
||||
ldp.append("\\renewcommand\\familydefault{\\")
|
||||
.append(s).append("default}").nl();
|
||||
} // TODO: Else read props directly from the style
|
||||
|
||||
s = nfssSeries(style.getProperty(XMLString.FO_FONT_WEIGHT));
|
||||
if (s!=null) {
|
||||
ldp.append("\\renewcommand\\seriesdefault{\\")
|
||||
.append(s).append("default}").nl();
|
||||
}
|
||||
|
||||
s = nfssShape(style.getProperty(XMLString.FO_FONT_VARIANT),
|
||||
style.getProperty(XMLString.FO_FONT_STYLE));
|
||||
if (s!=null) {
|
||||
ldp.append("\\renewcommand\\shapedefault{\\")
|
||||
.append(s).append("default}").nl();
|
||||
}
|
||||
|
||||
palette.getColorCv().setNormalColor(style.getProperty(XMLString.FO_COLOR),ldp);
|
||||
}
|
||||
|
||||
/** <p>Apply font effects (position, underline, crossout, change case.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyFontEffects(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style==null) { return; }
|
||||
applyTextPosition(style, bInherit, ba);
|
||||
applyUnderline(style, bInherit, ba);
|
||||
applyCrossout(style, bInherit, ba);
|
||||
applyChangeCase(style, bInherit, ba);
|
||||
}
|
||||
|
||||
// Remaining methods are private
|
||||
|
||||
/** <p>Apply font family.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyNfssFamily(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (style==null || bIgnoreFont) { return; }
|
||||
String sFontName=style.getProperty(XMLString.STYLE_FONT_NAME,bInherit);
|
||||
if (sFontName!=null){
|
||||
String sFamily = convertFontDeclaration(sFontName);
|
||||
if (sFamily==null) { return; }
|
||||
if (sFamily.equals(convertFontDeclaration(context.getFontName()))) { return; }
|
||||
if (bDecl) { ba.add("\\"+sFamily+"family",""); }
|
||||
else { ba.add("\\text"+sFamily+"{","}"); }
|
||||
} // TODO: Else read props directly from the style
|
||||
}
|
||||
|
||||
/** <p>Apply font series.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyNfssSeries(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (style!=null && !bIgnoreAll) {
|
||||
String sSeries = nfssSeries(style.getProperty(XMLString.FO_FONT_WEIGHT,bInherit));
|
||||
if (sSeries!=null) {
|
||||
// Temporary: Support text-attribute style maps for this particular case
|
||||
// TODO: Reimplement the CharStyleConverter to properly support this...
|
||||
if (!bDecl && "bf".equals(sSeries) && config.getTextAttributeStyleMap().contains("bold")) {
|
||||
ba.add(config.getTextAttributeStyleMap().getBefore("bold"),
|
||||
config.getTextAttributeStyleMap().getAfter("bold"));
|
||||
}
|
||||
else {
|
||||
if (style.isAutomatic()) { // optimize hard formatting
|
||||
if (sSeries.equals(nfssSeries(context.getFontWeight()))) { return; }
|
||||
if (context.getFontWeight()==null && sSeries.equals("md")) { return; }
|
||||
}
|
||||
if (bDecl) { ba.add("\\"+sSeries+"series",""); }
|
||||
else { ba.add("\\text"+sSeries+"{","}"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply font shape.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyNfssShape(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (style!=null && !bIgnoreAll) {
|
||||
String sVariant = style.getProperty(XMLString.FO_FONT_VARIANT, bInherit);
|
||||
String sStyle = style.getProperty(XMLString.FO_FONT_STYLE, bInherit);
|
||||
String sShape = nfssShape(sVariant,sStyle);
|
||||
if (sShape!=null) {
|
||||
// Temporary: Support text-attribute style maps for this particular case
|
||||
// TODO: Reimplement the CharStyleConverter to properly support this...
|
||||
if (!bDecl && "sc".equals(sShape) && config.getTextAttributeStyleMap().contains("small-caps")) {
|
||||
ba.add(config.getTextAttributeStyleMap().getBefore("small-caps"),
|
||||
config.getTextAttributeStyleMap().getAfter("small-caps"));
|
||||
}
|
||||
else if (!bDecl && "it".equals(sShape) && config.getTextAttributeStyleMap().contains("italic")) {
|
||||
ba.add(config.getTextAttributeStyleMap().getBefore("italic"),
|
||||
config.getTextAttributeStyleMap().getAfter("italic"));
|
||||
}
|
||||
else {
|
||||
if (style.isAutomatic()) { // optimize hard formatting
|
||||
if (sShape.equals(nfssShape(context.getFontVariant(),context.getFontStyle()))) return;
|
||||
if (context.getFontVariant()==null && context.getFontStyle()==null && sShape.equals("up")) return;
|
||||
}
|
||||
if (bDecl) ba.add("\\"+sShape+"shape","");
|
||||
else ba.add("\\text"+sShape+"{","}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply font size.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyNfssSize(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (style==null|| bIgnoreFontsize || (bIgnoreHardFontsize && style.isAutomatic())) { return; }
|
||||
if (style.getProperty(XMLString.FO_FONT_SIZE, bInherit)==null) { return; }
|
||||
String sSize = nfssSize(style.getAbsoluteProperty(XMLString.FO_FONT_SIZE));
|
||||
if (sSize==null) { return; }
|
||||
if (sSize.equals(nfssSize(context.getFontSize()))) { return; }
|
||||
if (bDecl) { ba.add(sSize,""); }
|
||||
else { ba.add("{"+sSize+" ","}"); }
|
||||
}
|
||||
|
||||
// Remaining methods are not context-sensitive
|
||||
|
||||
/** <p>Apply text position.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyTextPosition(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style!=null && !bIgnoreAll) {
|
||||
String s = textPosition(style.getProperty(XMLString.STYLE_TEXT_POSITION, bInherit));
|
||||
// Temporary: Support text-attribute style maps for this particular case
|
||||
// TODO: Reimplement the CharStyleConverter to properly support this...
|
||||
if (config.getTextAttributeStyleMap().contains("superscript") && "\\textsuperscript".equals(s)) {
|
||||
ba.add(config.getTextAttributeStyleMap().getBefore("superscript"),
|
||||
config.getTextAttributeStyleMap().getAfter("superscript"));
|
||||
}
|
||||
else if (config.getTextAttributeStyleMap().contains("subscript") && "\\textsubscript".equals(s)) {
|
||||
ba.add(config.getTextAttributeStyleMap().getBefore("subscript"),
|
||||
config.getTextAttributeStyleMap().getAfter("subscript"));
|
||||
}
|
||||
else if (s!=null) {
|
||||
ba.add(s+"{","}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply text underline.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyUnderline(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style==null || !bUseUlem) { return; }
|
||||
if (bIgnoreAll) { return; }
|
||||
String sTag = ofr.isOpenDocument() ?
|
||||
XMLString.STYLE_TEXT_UNDERLINE_STYLE :
|
||||
XMLString.STYLE_TEXT_UNDERLINE;
|
||||
String s = underline(style.getProperty(sTag, bInherit));
|
||||
if (s!=null) { bNeedUlem = true; ba.add(s+"{","}"); }
|
||||
}
|
||||
|
||||
/** <p>Apply text crossout.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyCrossout(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style==null || !bUseUlem) { return; }
|
||||
if (bIgnoreAll) { return; }
|
||||
String sTag = ofr.isOpenDocument() ?
|
||||
XMLString.STYLE_TEXT_LINE_THROUGH_STYLE :
|
||||
XMLString.STYLE_TEXT_CROSSING_OUT;
|
||||
String s = crossout(style.getProperty(sTag, bInherit));
|
||||
if (s!=null) { bNeedUlem = true; ba.add(s+"{","}"); }
|
||||
}
|
||||
|
||||
/** <p>Apply change case.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyChangeCase(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style==null) { return; }
|
||||
if (bIgnoreAll) { return; }
|
||||
String s = changeCase(style.getProperty(XMLString.FO_TEXT_TRANSFORM));
|
||||
if (s!=null) { ba.add(s+"{","}"); }
|
||||
}
|
||||
|
||||
/** <p>Convert font declarations to LaTeX.</p>
|
||||
* <p>It returns a generic LaTeX font family (rm, tt, sf).</p>
|
||||
* <p>It returns null if the font declaration doesn't exist.</p>
|
||||
* @param sName the name of the font declaration
|
||||
* @return <code>String</code> with a LaTeX generic fontfamily
|
||||
*/
|
||||
private String convertFontDeclaration(String sName) {
|
||||
FontDeclaration fd = ofr.getFontDeclaration(sName);
|
||||
if (fd==null) { return null; }
|
||||
if (!fontDecls.containsKey(sName)) {
|
||||
String sFontFamily = fd.getFontFamily();
|
||||
String sFontPitch = fd.getFontPitch();
|
||||
String sFontFamilyGeneric = fd.getFontFamilyGeneric();
|
||||
fontDecls.put(sName,nfssFamily(sFontFamily,sFontFamilyGeneric,sFontPitch));
|
||||
}
|
||||
return (String) fontDecls.get(sName);
|
||||
}
|
||||
|
||||
// The remaining methods are static helpers to convert single style properties
|
||||
|
||||
// Font change. These methods return the declaration form if the paramater
|
||||
// bDecl is true, and otherwise the command form
|
||||
|
||||
private static final String nfssFamily(String sFontFamily, String sFontFamilyGeneric,
|
||||
String sFontPitch){
|
||||
// Note: Defaults to rm
|
||||
// TODO: What about decorative, script, system?
|
||||
if ("fixed".equals(sFontPitch)) return "tt";
|
||||
else if ("modern".equals(sFontFamilyGeneric)) return "tt";
|
||||
else if ("swiss".equals(sFontFamilyGeneric)) return "sf";
|
||||
else return "rm";
|
||||
}
|
||||
|
||||
private static final String nfssSeries(String sFontWeight){
|
||||
if (sFontWeight==null) return null;
|
||||
if ("bold".equals(sFontWeight)) return "bf";
|
||||
else return "md";
|
||||
}
|
||||
|
||||
private static final String nfssShape(String sFontVariant, String sFontStyle){
|
||||
if (sFontVariant==null && sFontStyle==null) return null;
|
||||
if ("small-caps".equals(sFontVariant)) return "sc";
|
||||
else if ("italic".equals(sFontStyle)) return "it";
|
||||
else if ("oblique".equals(sFontStyle)) return "sl";
|
||||
else return "up";
|
||||
}
|
||||
|
||||
private static final String nfssSize(String sFontSize){
|
||||
if (sFontSize==null) return null;
|
||||
return "\\fontsize{"+sFontSize+"}{"+Misc.multiply("120%",sFontSize)+"}\\selectfont";
|
||||
}
|
||||
|
||||
// other character formatting
|
||||
|
||||
private final String textPosition(String sTextPosition){
|
||||
if (sTextPosition==null) return null;
|
||||
if (sTextPosition.startsWith("super")) return "\\textsuperscript";
|
||||
if (sTextPosition.startsWith("sub") || sTextPosition.startsWith("-")) {
|
||||
bNeedSubscript = true;
|
||||
return "\\textsubscript";
|
||||
}
|
||||
if (sTextPosition.startsWith("0%")) return null;
|
||||
return "\\textsuperscript";
|
||||
}
|
||||
|
||||
private static final String underline(String sUnderline) {
|
||||
if (sUnderline==null) { return null; }
|
||||
if (sUnderline.equals("none")) { return null; }
|
||||
if (sUnderline.indexOf("wave")>=0) { return "\\uwave"; }
|
||||
return "\\uline";
|
||||
}
|
||||
|
||||
private static final String crossout(String sCrossout) {
|
||||
if (sCrossout==null) { return null; }
|
||||
if (sCrossout.equals("X")) { return "\\xout"; }
|
||||
if (sCrossout.equals("slash")) { return "\\xout"; }
|
||||
return "\\sout";
|
||||
}
|
||||
|
||||
private static final String changeCase(String sTextTransform){
|
||||
if ("lowercase".equals(sTextTransform)) return "\\MakeLowercase";
|
||||
if ("uppercase".equals(sTextTransform)) return "\\MakeUppercase";
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
202
source/java/writer2latex/latex/ColorConverter.java
Normal file
202
source/java/writer2latex/latex/ColorConverter.java
Normal file
|
@ -0,0 +1,202 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ColorConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
|
||||
/** This class converts color
|
||||
*/
|
||||
public class ColorConverter extends ConverterHelper {
|
||||
|
||||
private static final int RED = 0;
|
||||
private static final int GREEN = 1;
|
||||
private static final int BLUE = 2;
|
||||
|
||||
private boolean bUseColor;
|
||||
|
||||
/** <p>Constructs a new <code>CharStyleConverter</code>.</p>
|
||||
*/
|
||||
public ColorConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
|
||||
// We use color if requested in the configuration, however ignoring
|
||||
// all formatting overrides this
|
||||
bUseColor = config.useColor() && config.formatting()>LaTeXConfig.IGNORE_ALL;
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bUseColor) {
|
||||
pack.append("\\usepackage{color}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
public void setNormalColor(String sColor, LaTeXDocumentPortion ldp) {
|
||||
if (bUseColor && sColor!=null) {
|
||||
ldp.append("\\renewcommand\\normalcolor{\\color")
|
||||
.append(color(sColor)).append("}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
public void applyNormalColor(BeforeAfter ba) {
|
||||
if (bUseColor) { ba.add("\\normalcolor",""); }
|
||||
}
|
||||
|
||||
/** <p>Apply foreground color.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
* @param context the current context
|
||||
*/
|
||||
public void applyColor(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (bUseColor && style!=null) {
|
||||
String sColor = style.getProperty(XMLString.FO_COLOR,bInherit);
|
||||
if (sColor!=null) {
|
||||
if (!sColor.equals(context.getFontColor())) {
|
||||
// Convert color if it differs from the current font color
|
||||
context.setFontColor(sColor);
|
||||
applyColor(sColor, bDecl, ba, context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No color; maybe automatic color?
|
||||
String sAutomatic = style.getProperty(XMLString.STYLE_USE_WINDOW_FONT_COLOR,bInherit);
|
||||
if (sAutomatic==null && bInherit) {
|
||||
// We may need to inherit this property from the default style
|
||||
StyleWithProperties defaultStyle = ofr.getDefaultParStyle();
|
||||
if (defaultStyle!=null) {
|
||||
sAutomatic = defaultStyle.getProperty(XMLString.STYLE_USE_WINDOW_FONT_COLOR,bInherit);
|
||||
}
|
||||
}
|
||||
if ("true".equals(sAutomatic)) {
|
||||
// Automatic color based on background
|
||||
if (context.getBgColor()!=null) { applyAutomaticColor(ba,bDecl,context); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply a specific foreground color.</p>
|
||||
* @param sColor the rgb color to use
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyColor(String sColor, boolean bDecl, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (bUseColor && sColor!=null) {
|
||||
// If there's a background color, allow all colors
|
||||
String s = context.getBgColor()!=null ? fullcolor(sColor) : color(sColor);
|
||||
if (s!=null) {
|
||||
if (bDecl) { ba.add("\\color"+s,""); }
|
||||
else { ba.add("\\textcolor"+s+"{","}"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void applyBgColor(String sCommand, String sColor, BeforeAfter ba, Context context) {
|
||||
// Note: Will only fill "before" part of ba
|
||||
if (sColor!=null && !"transparent".equals(sColor)) {
|
||||
String s = fullcolor(sColor);
|
||||
if (bUseColor && s!=null) {
|
||||
context.setBgColor(sColor);
|
||||
ba.add(sCommand+s,"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void applyAutomaticColor(BeforeAfter ba, boolean bDecl, Context context) {
|
||||
String s = automaticcolor(context.getBgColor());
|
||||
if (s!=null) {
|
||||
if (bDecl) { ba.add("\\color"+s,""); }
|
||||
else { ba.add("\\textcolor"+s+"{","}"); }
|
||||
}
|
||||
}
|
||||
|
||||
private static final String automaticcolor(String sBgColor) {
|
||||
if (sBgColor!=null && sBgColor.length()==7) {
|
||||
float[] rgb = getRgb(sBgColor);
|
||||
if (rgb[RED]+rgb[GREEN]+rgb[BLUE]<0.6) {
|
||||
// Dark background
|
||||
return "{white}";
|
||||
}
|
||||
}
|
||||
return "{black}";
|
||||
}
|
||||
|
||||
private static final String color(String sColor){
|
||||
if ("#000000".equalsIgnoreCase(sColor)) { return "{black}"; }
|
||||
else if ("#ff0000".equalsIgnoreCase(sColor)) { return "{red}"; }
|
||||
else if ("#00ff00".equalsIgnoreCase(sColor)) { return "{green}"; }
|
||||
else if ("#0000ff".equalsIgnoreCase(sColor)) { return "{blue}"; }
|
||||
else if ("#ffff00".equalsIgnoreCase(sColor)) { return "{yellow}"; }
|
||||
else if ("#ff00ff".equalsIgnoreCase(sColor)) { return "{magenta}"; }
|
||||
else if ("#00ffff".equalsIgnoreCase(sColor)) { return "{cyan}"; }
|
||||
//no white, since we don't have background colors:
|
||||
//else if ("#ffffff".equalsIgnoreCase(sColor)) { return "{white}"; }
|
||||
else {
|
||||
if (sColor==null || sColor.length()!=7) return null;
|
||||
float[] rgb = getRgb(sColor);
|
||||
// avoid very bright colors (since we don't have background colors):
|
||||
if (rgb[RED]+rgb[GREEN]+rgb[BLUE]>2.7) { return "{black}"; }
|
||||
else { return "[rgb]{"+rgb[RED]+","+rgb[GREEN]+","+rgb[BLUE]+"}"; }
|
||||
}
|
||||
}
|
||||
|
||||
private static final String fullcolor(String sColor){
|
||||
if ("#000000".equalsIgnoreCase(sColor)) { return "{black}"; }
|
||||
else if ("#ff0000".equalsIgnoreCase(sColor)) { return "{red}"; }
|
||||
else if ("#00ff00".equalsIgnoreCase(sColor)) { return "{green}"; }
|
||||
else if ("#0000ff".equalsIgnoreCase(sColor)) { return "{blue}"; }
|
||||
else if ("#ffff00".equalsIgnoreCase(sColor)) { return "{yellow}"; }
|
||||
else if ("#ff00ff".equalsIgnoreCase(sColor)) { return "{magenta}"; }
|
||||
else if ("#00ffff".equalsIgnoreCase(sColor)) { return "{cyan}"; }
|
||||
else if ("#ffffff".equalsIgnoreCase(sColor)) { return "{white}"; }
|
||||
else {
|
||||
// This could mean transparent:
|
||||
if (sColor==null || sColor.length()!=7) return null;
|
||||
float[] rgb = getRgb(sColor);
|
||||
return "[rgb]{"+rgb[RED]+","+rgb[GREEN]+","+rgb[BLUE]+"}";
|
||||
}
|
||||
}
|
||||
|
||||
private static final float[] getRgb(String sColor) {
|
||||
float[] rgb = new float[3];
|
||||
rgb[RED] = (float)Misc.getIntegerFromHex(sColor.substring(1,3),0)/255;
|
||||
rgb[GREEN] = (float)Misc.getIntegerFromHex(sColor.substring(3,5),0)/255;
|
||||
rgb[BLUE] = (float)Misc.getIntegerFromHex(sColor.substring(5,7),0)/255;
|
||||
return rgb;
|
||||
}
|
||||
|
||||
|
||||
}
|
43
source/java/writer2latex/latex/ContentHandlingOption.java
Normal file
43
source/java/writer2latex/latex/ContentHandlingOption.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ContentHandlingOption.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import writer2latex.base.IntegerOption;
|
||||
|
||||
public class ContentHandlingOption extends IntegerOption {
|
||||
public ContentHandlingOption(String sName, String sDefaultValue) {
|
||||
super(sName,sDefaultValue);
|
||||
}
|
||||
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
if ("accept".equals(sValue)) nValue = LaTeXConfig.ACCEPT;
|
||||
else if ("ignore".equals(sValue)) nValue = LaTeXConfig.IGNORE;
|
||||
else if ("warning".equals(sValue)) nValue = LaTeXConfig.WARNING;
|
||||
else if ("error".equals(sValue)) nValue = LaTeXConfig.ERROR;
|
||||
}
|
||||
}
|
49
source/java/writer2latex/latex/ConverterHelper.java
Normal file
49
source/java/writer2latex/latex/ConverterHelper.java
Normal file
|
@ -0,0 +1,49 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConverterHelper.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import writer2latex.office.OfficeReader;
|
||||
|
||||
/**
|
||||
* <p>This is an abstract superclass for converter helpers.</p>
|
||||
*/
|
||||
public abstract class ConverterHelper {
|
||||
|
||||
protected OfficeReader ofr;
|
||||
protected LaTeXConfig config;
|
||||
protected ConverterPalette palette;
|
||||
|
||||
protected ConverterHelper(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
this.ofr = ofr;
|
||||
this.config = config;
|
||||
this.palette = palette;
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
}
|
||||
|
||||
}
|
303
source/java/writer2latex/latex/ConverterPalette.java
Normal file
303
source/java/writer2latex/latex/ConverterPalette.java
Normal file
|
@ -0,0 +1,303 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConverterPalette.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import writer2latex.api.Config;
|
||||
import writer2latex.api.ConverterFactory;
|
||||
//import writer2latex.api.ConverterResult;
|
||||
import writer2latex.base.ConverterBase;
|
||||
import writer2latex.latex.i18n.ClassicI18n;
|
||||
import writer2latex.latex.i18n.I18n;
|
||||
import writer2latex.latex.i18n.XeTeXI18n;
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.latex.util.Info;
|
||||
import writer2latex.util.CSVList;
|
||||
import writer2latex.util.ExportNameCollection;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.office.MIMETypes;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
import writer2latex.office.XMLString;
|
||||
|
||||
/**
|
||||
* <p>This class converts a Writer XML file to a LaTeX file<.</p>
|
||||
*/
|
||||
public final class ConverterPalette extends ConverterBase {
|
||||
|
||||
// Configuration
|
||||
private LaTeXConfig config;
|
||||
|
||||
public Config getConfig() { return config; }
|
||||
|
||||
// The main outfile
|
||||
private LaTeXDocument texDoc;
|
||||
|
||||
// Various data used in conversion
|
||||
private Context mainContext; // main context
|
||||
private CSVList globalOptions; // global options
|
||||
|
||||
// The helpers (the "colors" of the palette)
|
||||
private I18n i18n;
|
||||
private ColorConverter colorCv;
|
||||
private CharStyleConverter charSc;
|
||||
private ListStyleConverter listSc;
|
||||
private PageStyleConverter pageSc;
|
||||
private BlockConverter blockCv;
|
||||
private ParConverter parCv;
|
||||
private HeadingConverter headingCv;
|
||||
private IndexConverter indexCv;
|
||||
private BibConverter bibCv;
|
||||
private SectionConverter sectionCv;
|
||||
private TableConverter tableCv;
|
||||
private NoteConverter noteCv;
|
||||
private CaptionConverter captionCv;
|
||||
private InlineConverter inlineCv;
|
||||
private FieldConverter fieldCv;
|
||||
private DrawConverter drawCv;
|
||||
private MathmlConverter mathmlCv;
|
||||
private Info info;
|
||||
|
||||
// Constructor
|
||||
public ConverterPalette() {
|
||||
super();
|
||||
config = new LaTeXConfig();
|
||||
}
|
||||
|
||||
// Accessor methods for data
|
||||
|
||||
public String getOutFileName() { return sTargetFileName; }
|
||||
|
||||
public Context getMainContext() { return mainContext; }
|
||||
|
||||
public void addGlobalOption(String sOption) {
|
||||
globalOptions.addValue(sOption);
|
||||
}
|
||||
|
||||
// Accessor methods for helpers
|
||||
public I18n getI18n() { return i18n; }
|
||||
public ColorConverter getColorCv() { return colorCv; }
|
||||
public CharStyleConverter getCharSc() { return charSc; }
|
||||
public ListStyleConverter getListSc() { return listSc; }
|
||||
public PageStyleConverter getPageSc() { return pageSc; }
|
||||
public BlockConverter getBlockCv() { return blockCv; }
|
||||
public ParConverter getParCv() { return parCv; }
|
||||
public HeadingConverter getHeadingCv() { return headingCv; }
|
||||
public IndexConverter getIndexCv() { return indexCv; }
|
||||
public BibConverter getBibCv() { return bibCv; }
|
||||
public SectionConverter getSectionCv() { return sectionCv; }
|
||||
public TableConverter getTableCv() { return tableCv; }
|
||||
public NoteConverter getNoteCv() { return noteCv; }
|
||||
public CaptionConverter getCaptionCv() { return captionCv; }
|
||||
public InlineConverter getInlineCv() { return inlineCv; }
|
||||
public FieldConverter getFieldCv() { return fieldCv; }
|
||||
public DrawConverter getDrawCv() { return drawCv; }
|
||||
public MathmlConverter getMathmlCv() { return mathmlCv; }
|
||||
public Info getInfo() { return info; }
|
||||
|
||||
|
||||
// fill out inner converter method
|
||||
public void convertInner() throws IOException {
|
||||
sTargetFileName = Misc.trimDocumentName(sTargetFileName,".tex");
|
||||
imageLoader.setOutFileName(new ExportNameCollection(true).getExportName(sTargetFileName));
|
||||
|
||||
imageLoader.setUseSubdir(config.saveImagesInSubdir());
|
||||
|
||||
// Set graphics formats depending on backend
|
||||
if (config.getBackend()==LaTeXConfig.PDFTEX || config.getBackend()==LaTeXConfig.XETEX) {
|
||||
imageLoader.setDefaultFormat(MIMETypes.PNG);
|
||||
imageLoader.setDefaultVectorFormat(MIMETypes.PDF);
|
||||
imageLoader.addAcceptedFormat(MIMETypes.JPEG);
|
||||
}
|
||||
else if (config.getBackend()==LaTeXConfig.DVIPS) {
|
||||
imageLoader.setDefaultFormat(MIMETypes.EPS);
|
||||
}
|
||||
// Other values: keep original format
|
||||
|
||||
// Inject user sequence names for tables and figures into OfficeReader
|
||||
if (config.getTableSequenceName().length()>0) {
|
||||
ofr.addTableSequenceName(config.getTableSequenceName());
|
||||
}
|
||||
if (config.getFigureSequenceName().length()>0) {
|
||||
ofr.addFigureSequenceName(config.getFigureSequenceName());
|
||||
}
|
||||
|
||||
// Create helpers
|
||||
if (config.getBackend()!=LaTeXConfig.XETEX) {
|
||||
i18n = new ClassicI18n(ofr,config,this);
|
||||
}
|
||||
else {
|
||||
i18n = new XeTeXI18n(ofr,config,this);
|
||||
}
|
||||
colorCv = new ColorConverter(ofr,config,this);
|
||||
charSc = new CharStyleConverter(ofr,config,this);
|
||||
listSc = new ListStyleConverter(ofr,config,this);
|
||||
pageSc = new PageStyleConverter(ofr,config,this);
|
||||
blockCv = new BlockConverter(ofr,config,this);
|
||||
parCv = new ParConverter(ofr,config,this);
|
||||
headingCv = new HeadingConverter(ofr,config,this);
|
||||
indexCv = new IndexConverter(ofr,config,this);
|
||||
bibCv = new BibConverter(ofr,config,this);
|
||||
sectionCv = new SectionConverter(ofr,config,this);
|
||||
tableCv = new TableConverter(ofr,config,this);
|
||||
noteCv = new NoteConverter(ofr,config,this);
|
||||
captionCv = new CaptionConverter(ofr,config,this);
|
||||
inlineCv = new InlineConverter(ofr,config,this);
|
||||
fieldCv = new FieldConverter(ofr,config,this);
|
||||
drawCv = new DrawConverter(ofr,config,this);
|
||||
mathmlCv = new MathmlConverter(ofr,config,this);
|
||||
info = new Info(ofr,config,this);
|
||||
|
||||
// Create master document and add this
|
||||
this.texDoc = new LaTeXDocument(sTargetFileName,config.getWrapLinesAfter());
|
||||
if (config.getBackend()!=LaTeXConfig.XETEX) {
|
||||
texDoc.setEncoding(ClassicI18n.writeJavaEncoding(config.getInputencoding()));
|
||||
}
|
||||
else {
|
||||
texDoc.setEncoding("UTF-8");
|
||||
|
||||
}
|
||||
convertData.addDocument(texDoc);
|
||||
|
||||
// Create other data
|
||||
globalOptions = new CSVList(',');
|
||||
|
||||
// Setup context.
|
||||
// The default language is specified in the default paragraph style:
|
||||
mainContext = new Context();
|
||||
mainContext.resetFormattingFromStyle(ofr.getDefaultParStyle());
|
||||
mainContext.setInMulticols(pageSc.isTwocolumn());
|
||||
|
||||
// Create main LaTeXDocumentPortions
|
||||
LaTeXDocumentPortion packages = new LaTeXDocumentPortion(false);
|
||||
LaTeXDocumentPortion declarations = new LaTeXDocumentPortion(false);
|
||||
LaTeXDocumentPortion body = new LaTeXDocumentPortion(true);
|
||||
|
||||
// Traverse the content
|
||||
Element content = ofr.getContent();
|
||||
blockCv.traverseBlockText(content,body,mainContext);
|
||||
noteCv.insertEndnotes(body);
|
||||
|
||||
// Add declarations from our helpers
|
||||
i18n.appendDeclarations(packages,declarations);
|
||||
colorCv.appendDeclarations(packages,declarations);
|
||||
charSc.appendDeclarations(packages,declarations);
|
||||
headingCv.appendDeclarations(packages,declarations);
|
||||
parCv.appendDeclarations(packages,declarations);
|
||||
listSc.appendDeclarations(packages,declarations);
|
||||
pageSc.appendDeclarations(packages,declarations);
|
||||
blockCv.appendDeclarations(packages,declarations);
|
||||
indexCv.appendDeclarations(packages,declarations);
|
||||
bibCv.appendDeclarations(packages,declarations);
|
||||
sectionCv.appendDeclarations(packages,declarations);
|
||||
tableCv.appendDeclarations(packages,declarations);
|
||||
noteCv.appendDeclarations(packages,declarations);
|
||||
captionCv.appendDeclarations(packages,declarations);
|
||||
inlineCv.appendDeclarations(packages,declarations);
|
||||
fieldCv.appendDeclarations(packages,declarations);
|
||||
drawCv.appendDeclarations(packages,declarations);
|
||||
mathmlCv.appendDeclarations(packages,declarations);
|
||||
|
||||
// Add custom preamble
|
||||
LinkedList customPreamble = config.getCustomPreamble();
|
||||
int nCPLen = customPreamble.size();
|
||||
for (int i=0; i<nCPLen; i++) {
|
||||
declarations.append( (String) customPreamble.get(i) ).nl();
|
||||
}
|
||||
|
||||
// Set \title, \author and \date (for \maketitle)
|
||||
createMeta("title",metaData.getTitle(),declarations);
|
||||
if (config.metadata()) {
|
||||
createMeta("author",metaData.getCreator(),declarations);
|
||||
// According to the spec, the date has the format YYYY-MM-DDThh:mm:ss
|
||||
String sDate = metaData.getDate();
|
||||
if (sDate.length()==19 && sDate.charAt(10)=='T') {
|
||||
sDate = sDate.substring(0,10);
|
||||
}
|
||||
createMeta("date",sDate,declarations);
|
||||
}
|
||||
|
||||
// Create options for documentclass
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) {
|
||||
StyleWithProperties dpStyle = ofr.getDefaultParStyle();
|
||||
if (dpStyle!=null) {
|
||||
String s = dpStyle.getProperty(XMLString.FO_FONT_SIZE);
|
||||
if ("10pt".equals(s)) { globalOptions.addValue("10pt"); }
|
||||
if ("11pt".equals(s)) { globalOptions.addValue("11pt"); }
|
||||
if ("12pt".equals(s)) { globalOptions.addValue("12pt"); }
|
||||
}
|
||||
}
|
||||
|
||||
// Temp solution. TODO: Fix when new CSVList is implemented
|
||||
if (config.getGlobalOptions().length()>0) {
|
||||
globalOptions.addValue(config.getGlobalOptions());
|
||||
}
|
||||
|
||||
// Assemble the document
|
||||
LaTeXDocumentPortion result = texDoc.getContents();
|
||||
|
||||
if (!config.noPreamble()) {
|
||||
// Create document class declaration
|
||||
result.append("% This file was converted to LaTeX by Writer2LaTeX ver. "+ConverterFactory.getVersion()).nl()
|
||||
.append("% see http://www.hj-gym.dk/~hj/writer2latex for more info").nl();
|
||||
result.append("\\documentclass");
|
||||
if (!globalOptions.isEmpty()) {
|
||||
result.append("[").append(globalOptions.toString()).append("]");
|
||||
}
|
||||
result.append("{").append(config.getDocumentclass()).append("}").nl();
|
||||
|
||||
result.append(packages)
|
||||
.append(declarations)
|
||||
.append("\\begin{document}").nl();
|
||||
}
|
||||
|
||||
result.append(body);
|
||||
|
||||
if (!config.noPreamble()) {
|
||||
result.append("\\end{document}").nl();
|
||||
}
|
||||
else {
|
||||
result.append("\\endinput").nl();
|
||||
}
|
||||
|
||||
// Add BibTeX document if there's any bibliographic data
|
||||
if (bibCv.getBibTeXDocument()!=null) {
|
||||
convertData.addDocument(bibCv.getBibTeXDocument());
|
||||
}
|
||||
}
|
||||
|
||||
private void createMeta(String sName, String sValue,LaTeXDocumentPortion ldp) {
|
||||
if (sValue==null) { return; }
|
||||
// Meta data is assumed to be in the default language:
|
||||
ldp.append("\\"+sName+"{"+i18n.convert(sValue,false,mainContext.getLang())+"}").nl();
|
||||
}
|
||||
|
||||
|
||||
}
|
496
source/java/writer2latex/latex/DrawConverter.java
Normal file
496
source/java/writer2latex/latex/DrawConverter.java
Normal file
|
@ -0,0 +1,496 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* DrawConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
//import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.xmerge.EmbeddedObject;
|
||||
import writer2latex.xmerge.EmbeddedXMLObject;
|
||||
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
//import writer2latex.office.ImageLoader;
|
||||
import writer2latex.office.MIMETypes;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.CSVList;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.xmerge.BinaryGraphicsDocument;
|
||||
|
||||
/**
|
||||
* <p>This class handles draw elements.</p>
|
||||
*/
|
||||
public class DrawConverter extends ConverterHelper {
|
||||
|
||||
private boolean bNeedGraphicx = false;
|
||||
private boolean bNeedOOoLaTeXPreamble = false;
|
||||
|
||||
// Keep track of floating frames (images, textboxes...)
|
||||
private Stack floatingFramesStack = new Stack();
|
||||
|
||||
private Element getFrame(Element onode) {
|
||||
if (ofr.isOpenDocument()) return (Element) onode.getParentNode();
|
||||
else return onode;
|
||||
}
|
||||
|
||||
public DrawConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
floatingFramesStack.push(new LinkedList());
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bNeedGraphicx) {
|
||||
pack.append("\\usepackage");
|
||||
if (config.getBackend()==LaTeXConfig.PDFTEX) pack.append("[pdftex]");
|
||||
//else if (config.getBackend()==LaTeXConfig.XETEX) pack.append("[xetex]");
|
||||
else if (config.getBackend()==LaTeXConfig.DVIPS) pack.append("[dvips]");
|
||||
pack.append("{graphicx}").nl();
|
||||
}
|
||||
if (bNeedOOoLaTeXPreamble) {
|
||||
// The preamble may be stored in the description
|
||||
String sDescription = palette.getMetaData().getDescription();
|
||||
int nStart = sDescription.indexOf("%%% OOoLatex Preamble %%%%%%%%%%%%%%");
|
||||
int nEnd = sDescription.indexOf("%%% End OOoLatex Preamble %%%%%%%%%%%%");
|
||||
if (nStart>-1 && nEnd>nStart) {
|
||||
decl.append("% OOoLaTeX preamble").nl()
|
||||
.append(sDescription.substring(nStart+37,nEnd));
|
||||
}
|
||||
// TODO: Otherwise try the user settings...
|
||||
}
|
||||
}
|
||||
|
||||
public void handleCaption(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Floating frames should be positioned *above* the label, hence
|
||||
// we use a separate ldp for the paragraphs and add this later
|
||||
LaTeXDocumentPortion capLdp = new LaTeXDocumentPortion(true);
|
||||
|
||||
// Convert the caption
|
||||
if (oc.isInFigureFloat()) { // float
|
||||
capLdp.append("\\caption");
|
||||
palette.getCaptionCv().handleCaptionBody(node,capLdp,oc,false);
|
||||
}
|
||||
else { // nonfloat
|
||||
capLdp.append("\\captionof{figure}");
|
||||
palette.getCaptionCv().handleCaptionBody(node,capLdp,oc,true);
|
||||
}
|
||||
|
||||
flushFloatingFrames(ldp,oc);
|
||||
ldp.append(capLdp);
|
||||
}
|
||||
|
||||
public void handleDrawElement(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// node must be an elment in the draw namespace
|
||||
String sName = node.getTagName();
|
||||
if (sName.equals(XMLString.DRAW_OBJECT)) {
|
||||
handleDrawObject(node,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.DRAW_OBJECT_OLE)) {
|
||||
handleDrawObject(node,ldp,oc);
|
||||
}
|
||||
else if ((!oc.isInHeaderFooter()) && sName.equals(XMLString.DRAW_IMAGE)) {
|
||||
handleDrawImage(node,ldp,oc);
|
||||
}
|
||||
else if ((!oc.isInHeaderFooter()) && sName.equals(XMLString.DRAW_TEXT_BOX)) {
|
||||
handleDrawTextBox(node,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.DRAW_A)) {
|
||||
// we handle this like text:a
|
||||
palette.getFieldCv().handleAnchor(node,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.DRAW_FRAME)) {
|
||||
// OpenDocument: Get the actual draw element in the frame
|
||||
handleDrawElement(Misc.getFirstChildElement(node),ldp,oc);
|
||||
}
|
||||
else {
|
||||
// Other drawing objects (eg. shapes) are currently not supported
|
||||
ldp.append("[Warning: Draw object ignored]");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// handle draw:object elements (OOo objects such as Chart, Math,...)
|
||||
|
||||
private void handleDrawObject(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sHref = Misc.getAttribute(node,XMLString.XLINK_HREF);
|
||||
|
||||
if (sHref!=null) { // Embedded object in package or linked object
|
||||
if (ofr.isInPackage(sHref)) { // Embedded object in package
|
||||
if (sHref.startsWith("#")) { sHref=sHref.substring(1); }
|
||||
if (sHref.startsWith("./")) { sHref=sHref.substring(2); }
|
||||
EmbeddedObject object = palette.getEmbeddedObject(sHref);
|
||||
if (object!=null) {
|
||||
if (MIMETypes.MATH.equals(object.getType()) || MIMETypes.ODF.equals(object.getType())) { // Formula!
|
||||
try {
|
||||
Document settings = ((EmbeddedXMLObject) object).getSettingsDOM();
|
||||
Document formuladoc = ((EmbeddedXMLObject) object).getContentDOM();
|
||||
Element formula = Misc.getChildByTagName(formuladoc,XMLString.MATH_MATH);
|
||||
ldp.append(" $")
|
||||
.append(palette.getMathmlCv().convert(settings,formula))
|
||||
.append("$");
|
||||
if (Character.isLetterOrDigit(OfficeReader.getNextChar(node))) { ldp.append(" "); }
|
||||
}
|
||||
catch (org.xml.sax.SAXException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (java.io.IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
else { // unsupported object
|
||||
boolean bIgnore = true;
|
||||
if (ofr.isOpenDocument()) { // look for replacement image
|
||||
Element replacementImage = Misc.getChildByTagName(getFrame(node),XMLString.DRAW_IMAGE);
|
||||
if (replacementImage!=null) {
|
||||
handleDrawImage(replacementImage,ldp,oc);
|
||||
bIgnore = false;
|
||||
}
|
||||
}
|
||||
if (bIgnore) {
|
||||
ldp.append("[Warning: object ignored]");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // flat xml, object is contained in node
|
||||
Element formula = Misc.getChildByTagName(node,XMLString.MATH_MATH);
|
||||
if (formula!=null) {
|
||||
ldp.append(" $")
|
||||
.append(palette.getMathmlCv().convert(null,formula))
|
||||
.append("$");
|
||||
if (Character.isLetterOrDigit(OfficeReader.getNextChar(node))) { ldp.append(" "); }
|
||||
}
|
||||
else { // unsupported object
|
||||
boolean bIgnore = true;
|
||||
if (ofr.isOpenDocument()) { // look for replacement image
|
||||
Element replacementImage = Misc.getChildByTagName(getFrame(node),XMLString.DRAW_IMAGE);
|
||||
if (replacementImage!=null) {
|
||||
handleDrawImage(replacementImage,ldp,oc);
|
||||
bIgnore = false;
|
||||
}
|
||||
}
|
||||
if (bIgnore) {
|
||||
ldp.append("[Warning: object ignored]");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Create float environment
|
||||
private void applyFigureFloat(BeforeAfter ba, Context oc) {
|
||||
// todo: check context...
|
||||
if (config.floatFigures() && !oc.isInFrame() && !oc.isInTable()) {
|
||||
if (oc.isInMulticols()) {
|
||||
ba.add("\\begin{figure*}","\\end{figure*}\n");
|
||||
}
|
||||
else {
|
||||
ba.add("\\begin{figure}","\\end{figure}\n");
|
||||
}
|
||||
if (config.getFloatOptions().length()>0) {
|
||||
ba.add("["+config.getFloatOptions()+"]","");
|
||||
}
|
||||
ba.add("\n","");
|
||||
oc.setInFigureFloat(true);
|
||||
}
|
||||
if (!oc.isInFrame() && config.alignFrames()) {
|
||||
// Avoid nesting center environment
|
||||
ba.add("\\begin{center}\n","\n\\end{center}\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handle draw:image elements
|
||||
|
||||
private void handleDrawImage(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Include graphics if allowed by the configuration
|
||||
switch (config.imageContent()) {
|
||||
case LaTeXConfig.IGNORE:
|
||||
// Ignore graphics silently
|
||||
return;
|
||||
case LaTeXConfig.WARNING:
|
||||
System.err.println("Warning: Images are not allowed");
|
||||
return;
|
||||
case LaTeXConfig.ERROR:
|
||||
ldp.append("% Error in document: An image was ignored");
|
||||
return;
|
||||
}
|
||||
|
||||
Element frame = getFrame(node);
|
||||
//String sName = frame.getAttribute(XMLString.DRAW_NAME);
|
||||
palette.getFieldCv().addTarget(frame,"|graphics",ldp);
|
||||
String sAnchor = frame.getAttribute(XMLString.TEXT_ANCHOR_TYPE);
|
||||
|
||||
// TODO: Recognize Jex equations (needs further testing of Jex)
|
||||
/*Element desc = Misc.getChildByTagName(frame,XMLString.SVG_DESC);
|
||||
if (desc!=null) {
|
||||
String sDesc = Misc.getPCDATA(desc);
|
||||
if (sDesc.startsWith("jex149$tex={") && sDesc.endsWith("}")) {
|
||||
String sTeX = sDesc.substring(12,sDesc.length()-1);
|
||||
if (sTeX.length()>0) {
|
||||
// Succesfully extracted Jex equation!
|
||||
ldp.append("$"+sTeX+"$");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// Recognize OOoLaTeX equation
|
||||
// The LaTeX code is embedded in a custom style attribute:
|
||||
StyleWithProperties style = ofr.getFrameStyle(
|
||||
Misc.getAttribute(frame, XMLString.DRAW_STYLE_NAME));
|
||||
if (style!=null) {
|
||||
String sOOoLaTeX = style.getProperty("OOoLatexArgs");
|
||||
// The content of the attribute is <point size><paragraph sign><mode><paragraph sign><TeX code>
|
||||
int n=0;
|
||||
if (sOOoLaTeX!=null) {
|
||||
if ((n=sOOoLaTeX.indexOf("\u00A7display\u00A7"))>-1) {
|
||||
ldp.append("\\[").append(sOOoLaTeX.substring(n+9)).append("\\]");
|
||||
bNeedOOoLaTeXPreamble = true;
|
||||
return;
|
||||
}
|
||||
else if ((n=sOOoLaTeX.indexOf("\u00A7inline\u00A7"))>-1) {
|
||||
ldp.append("$").append(sOOoLaTeX.substring(n+8)).append("$");
|
||||
bNeedOOoLaTeXPreamble = true;
|
||||
return;
|
||||
}
|
||||
else if ((n=sOOoLaTeX.indexOf("\u00A7text\u00A7"))>-1) {
|
||||
ldp.append(sOOoLaTeX.substring(n+6));
|
||||
bNeedOOoLaTeXPreamble = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (oc.isInFrame() || "as-char".equals(sAnchor)) {
|
||||
if ("as-char".equals(sAnchor)) {
|
||||
handleDrawImageAsChar(node,ldp,oc);
|
||||
}
|
||||
else {
|
||||
((LinkedList) floatingFramesStack.peek()).add(node);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDrawImageAsChar(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append(" ");
|
||||
includeGraphics(node,ldp,oc);
|
||||
ldp.append(" ");
|
||||
}
|
||||
|
||||
private void handleDrawImageFloat(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Context ic = (Context) oc.clone();
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
|
||||
applyFigureFloat(ba,ic);
|
||||
|
||||
ldp.append(ba.getBefore());
|
||||
includeGraphics(node,ldp,ic);
|
||||
ldp.append(ba.getAfter());
|
||||
}
|
||||
|
||||
private void includeGraphics(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sFileName = null;
|
||||
boolean bCommentOut = true;
|
||||
String sHref = node.getAttribute(XMLString.XLINK_HREF);
|
||||
|
||||
if (node.hasAttribute(XMLString.XLINK_HREF) && !ofr.isInPackage(sHref)) {
|
||||
// Linked image is not yet handled by ImageLoader. This is a temp.
|
||||
// solution (will go away when ImageLoader is finished)
|
||||
sFileName = sHref;
|
||||
// In OpenDocument package format ../ means "leave the package"
|
||||
if (ofr.isOpenDocument() && ofr.isPackageFormat() && sFileName.startsWith("../")) {
|
||||
sFileName=sFileName.substring(3);
|
||||
}
|
||||
int nExtStart = sHref.lastIndexOf(".");
|
||||
String sExt = nExtStart>=0 ? sHref.substring(nExtStart).toLowerCase() : "";
|
||||
// Accept only relative filenames and supported filetypes:
|
||||
bCommentOut = sFileName.indexOf(":")>-1 || !(
|
||||
config.getBackend()==LaTeXConfig.UNSPECIFIED ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.JPEG_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.PNG_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.PDF_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.JPEG_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.PNG_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.PDF_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.DVIPS && MIMETypes.EPS_EXT.equals(sExt)));
|
||||
}
|
||||
else { // embedded or base64 encoded image
|
||||
BinaryGraphicsDocument bgd = palette.getImageLoader().getImage(node);
|
||||
if (bgd!=null) {
|
||||
palette.addDocument(bgd);
|
||||
sFileName = bgd.getFileName();
|
||||
String sMIME = bgd.getDocumentMIMEType();
|
||||
bCommentOut = !(
|
||||
config.getBackend()==LaTeXConfig.UNSPECIFIED ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.JPEG.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.PNG.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.PDF.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.JPEG.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.PNG.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.PDF.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.DVIPS && MIMETypes.EPS.equals(sMIME)));
|
||||
}
|
||||
}
|
||||
|
||||
if (sFileName==null) {
|
||||
ldp.append("[Warning: Image not found]");
|
||||
return;
|
||||
}
|
||||
|
||||
// Now for the actual inclusion:
|
||||
bNeedGraphicx = true;
|
||||
/* TODO: handle cropping and mirror:
|
||||
style:mirror can be none, vertical (lodret), horizontal (vandret),
|
||||
horizontal-on-odd, or
|
||||
horizontal-on-even (horizontal on odd or even pages).
|
||||
mirror is handled with scalebox, eg:
|
||||
%\\scalebox{-1}[1]{...}
|
||||
can check for even/odd page first!!
|
||||
|
||||
fo:clip="rect(t,r,b,l) svarer til trim
|
||||
value can be auto - no clip!
|
||||
cropping is handled with clip and trim:
|
||||
\\includegraphics[clip,trim=l b r t]{...}
|
||||
note the different order from xsl-fo!
|
||||
*/
|
||||
|
||||
if (bCommentOut) {
|
||||
ldp.append(" [Warning: Image ignored] ");
|
||||
ldp.append("% Unhandled or unsupported graphics:").nl().append("%");
|
||||
}
|
||||
ldp.append("\\includegraphics");
|
||||
|
||||
CSVList options = new CSVList(',');
|
||||
if (!config.originalImageSize()) {
|
||||
Element frame = getFrame(node);
|
||||
String sWidth = Misc.truncateLength(frame.getAttribute(XMLString.SVG_WIDTH));
|
||||
String sHeight = Misc.truncateLength(frame.getAttribute(XMLString.SVG_HEIGHT));
|
||||
if (sWidth!=null) { options.addValue("width="+sWidth); }
|
||||
if (sHeight!=null) { options.addValue("height="+sHeight); }
|
||||
}
|
||||
if (config.getImageOptions().length()>0) {
|
||||
options.addValue(config.getImageOptions()); // TODO: New CSVList...
|
||||
}
|
||||
if (!options.isEmpty()) {
|
||||
ldp.append("[").append(options.toString()).append("]");
|
||||
}
|
||||
|
||||
if (config.removeGraphicsExtension()) {
|
||||
sFileName = Misc.removeExtension(sFileName);
|
||||
}
|
||||
ldp.append("{").append(sFileName).append("}");
|
||||
if (bCommentOut) { ldp.nl(); }
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// handle draw:text-box element
|
||||
|
||||
private void handleDrawTextBox(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Element frame = getFrame(node);
|
||||
//String sName = frame.getAttribute(XMLString.DRAW_NAME);
|
||||
palette.getFieldCv().addTarget(frame,"|frame",ldp);
|
||||
String sAnchor = frame.getAttribute(XMLString.TEXT_ANCHOR_TYPE);
|
||||
//if (oc.isInFrame() || "as-char".equals(sAnchor)) {
|
||||
if ("as-char".equals(sAnchor)) {
|
||||
makeDrawTextBox(node, ldp, oc);
|
||||
}
|
||||
else {
|
||||
((LinkedList) floatingFramesStack.peek()).add(node);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDrawTextBoxFloat(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
Context ic = (Context) oc.clone();
|
||||
|
||||
applyFigureFloat(ba,ic);
|
||||
|
||||
ldp.append(ba.getBefore());
|
||||
makeDrawTextBox(node, ldp, ic);
|
||||
ldp.append(ba.getAfter());
|
||||
}
|
||||
|
||||
private void makeDrawTextBox(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInFrame(true);
|
||||
ic.setNoFootnotes(true);
|
||||
|
||||
// Check to see, if this is really a container for a figure caption
|
||||
boolean bIsCaption = false;
|
||||
if (OfficeReader.isSingleParagraph(node)) {
|
||||
Element par = Misc.getFirstChildElement(node);
|
||||
String sSeqName = ofr.getSequenceName(par);
|
||||
if (ofr.isFigureSequenceName(sSeqName)) { bIsCaption = true; }
|
||||
}
|
||||
|
||||
String sWidth = Misc.truncateLength(getFrame(node).getAttribute(XMLString.SVG_WIDTH));
|
||||
if (!bIsCaption) {
|
||||
ldp.append("\\begin{minipage}{").append(sWidth).append("}").nl();
|
||||
}
|
||||
floatingFramesStack.push(new LinkedList());
|
||||
palette.getBlockCv().traverseBlockText(node,ldp,ic);
|
||||
flushFloatingFrames(ldp,ic);
|
||||
floatingFramesStack.pop();
|
||||
if (!bIsCaption) {
|
||||
ldp.append("\\end{minipage}");
|
||||
}
|
||||
if (!oc.isNoFootnotes()) { palette.getNoteCv().flushFootnotes(ldp,oc); }
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//handle any pending floating frames
|
||||
|
||||
public void flushFloatingFrames(LaTeXDocumentPortion ldp, Context oc) {
|
||||
// todo: fix language
|
||||
LinkedList floatingFrames = (LinkedList) floatingFramesStack.peek();
|
||||
int n = floatingFrames.size();
|
||||
if (n==0) { return; }
|
||||
for (int i=0; i<n; i++) {
|
||||
Element node = (Element) floatingFrames.get(i);
|
||||
String sName = node.getNodeName();
|
||||
if (sName.equals(XMLString.DRAW_IMAGE)) {
|
||||
handleDrawImageFloat(node,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.DRAW_TEXT_BOX)) {
|
||||
handleDrawTextBoxFloat(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
floatingFrames.clear();
|
||||
}
|
||||
|
||||
}
|
672
source/java/writer2latex/latex/FieldConverter.java
Normal file
672
source/java/writer2latex/latex/FieldConverter.java
Normal file
|
@ -0,0 +1,672 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* FieldConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
//import java.io.UnsupportedEncodingException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.latex.util.HeadingMap;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.CSVList;
|
||||
import writer2latex.util.ExportNameCollection;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.util.SimpleInputBuffer;
|
||||
|
||||
/**
|
||||
* This class handles text fields and links in the document.
|
||||
* Packages: lastpage, hyperref, titleref, oooref (all optional)
|
||||
* TODO: Need proper treatment of "caption" and "text" for sequence
|
||||
* references not to figures and tables (should be fairly rare, though)
|
||||
|
||||
*/
|
||||
public class FieldConverter extends ConverterHelper {
|
||||
|
||||
// Links & references
|
||||
private ExportNameCollection targets = new ExportNameCollection(true);
|
||||
private ExportNameCollection refnames = new ExportNameCollection(true);
|
||||
private ExportNameCollection bookmarknames = new ExportNameCollection(true);
|
||||
private ExportNameCollection seqnames = new ExportNameCollection(true);
|
||||
private ExportNameCollection seqrefnames = new ExportNameCollection(true);
|
||||
|
||||
// sequence declarations (maps name->text:sequence-decl element)
|
||||
private Hashtable seqDecl = new Hashtable();
|
||||
// first usage of sequence (maps name->text:sequence element)
|
||||
private Hashtable seqFirst = new Hashtable();
|
||||
|
||||
private Vector postponedReferenceMarks = new Vector();
|
||||
private Vector postponedBookmarks = new Vector();
|
||||
|
||||
private boolean bUseHyperref = false;
|
||||
private boolean bUsesPageCount = false;
|
||||
private boolean bUsesTitleref = false;
|
||||
private boolean bUsesOooref = false;
|
||||
|
||||
public FieldConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
// hyperref.sty is not compatible with titleref.sty and oooref.sty:
|
||||
bUseHyperref = config.useHyperref() && !config.useTitleref() && !config.useOooref();
|
||||
}
|
||||
|
||||
/** <p>Append declarations needed by the <code>FieldConverter</code> to
|
||||
* the preamble.</p>
|
||||
* @param pack the <code>LaTeXDocumentPortion</code> to which
|
||||
* declarations of packages should be added (<code>\\usepackage</code>).
|
||||
* @param decl the <code>LaTeXDocumentPortion</code> to which
|
||||
* other declarations should be added.
|
||||
*/
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
// use lastpage.sty
|
||||
if (bUsesPageCount) {
|
||||
pack.append("\\usepackage{lastpage}").nl();
|
||||
}
|
||||
|
||||
// use titleref.sty
|
||||
if (bUsesTitleref) {
|
||||
pack.append("\\usepackage{titleref}").nl();
|
||||
}
|
||||
|
||||
// use oooref.sty
|
||||
if (bUsesOooref) {
|
||||
pack.append("\\usepackage[");
|
||||
HeadingMap hm = config.getHeadingMap();
|
||||
CSVList opt = new CSVList(",");
|
||||
for (int i=0; i<=hm.getMaxLevel(); i++) { opt.addValue(hm.getName(i)); }
|
||||
pack.append(opt.toString()).append("]{oooref}").nl();
|
||||
}
|
||||
|
||||
// use hyperref.sty
|
||||
if (bUseHyperref){
|
||||
pack.append("\\usepackage{hyperref}").nl();
|
||||
pack.append("\\hypersetup{");
|
||||
if (config.getBackend()==LaTeXConfig.PDFTEX) pack.append("pdftex, ");
|
||||
else if (config.getBackend()==LaTeXConfig.DVIPS) pack.append("dvips, ");
|
||||
//else pack.append("hypertex");
|
||||
pack.append("colorlinks=true, linkcolor=blue, citecolor=blue, filecolor=blue, urlcolor=blue");
|
||||
if (config.getBackend()==LaTeXConfig.PDFTEX) {
|
||||
pack.append(createPdfMeta("pdftitle",palette.getMetaData().getTitle()));
|
||||
if (config.metadata()) {
|
||||
pack.append(createPdfMeta("pdfauthor",palette.getMetaData().getCreator()))
|
||||
.append(createPdfMeta("pdfsubject",palette.getMetaData().getSubject()))
|
||||
.append(createPdfMeta("pdfkeywords",palette.getMetaData().getKeywords()));
|
||||
}
|
||||
}
|
||||
pack.append("}").nl();
|
||||
}
|
||||
|
||||
// Export sequence declarations
|
||||
// The number format is fetched from the first occurence of the
|
||||
// sequence in the text, while the outline level and the separation
|
||||
// character are fetched from the declaration
|
||||
Enumeration names = seqFirst.keys();
|
||||
while (names.hasMoreElements()) {
|
||||
// Get first text:sequence element
|
||||
String sName = (String) names.nextElement();
|
||||
Element first = (Element) seqFirst.get(sName);
|
||||
// Collect data
|
||||
String sNumFormat = Misc.getAttribute(first,XMLString.STYLE_NUM_FORMAT);
|
||||
if (sNumFormat==null) { sNumFormat="1"; }
|
||||
int nLevel = 0;
|
||||
String sSepChar = ".";
|
||||
if (seqDecl.containsKey(sName)) {
|
||||
Element sdecl = (Element) seqDecl.get(sName);
|
||||
nLevel = Misc.getPosInteger(sdecl.getAttribute(XMLString.TEXT_DISPLAY_OUTLINE_LEVEL),0);
|
||||
if (sdecl.hasAttribute(XMLString.TEXT_SEPARATION_CHARACTER)) {
|
||||
sSepChar = palette.getI18n().convert(
|
||||
sdecl.getAttribute(XMLString.TEXT_SEPARATION_CHARACTER),
|
||||
false,palette.getMainContext().getLang());
|
||||
}
|
||||
}
|
||||
// Create counter
|
||||
decl.append("\\newcounter{")
|
||||
.append(seqnames.getExportName(sName))
|
||||
.append("}");
|
||||
String sPrefix = "";
|
||||
if (nLevel>0) {
|
||||
HeadingMap hm = config.getHeadingMap();
|
||||
int nUsedLevel = nLevel<=hm.getMaxLevel() ? nLevel : hm.getMaxLevel();
|
||||
if (nUsedLevel>0) {
|
||||
decl.append("[").append(hm.getName(nUsedLevel)).append("]");
|
||||
sPrefix = "\\the"+hm.getName(nUsedLevel)+sSepChar;
|
||||
}
|
||||
}
|
||||
decl.nl()
|
||||
.append("\\renewcommand\\the")
|
||||
.append(seqnames.getExportName(sName))
|
||||
.append("{").append(sPrefix)
|
||||
.append(ListStyleConverter.numFormat(sNumFormat))
|
||||
.append("{").append(seqnames.getExportName(sName))
|
||||
.append("}}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process sequence declarations</p>
|
||||
* @param node the text:sequence-decls node
|
||||
*/
|
||||
public void handleSequenceDecls(Element node) {
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (Misc.isElement(child,XMLString.TEXT_SEQUENCE_DECL)) {
|
||||
// Don't process the declaration, but store a reference
|
||||
seqDecl.put(((Element)child).getAttribute(XMLString.TEXT_NAME),child);
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a sequence field (text:sequence tag)</p>
|
||||
* @param node The element containing the sequence field
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleSequence(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sName = Misc.getAttribute(node,XMLString.TEXT_NAME);
|
||||
String sRefName = Misc.getAttribute(node,XMLString.TEXT_REF_NAME);
|
||||
String sFormula = Misc.getAttribute(node,XMLString.TEXT_FORMULA);
|
||||
if (sFormula==null) {
|
||||
// If there's no formula, we must use the content as formula
|
||||
// The parser below requires a namespace, so we add that..
|
||||
sFormula = "ooow:"+Misc.getPCDATA(node);
|
||||
}
|
||||
if (sName!=null) {
|
||||
if (ofr.isFigureSequenceName(sName) || ofr.isTableSequenceName(sName)) {
|
||||
// Export \label only, assuming the number is generated by \caption
|
||||
if (sRefName!=null && ofr.hasSequenceRefTo(sRefName)) {
|
||||
ldp.append("\\label{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// General purpose sequence -> export as counter
|
||||
if (!seqFirst.containsKey(sName)) {
|
||||
// Save first occurence -> used to determine number format
|
||||
seqFirst.put(sName,node);
|
||||
}
|
||||
if (sRefName!=null && ofr.hasSequenceRefTo(sRefName)) {
|
||||
// Export as {\refstepcounter{name}\thename\label{refname}}
|
||||
ldp.append("{").append(changeCounter(sName,sFormula,true))
|
||||
.append("\\the").append(seqnames.getExportName(sName))
|
||||
.append("\\label{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}}");
|
||||
}
|
||||
else {
|
||||
// Export as \stepcounter{name}{\thename}
|
||||
ldp.append(changeCounter(sName,sFormula,false))
|
||||
.append("{\\the")
|
||||
.append(seqnames.getExportName(sName))
|
||||
.append("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Create label for a sequence field (text:sequence tag)</p>
|
||||
* @param node The element containing the sequence field
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
*/
|
||||
public void handleSequenceLabel(Element node, LaTeXDocumentPortion ldp) {
|
||||
String sRefName = Misc.getAttribute(node,XMLString.TEXT_REF_NAME);
|
||||
if (sRefName!=null && ofr.hasSequenceRefTo(sRefName)) {
|
||||
ldp.append("\\label{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
}
|
||||
}
|
||||
|
||||
// According to the spec for OpenDocument, the formula is application
|
||||
// specific, prefixed with a namespace. OOo uses the namespace ooow, and
|
||||
// we accept the formulas ooow:<number>, ooow:<name>, ooow:<name>+<number>
|
||||
// and ooow:<name>-<number>
|
||||
// Note: In OOo a counter is a 16 bit unsigned integer, whereas a (La)TeX
|
||||
// counter can be negative - thus there will be a slight deviation in the
|
||||
// (rare) case of a negative number
|
||||
private String changeCounter(String sName, String sFormula, boolean bRef) {
|
||||
if (sFormula!=null) {
|
||||
sFormula = sFormula.trim();
|
||||
if (sFormula.startsWith("ooow:")) {
|
||||
SimpleInputBuffer input = new SimpleInputBuffer(sFormula.substring(5));
|
||||
if (input.peekChar()>='0' && input.peekChar()<='9') {
|
||||
// Value is <number>
|
||||
String sNumber = input.getInteger();
|
||||
if (input.atEnd()) {
|
||||
return setCounter(sName, Misc.getPosInteger(sNumber,0), bRef);
|
||||
}
|
||||
}
|
||||
else if (input.peekChar()=='-') {
|
||||
// Value is a negative <number>
|
||||
input.getChar();
|
||||
if (input.peekChar()>='0' && input.peekChar()<='9') {
|
||||
String sNumber = input.getInteger();
|
||||
if (input.atEnd()) {
|
||||
return setCounter(sName, -Misc.getPosInteger(sNumber,0), bRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Value starts with <name>
|
||||
String sToken = input.getIdentifier();
|
||||
if (sToken.equals(sName)) {
|
||||
input.skipSpaces();
|
||||
if (input.peekChar()=='+') {
|
||||
// Value is <name>+<number>
|
||||
input.getChar();
|
||||
input.skipSpaces();
|
||||
String sNumber = input.getInteger();
|
||||
if (input.atEnd()) {
|
||||
return addtoCounter(sName, Misc.getPosInteger(sNumber,0), bRef);
|
||||
}
|
||||
}
|
||||
else if (input.peekChar()=='-') {
|
||||
// Value is <name>-<number>
|
||||
input.getChar();
|
||||
input.skipSpaces();
|
||||
String sNumber = input.getInteger();
|
||||
if (input.atEnd()) {
|
||||
return addtoCounter(sName, -Misc.getPosInteger(sNumber,0), bRef);
|
||||
}
|
||||
}
|
||||
else if (input.atEnd()) {
|
||||
// Value is <name>
|
||||
return addtoCounter(sName, 0, bRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// No formula, or a formula we don't understand -> use default behavior
|
||||
return stepCounter(sName, bRef);
|
||||
}
|
||||
|
||||
private String stepCounter(String sName, boolean bRef) {
|
||||
if (bRef) {
|
||||
return "\\refstepcounter{" + seqnames.getExportName(sName) + "}";
|
||||
}
|
||||
else {
|
||||
return "\\stepcounter{" + seqnames.getExportName(sName) + "}";
|
||||
}
|
||||
}
|
||||
|
||||
private String addtoCounter(String sName, int nValue, boolean bRef) {
|
||||
if (nValue==1) {
|
||||
return stepCounter(sName, bRef);
|
||||
}
|
||||
else if (bRef) {
|
||||
return "\\addtocounter{" + seqnames.getExportName(sName) + "}"
|
||||
+ "{" + Integer.toString(nValue-1) + "}"
|
||||
+ "\\refstepcounter{" + seqnames.getExportName(sName) + "}";
|
||||
}
|
||||
else if (nValue!=0) {
|
||||
return "\\addtocounter{" + seqnames.getExportName(sName) + "}"
|
||||
+ "{" + Integer.toString(nValue) + "}";
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private String setCounter(String sName, int nValue, boolean bRef) {
|
||||
if (bRef) {
|
||||
return "\\setcounter{" + seqnames.getExportName(sName) + "}"
|
||||
+ "{" + Integer.toString(nValue-1) + "}"
|
||||
+ "\\refstepcounter{" + seqnames.getExportName(sName) + "}";
|
||||
}
|
||||
else {
|
||||
return "\\setcounter{" + seqnames.getExportName(sName) + "}"
|
||||
+ "{" + Integer.toString(nValue) + "}";
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a sequence reference (text:sequence-ref tag)</p>
|
||||
* @param node The element containing the sequence reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleSequenceRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sRefName = Misc.getAttribute(node,XMLString.TEXT_REF_NAME);
|
||||
String sFormat = Misc.getAttribute(node,XMLString.TEXT_REFERENCE_FORMAT);
|
||||
String sName = ofr.getSequenceFromRef(sRefName);
|
||||
if (sRefName!=null) {
|
||||
if (sFormat==null || "page".equals(sFormat)) {
|
||||
ldp.append("\\pageref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
}
|
||||
else if ("value".equals(sFormat)) {
|
||||
ldp.append("\\ref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
}
|
||||
else if ("category-and-value".equals(sFormat)) {
|
||||
// Export as Name~\\ref{refname}
|
||||
if (sName!=null) {
|
||||
if (ofr.isFigureSequenceName(sName)) {
|
||||
ldp.append("\\figurename~");
|
||||
}
|
||||
else if (ofr.isTableSequenceName(sName)) {
|
||||
ldp.append("\\tablename~");
|
||||
}
|
||||
else {
|
||||
ldp.append(sName).append("~");
|
||||
}
|
||||
}
|
||||
ldp.append("\\ref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
}
|
||||
else if ("chapter".equals(sFormat) && config.useOooref()) {
|
||||
ldp.append("\\chapterref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
bUsesOooref = true;
|
||||
}
|
||||
else if ("caption".equals(sFormat) && config.useTitleref() &&
|
||||
(ofr.isFigureSequenceName(sName) || ofr.isTableSequenceName(sName))) {
|
||||
ldp.append("\\titleref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
bUsesTitleref = true;
|
||||
}
|
||||
else if ("text".equals(sFormat) && config.useTitleref() &&
|
||||
(ofr.isFigureSequenceName(sName) || ofr.isTableSequenceName(sName))) {
|
||||
// This is a combination of "category-and-value" and "caption"
|
||||
// Export as \\figurename~\ref{refname}:~\titleref{refname}
|
||||
if (ofr.isFigureSequenceName(sName)) {
|
||||
ldp.append("\\figurename");
|
||||
}
|
||||
else if (ofr.isTableSequenceName(sName)) {
|
||||
ldp.append("\\tablename");
|
||||
}
|
||||
ldp.append("~\\ref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}:~\\titleref{")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
bUsesTitleref = true;
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traversePCDATA(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** <p>Process a reference mark (text:reference-mark tag)</p>
|
||||
* @param node The element containing the reference mark
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleReferenceMark(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (!oc.isInSection() && !oc.isInCaption() && !oc.isVerbatim()) {
|
||||
// Note: Always include \label here, even when it's not used
|
||||
String sName = node.getAttribute(XMLString.TEXT_NAME);
|
||||
if (sName!=null) {
|
||||
ldp.append("\\label{ref:"+refnames.getExportName(sName)+"}");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Reference marks should not appear within \section or \caption
|
||||
postponedReferenceMarks.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a reference (text:reference-ref tag)</p>
|
||||
* @param node The element containing the reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleReferenceRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sFormat = node.getAttribute(XMLString.TEXT_REFERENCE_FORMAT);
|
||||
String sName = node.getAttribute(XMLString.TEXT_REF_NAME);
|
||||
if (("page".equals(sFormat) || "".equals(sFormat)) && sName!=null) {
|
||||
ldp.append("\\pageref{ref:"+refnames.getExportName(sName)+"}");
|
||||
}
|
||||
else if ("chapter".equals(sFormat) && ofr.referenceMarkInHeading(sName)) {
|
||||
// This is safe if the reference mark is contained in a heading
|
||||
ldp.append("\\ref{ref:"+refnames.getExportName(sName)+"}");
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traversePCDATA(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a bookmark (text:bookmark tag)</p>
|
||||
* <p>A bookmark may be the target for either a hyperlink or a reference,
|
||||
* so this will generate a <code>\\hyperref</code> and/or a <code>\\label</code></p>
|
||||
* @param node The element containing the bookmark
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleBookmark(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (!oc.isInSection() && !oc.isInCaption() && !oc.isVerbatim()) {
|
||||
String sName = node.getAttribute(XMLString.TEXT_NAME);
|
||||
if (sName!=null) {
|
||||
// A bookmark may be used as a target for a hyperlink as well as
|
||||
// for a reference. We export whatever is actually used:
|
||||
addTarget(node,"",ldp);
|
||||
if (ofr.hasBookmarkRefTo(sName)) {
|
||||
ldp.append("\\label{bkm:"+bookmarknames.getExportName(sName)+"}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Bookmarks should not appear within \section or \caption
|
||||
postponedBookmarks.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a bookmark reference (text:bookmark-ref tag).</p>
|
||||
* @param node The element containing the bookmark reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleBookmarkRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sFormat = node.getAttribute(XMLString.TEXT_REFERENCE_FORMAT);
|
||||
String sName = node.getAttribute(XMLString.TEXT_REF_NAME);
|
||||
if (("page".equals(sFormat) || "".equals(sFormat)) && sName!=null) {
|
||||
ldp.append("\\pageref{bkm:"+bookmarknames.getExportName(sName)+"}");
|
||||
}
|
||||
else if ("chapter".equals(sFormat) && ofr.bookmarkInHeading(sName)) {
|
||||
// This is safe if the bookmark is contained in a heading
|
||||
ldp.append("\\ref{bkm:"+bookmarknames.getExportName(sName)+"}");
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traversePCDATA(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process pending reference marks and bookmarks (which may have been
|
||||
* postponed within sections, captions or verbatim text.</p>
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void flushReferenceMarks(LaTeXDocumentPortion ldp, Context oc) {
|
||||
// We may still be in a context with no reference marks
|
||||
if (!oc.isInSection() && !oc.isInCaption() && !oc.isVerbatim()) {
|
||||
// Type out all postponed reference marks
|
||||
int n = postponedReferenceMarks.size();
|
||||
for (int i=0; i<n; i++) {
|
||||
handleReferenceMark((Element) postponedReferenceMarks.get(i),ldp,oc);
|
||||
}
|
||||
postponedReferenceMarks.clear();
|
||||
// Type out all postponed bookmarks
|
||||
n = postponedBookmarks.size();
|
||||
for (int i=0; i<n; i++) {
|
||||
handleBookmark((Element) postponedBookmarks.get(i),ldp,oc);
|
||||
}
|
||||
postponedBookmarks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a hyperlink (text:a tag)</p>
|
||||
* @param node The element containing the hyperlink
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleAnchor(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sHref = node.getAttribute(XMLString.XLINK_HREF);
|
||||
if (sHref!=null) {
|
||||
if (sHref.startsWith("#")) {
|
||||
// TODO: hyperlinks to headings (?) and objects
|
||||
if (bUseHyperref) {
|
||||
ldp.append("\\hyperlink{")
|
||||
.append(targets.getExportName(Misc.urlDecode(sHref.substring(1))))
|
||||
.append("}{");
|
||||
// ignore text style (let hyperref.sty handle the decoration):
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,oc);
|
||||
ldp.append("}");
|
||||
}
|
||||
else { // user don't want to include hyperlinks
|
||||
palette.getInlineCv().handleTextSpan(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (bUseHyperref) {
|
||||
if (ofr.getTextContent(node).trim().equals(sHref)) {
|
||||
// The link text equals the url
|
||||
ldp.append("\\url{")
|
||||
.append(oc.isInFootnote() ? escapeHref(Misc.urlDecode(sHref)) : Misc.urlDecode(sHref))
|
||||
.append("}");
|
||||
}
|
||||
else {
|
||||
ldp.append("\\href{")
|
||||
.append(oc.isInFootnote() ? escapeHref(Misc.urlDecode(sHref)) : Misc.urlDecode(sHref))
|
||||
.append("}{");
|
||||
// ignore text style (let hyperref.sty handle the decoration):
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,oc);
|
||||
ldp.append("}");
|
||||
}
|
||||
}
|
||||
else { // user don't want to include hyperlinks
|
||||
palette.getInlineCv().handleTextSpan(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
palette.getInlineCv().handleTextSpan(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Add a <code>\\hypertarget</code></p>
|
||||
* @param node The element containing the name of the target
|
||||
* @param sSuffix A suffix to be added to the target,
|
||||
* e.g. "|table" for a reference to a table.
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
*/
|
||||
public void addTarget(Element node, String sSuffix, LaTeXDocumentPortion ldp) {
|
||||
// TODO: Remove this and use addTarget by name only
|
||||
String sName = node.getAttribute(XMLString.TEXT_NAME);
|
||||
if (sName == null) { sName = node.getAttribute(XMLString.TABLE_NAME); }
|
||||
if (sName == null || !bUseHyperref) { return; }
|
||||
if (!ofr.hasLinkTo(sName+sSuffix)) { return; }
|
||||
ldp.append("\\hypertarget{")
|
||||
.append(targets.getExportName(sName+sSuffix))
|
||||
.append("}{}");
|
||||
}
|
||||
|
||||
/** <p>Add a <code>\\hypertarget</code></p>
|
||||
* @param sName The name of the target
|
||||
* @param sSuffix A suffix to be added to the target,
|
||||
* e.g. "|table" for a reference to a table.
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
*/
|
||||
public void addTarget(String sName, String sSuffix, LaTeXDocumentPortion ldp) {
|
||||
if (sName!=null && bUseHyperref && ofr.hasLinkTo(sName+sSuffix)) {
|
||||
ldp.append("\\hypertarget{")
|
||||
.append(targets.getExportName(sName+sSuffix))
|
||||
.append("}{}");
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a page number field (text:page-number tag)</p>
|
||||
* @param node The element containing the page number field
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handlePageNumber(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// TODO: Obey attributes!
|
||||
ldp.append("\\thepage{}");
|
||||
}
|
||||
|
||||
/** <p>Process a page count field (text:page-count tag)</p>
|
||||
* @param node The element containing the page count field
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handlePageCount(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// TODO: Obey attributes!
|
||||
// Note: Actually LastPage refers to the page number of the last page, not the number of pages
|
||||
if (config.useLastpage()) {
|
||||
bUsesPageCount = true;
|
||||
ldp.append("\\pageref{LastPage}");
|
||||
}
|
||||
else {
|
||||
ldp.append("?");
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers:
|
||||
|
||||
private String createPdfMeta(String sName, String sValue) {
|
||||
if (sValue==null) { return ""; }
|
||||
// Replace commas with semicolons (the keyval package doesn't like commas):
|
||||
sValue = sValue.replace(',', ';');
|
||||
// Meta data is assumed to be in the default language:
|
||||
return ", "+sName+"="+palette.getI18n().convert(sValue,false,palette.getMainContext().getLang());
|
||||
}
|
||||
|
||||
// For href within footnote, we have to escape the #
|
||||
private String escapeHref(String s) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i=0; i<s.length(); i++) {
|
||||
if (s.charAt(i)=='#') { buf.append("\\#"); }
|
||||
else { buf.append(s.charAt(i)); }
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
357
source/java/writer2latex/latex/HeadingConverter.java
Normal file
357
source/java/writer2latex/latex/HeadingConverter.java
Normal file
|
@ -0,0 +1,357 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* HeadingConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
//import java.util.Hashtable;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.latex.util.HeadingMap;
|
||||
//import writer2latex.latex.util.StyleMap;
|
||||
|
||||
/* This class converts OpenDocument headings (<code>text:h</code>) and
|
||||
* paragraph styles/formatting into LaTeX
|
||||
* Export of formatting depends on the option "formatting":
|
||||
* <ul>
|
||||
* <li><code>ignore_all</code>
|
||||
* <li><code>ignore_most</code>
|
||||
* <li><code>convert_basic</code>
|
||||
* <li><code>convert_most</code>
|
||||
* <li><code>convert_all</code>
|
||||
* </ul>
|
||||
*/
|
||||
public class HeadingConverter extends ConverterHelper {
|
||||
private String[] sHeadingStyles = new String[11];
|
||||
|
||||
/** Constructs a new <code>HeadingConverter</code>.
|
||||
*/
|
||||
public HeadingConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
appendHeadingStyles(decl);
|
||||
}
|
||||
|
||||
/** Process a heading
|
||||
* @param node The text:h element node containing the heading
|
||||
* @param ldp The LaTeXDocumentPortion to add LaTeX code to
|
||||
* @param oc The current context
|
||||
*/
|
||||
public void handleHeading(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Get the level, the heading map and the style name
|
||||
int nLevel = ofr.isOpenDocument() ?
|
||||
Misc.getPosInteger(Misc.getAttribute(node, XMLString.TEXT_OUTLINE_LEVEL),1) :
|
||||
Misc.getPosInteger(Misc.getAttribute(node, XMLString.TEXT_LEVEL),1);
|
||||
HeadingMap hm = config.getHeadingMap();
|
||||
String sStyleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
|
||||
if (nLevel<=hm.getMaxLevel()) {
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getParStyle(sStyleName)));
|
||||
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInSection(true);
|
||||
// Footnotes with more than one paragraph are not allowed within
|
||||
// sections. To be safe, we disallow all footnotes
|
||||
ic.setNoFootnotes(true);
|
||||
|
||||
// Apply style
|
||||
BeforeAfter baHardPage = new BeforeAfter();
|
||||
BeforeAfter baHardChar = new BeforeAfter();
|
||||
applyHardHeadingStyle(nLevel, sStyleName,
|
||||
baHardPage, baHardChar, ic);
|
||||
|
||||
// Export the heading
|
||||
ldp.append(baHardPage.getBefore());
|
||||
ldp.append("\\"+hm.getName(nLevel));
|
||||
// If this heading contains formatting, add optional argument:
|
||||
if (baHardChar.getBefore().length()>0 || containsElements(node)) {
|
||||
ldp.append("[");
|
||||
palette.getInlineCv().traversePlainInlineText(node,ldp,ic);
|
||||
ldp.append("]");
|
||||
}
|
||||
ldp.append("{").append(baHardChar.getBefore());
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,ic);
|
||||
ldp.append(baHardChar.getAfter()).append("}").nl();
|
||||
ldp.append(baHardPage.getAfter());
|
||||
|
||||
// Include pending index marks, labels, footnotes & floating frames
|
||||
palette.getFieldCv().flushReferenceMarks(ldp,oc);
|
||||
palette.getIndexCv().flushIndexMarks(ldp,oc);
|
||||
palette.getNoteCv().flushFootnotes(ldp,oc);
|
||||
palette.getDrawCv().flushFloatingFrames(ldp,ic);
|
||||
|
||||
// Pop the font name
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
else { // beyond supported headings - export as ordinary paragraph
|
||||
palette.getParCv().handleParagraph(node,ldp,oc,false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Use a paragraph style on a heading. If hard paragraph formatting
|
||||
* is applied to a heading, page break and font is converted - other
|
||||
* hard formatting is ignored.
|
||||
* This method also collects name of heading style
|
||||
* @param <code>nLevel</code> The level of this heading
|
||||
* @param <code>sStyleName</code> the name of the paragraph style to use
|
||||
* @param <code>baPage</code> a <code>BeforeAfter</code> to put page break code into
|
||||
* @param <code>baText</code> a <code>BeforeAfter</code> to put character formatting code into
|
||||
* @param <code>context</code> the current context. This method will use and update the formatting context
|
||||
*/
|
||||
private void applyHardHeadingStyle(int nLevel, String sStyleName,
|
||||
BeforeAfter baPage, BeforeAfter baText, Context context) {
|
||||
|
||||
// Get the style
|
||||
StyleWithProperties style = ofr.getParStyle(sStyleName);
|
||||
if (style==null) { return; }
|
||||
|
||||
// Register heading style
|
||||
if (sHeadingStyles[nLevel]==null) {
|
||||
sHeadingStyles[nLevel] = style.isAutomatic() ? style.getParentName() : sStyleName;
|
||||
}
|
||||
|
||||
// Do conversion
|
||||
if (style.isAutomatic()) {
|
||||
palette.getPageSc().applyPageBreak(style,false,baPage);
|
||||
palette.getCharSc().applyHardCharFormatting(style,baText);
|
||||
}
|
||||
|
||||
// Update context
|
||||
context.updateFormattingFromStyle(style);
|
||||
}
|
||||
|
||||
|
||||
/** Convert heading styles and outline numbering to LaTeX.
|
||||
* An array of stylenames to use is required: The OOo writer file format
|
||||
* allows different paragraph styles to be applied to individual headings,
|
||||
* so this is not included in the styles.
|
||||
* LaTeX (and OOo Writer!) usually uses the same format for all headings.
|
||||
* @param ldp the LaTeXDocumentPortion to add definitions to.
|
||||
*/
|
||||
// TODO: use method from ListStyleConverter to create labels
|
||||
private void appendHeadingStyles(LaTeXDocumentPortion ldp) {
|
||||
// The user may not want to convert the formatting of headings
|
||||
if (config.formatting()<=LaTeXConfig.IGNORE_MOST) { return; }
|
||||
|
||||
HeadingMap hm = config.getHeadingMap();
|
||||
|
||||
// OK, we are going to convert. First find the max level for headings
|
||||
int nMaxLevel = 0;
|
||||
for (int i=1; i<=5; i++) { if (sHeadingStyles[i]!=null) { nMaxLevel=i; } }
|
||||
if (nMaxLevel==0) { return; } // no headings, nothing to do!
|
||||
if (nMaxLevel>hm.getMaxLevel()) { nMaxLevel = hm.getMaxLevel(); }
|
||||
|
||||
boolean bOnlyNum = config.formatting()==LaTeXConfig.CONVERT_BASIC;
|
||||
if (bOnlyNum) {
|
||||
ldp.append("% Outline numbering").nl();
|
||||
}
|
||||
else {
|
||||
ldp.append("% Headings and outline numbering").nl()
|
||||
.append("\\makeatletter").nl();
|
||||
}
|
||||
|
||||
// Paragraph style for headings:
|
||||
if (!bOnlyNum) {
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
if (sHeadingStyles[i]!=null) {
|
||||
StyleWithProperties style = ofr.getParStyle(sHeadingStyles[i]);
|
||||
if (style!=null) {
|
||||
BeforeAfter decl = new BeforeAfter();
|
||||
BeforeAfter comm = new BeforeAfter();
|
||||
|
||||
palette.getPageSc().applyPageBreak(style,true,decl);
|
||||
|
||||
palette.getCharSc().applyNormalFont(decl);
|
||||
palette.getCharSc().applyFont(style,true,true,decl,new Context());
|
||||
palette.getParCv().applyAlignment(style,false,true,decl);
|
||||
|
||||
palette.getI18n().applyLanguage(style,false,true,comm);
|
||||
palette.getCharSc().applyFontEffects(style,true,comm);
|
||||
|
||||
String sMarginTop = style.getAbsoluteLength(XMLString.FO_MARGIN_TOP);
|
||||
String sMarginBottom = style.getAbsoluteLength(XMLString.FO_MARGIN_BOTTOM);
|
||||
String sMarginLeft = style.getAbsoluteLength(XMLString.FO_MARGIN_LEFT);
|
||||
|
||||
String sSecName = hm.getName(i);
|
||||
if (!comm.isEmpty()) { // have to create a cs for this heading
|
||||
ldp.append("\\newcommand\\cs").append(sSecName).append("[1]{")
|
||||
.append(comm.getBefore()).append("#1").append(comm.getAfter())
|
||||
.append("}").nl();
|
||||
}
|
||||
ldp.append("\\renewcommand\\").append(sSecName)
|
||||
.append("{\\@startsection{").append(sSecName).append("}{"+hm.getLevel(i))
|
||||
.append("}{"+sMarginLeft+"}{");
|
||||
// Suppress indentation after heading? currently not..
|
||||
// ldp.append("-");
|
||||
ldp.append(sMarginTop)
|
||||
.append("}{").append(sMarginBottom).append("}{");
|
||||
// Note: decl.getAfter() may include a page break after, which we ignore
|
||||
ldp.append(decl.getBefore());
|
||||
if (!comm.isEmpty()) {
|
||||
ldp.append("\\cs").append(sSecName);
|
||||
}
|
||||
ldp.append("}}").nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// redefine formatting of section counters
|
||||
// simplified if the user wants to ignore formatting
|
||||
if (!bOnlyNum) {
|
||||
ldp.append("\\renewcommand\\@seccntformat[1]{")
|
||||
.append("\\csname @textstyle#1\\endcsname{\\csname the#1\\endcsname}")
|
||||
.append("\\csname @distance#1\\endcsname}").nl();
|
||||
}
|
||||
|
||||
// Collect numbering styles and set secnumdepth
|
||||
int nSecnumdepth = nMaxLevel;
|
||||
ListStyle outline = ofr.getOutlineStyle();
|
||||
String[] sNumFormat = new String[6];
|
||||
for (int i=nMaxLevel; i>=1; i--) {
|
||||
sNumFormat[i] = ListStyleConverter.numFormat(outline.getLevelProperty(i,
|
||||
XMLString.STYLE_NUM_FORMAT));
|
||||
if (sNumFormat[i]==null || "".equals(sNumFormat[i])) {
|
||||
nSecnumdepth = i-1;
|
||||
}
|
||||
}
|
||||
ldp.append("\\setcounter{secnumdepth}{"+nSecnumdepth+"}").nl();
|
||||
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
if (sNumFormat[i]==null || "".equals(sNumFormat[i])) {
|
||||
// no numbering at this level
|
||||
if (!bOnlyNum) {
|
||||
ldp.append("\\newcommand\\@distance")
|
||||
.append(hm.getName(i)).append("{}").nl()
|
||||
.append("\\newcommand\\@textstyle")
|
||||
.append(hm.getName(i)).append("[1]{#1}").nl();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!bOnlyNum) {
|
||||
// Distance between label and text:
|
||||
String sDistance = outline.getLevelStyleProperty(i,XMLString.TEXT_MIN_LABEL_DISTANCE);
|
||||
ldp.append("\\newcommand\\@distance")
|
||||
.append(hm.getName(i)).append("{");
|
||||
if (sDistance!=null) {
|
||||
ldp.append("\\hspace{").append(sDistance).append("}");
|
||||
}
|
||||
ldp.append("}").nl();
|
||||
// Label width and alignment
|
||||
String sLabelWidth = outline.getLevelStyleProperty(i,XMLString.TEXT_MIN_LABEL_WIDTH);
|
||||
String sTextAlign = outline.getLevelStyleProperty(i,XMLString.FO_TEXT_ALIGN);
|
||||
String sAlignmentChar = "l"; // start (or left) is default
|
||||
if (sTextAlign!=null) {
|
||||
if ("end".equals(sTextAlign)) { sAlignmentChar="r"; }
|
||||
else if ("right".equals(sTextAlign)) { sAlignmentChar="r"; }
|
||||
else if ("center".equals(sTextAlign)) { sAlignmentChar="c"; }
|
||||
}
|
||||
// Textstyle to use for label:
|
||||
String sStyleName = outline.getLevelProperty(i,XMLString.TEXT_STYLE_NAME);
|
||||
// Prefix and suffix text to decorate the label
|
||||
String sPrefix = outline.getLevelProperty(i,XMLString.STYLE_NUM_PREFIX);
|
||||
String sSuffix = outline.getLevelProperty(i,XMLString.STYLE_NUM_SUFFIX);
|
||||
// TODO is this correct?? todo: space-before??? start value???
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
if (!bOnlyNum) {palette.getCharSc().applyTextStyle(sStyleName,baText,new Context()); }
|
||||
ldp.append("\\newcommand\\@textstyle")
|
||||
.append(hm.getName(i)).append("[1]{");
|
||||
if (!bOnlyNum && sLabelWidth!=null) {
|
||||
ldp.append("\\makebox[").append(sLabelWidth).append("][").append(sAlignmentChar).append("]{");
|
||||
}
|
||||
ldp.append(baText.getBefore())
|
||||
.append(sPrefix!=null ? sPrefix : "")
|
||||
.append("#1")
|
||||
.append(sSuffix!=null ? sSuffix : "")
|
||||
.append(baText.getAfter());
|
||||
if (!bOnlyNum && sLabelWidth!=null) {
|
||||
ldp.append("}");
|
||||
}
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
|
||||
// The label:
|
||||
int nLevels = Misc.getPosInteger(outline.getLevelProperty(i,
|
||||
XMLString.TEXT_DISPLAY_LEVELS),1);
|
||||
ldp.append("\\renewcommand\\the")
|
||||
.append(hm.getName(i))
|
||||
.append("{");
|
||||
for (int j=i-nLevels+1; j<i; j++) {
|
||||
ldp.append(sNumFormat[j])
|
||||
.append("{").append(sectionName(j)).append("}")
|
||||
.append(".");
|
||||
}
|
||||
ldp.append(sNumFormat[i])
|
||||
.append("{").append(hm.getName(i)).append("}")
|
||||
.append("}").nl();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!bOnlyNum) {
|
||||
ldp.append("\\makeatother").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if this node contains any element nodes, except reference marks */
|
||||
public boolean containsElements(Node node) {
|
||||
if (!node.hasChildNodes()) { return false; }
|
||||
NodeList list = node.getChildNodes();
|
||||
int nLen = list.getLength();
|
||||
for (int i = 0; i < nLen; i++) {
|
||||
Node child = list.item(i);
|
||||
if (child.getNodeType()==Node.ELEMENT_NODE &&
|
||||
!child.getNodeName().startsWith(XMLString.TEXT_REFERENCE_MARK)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static final String sectionName(int nLevel){
|
||||
switch (nLevel) {
|
||||
case 1: return "section";
|
||||
case 2: return "subsection";
|
||||
case 3: return "subsubsection";
|
||||
case 4: return "paragraph";
|
||||
case 5: return "subparagraph";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
242
source/java/writer2latex/latex/IndexConverter.java
Normal file
242
source/java/writer2latex/latex/IndexConverter.java
Normal file
|
@ -0,0 +1,242 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* IndexConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
//import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
import writer2latex.office.IndexMark;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.XMLString;
|
||||
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/**
|
||||
* <p>This class handles indexes (table of contents, list of tables, list of
|
||||
* illustrations, object index, user index, alphabetical index)
|
||||
* as well as their associated index marks.</p>
|
||||
*/
|
||||
public class IndexConverter extends ConverterHelper {
|
||||
|
||||
private boolean bContainsAlphabeticalIndex = false;
|
||||
|
||||
private Vector postponedIndexMarks = new Vector();
|
||||
|
||||
/** <p>Construct a new <code>IndexConverter</code>.
|
||||
* @param config the configuration to use
|
||||
* @param palette the <code>ConverterPalette</code> to link to
|
||||
* if such a document is created by the <code>IndexConverter</code>
|
||||
*/
|
||||
public IndexConverter(OfficeReader ofr,LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
/** <p>Append declarations needed by the <code>IndexConverter</code> to
|
||||
* the preamble.
|
||||
* @param pack the <code>LaTeXDocumentPortion</code> to which
|
||||
* declarations of packages should be added (<code>\\usepackage</code>).
|
||||
* @param decl the <code>LaTeXDocumentPortion</code> to which
|
||||
* other declarations should be added.
|
||||
*/
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bContainsAlphabeticalIndex) {
|
||||
pack.append("\\usepackage{makeidx}").nl();
|
||||
decl.append("\\makeindex").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/** Process Table of Contents (text:table-of-content tag)
|
||||
* @param node The element containing the Table of Contents
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleTOC (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
/* TODO: Apply more formatting by modfification of \l@section etc.
|
||||
Something like this:
|
||||
\newcommand\l@section[2]{\@dottedtocline{1}{1.5em}{2.3em}{\textbf{#1}}{\textit{#2}}
|
||||
Textformatting is trivial; see article.cls for examples of more complicated
|
||||
formatting. Note: The section number can't be formatted indivdually.*/
|
||||
|
||||
Element source = Misc.getChildByTagName(node,XMLString.TEXT_TABLE_OF_CONTENT_SOURCE);
|
||||
if (source!=null) {
|
||||
if ("chapter".equals(source.getAttribute(XMLString.TEXT_INDEX_SOURCE))) {
|
||||
ldp.append("[Warning: Table of content (for this chapter) ignored!]").nl().nl();
|
||||
}
|
||||
else {
|
||||
int nLevel = Misc.getPosInteger(source.getAttribute(XMLString.TEXT_OUTLINE_LEVEL),1);
|
||||
ldp.append("\\setcounter{tocdepth}{"+nLevel+"}").nl();
|
||||
Element title = Misc.getChildByTagName(source,XMLString.TEXT_INDEX_TITLE_TEMPLATE);
|
||||
if (title!=null) {
|
||||
ldp.append("\\renewcommand\\contentsname{");
|
||||
palette.getInlineCv().traversePCDATA(title,ldp,oc);
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
ldp.append("\\tableofcontents").nl();
|
||||
}
|
||||
|
||||
/** Process List of Illustrations (text:list-of-illustrations tag)
|
||||
* @param node The element containing the List of Illustrations
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleLOF (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
ldp.append("\\listoffigures").nl();
|
||||
}
|
||||
|
||||
/** Process List of Tables (text:list-of-tables tag)
|
||||
* @param node The element containing the List of Tables
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleLOT (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
ldp.append("\\listoftables").nl();
|
||||
}
|
||||
|
||||
/** Process Object Index (text:object index tag)
|
||||
* @param node The element containing the Object Index
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleObjectIndex (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
ldp.append("[Warning: Object index ignored]").nl().nl();
|
||||
}
|
||||
|
||||
/** Process User Index (text:user-index tag)
|
||||
* @param node The element containing the User Index
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleUserIndex (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
ldp.append("[Warning: User index ignored]").nl().nl();
|
||||
}
|
||||
|
||||
|
||||
/** Process Alphabetical Index (text:alphabetical-index tag)
|
||||
* @param node The element containing the Alphabetical Index
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleAlphabeticalIndex (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
ldp.append("\\printindex").nl();
|
||||
bContainsAlphabeticalIndex = true;
|
||||
}
|
||||
|
||||
|
||||
/** Process an Alphabetical Index Mark (text:alphabetical-index-mark{-start} tag)
|
||||
* @param node The element containing the Mark
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleAlphabeticalIndexMark(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (!oc.isInSection() && !oc.isInCaption() && !oc.isVerbatim()) {
|
||||
String sValue = IndexMark.getIndexValue(node);
|
||||
if (sValue!=null) {
|
||||
ldp.append("\\index{");
|
||||
String sKey1 = IndexMark.getKey1(node);
|
||||
if (sKey1!=null) {
|
||||
writeIndexText(sKey1.trim(),ldp,oc);
|
||||
ldp.append("!");
|
||||
}
|
||||
String sKey2 = IndexMark.getKey2(node);
|
||||
if (sKey2!=null) {
|
||||
writeIndexText(sKey2.trim(),ldp,oc);
|
||||
ldp.append("!");
|
||||
}
|
||||
writeIndexText(sValue.trim(),ldp,oc);
|
||||
ldp.append("}");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Index marks should not appear within \section or \caption
|
||||
postponedIndexMarks.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
public void flushIndexMarks(LaTeXDocumentPortion ldp, Context oc) {
|
||||
// We may still be in a context with no index marks
|
||||
if (!oc.isInSection() && !oc.isInCaption() && !oc.isVerbatim()) {
|
||||
// Type out all postponed index marks
|
||||
int n = postponedIndexMarks.size();
|
||||
for (int i=0; i<n; i++) {
|
||||
handleAlphabeticalIndexMark((Element) postponedIndexMarks.get(i),ldp,oc);
|
||||
}
|
||||
postponedIndexMarks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Helper: Write the text of an index mark, escaping special characters
|
||||
private void writeIndexText(String sText, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sTextOut = palette.getI18n().convert(sText,false,oc.getLang());
|
||||
// need to escape !, @, | and ":
|
||||
int nLen = sTextOut.length();
|
||||
boolean bBackslash = false;
|
||||
for (int i=0; i<nLen; i++) {
|
||||
if (bBackslash) {
|
||||
ldp.append(sTextOut.substring(i,i+1));
|
||||
bBackslash = false;
|
||||
}
|
||||
else {
|
||||
switch (sTextOut.charAt(i)) {
|
||||
case '\\' : bBackslash = true;
|
||||
ldp.append("\\");
|
||||
break;
|
||||
case '~' :
|
||||
case '\u00A0' :
|
||||
// Non-breaking space causes trouble in index:
|
||||
ldp.append(" ");
|
||||
break;
|
||||
case '!' :
|
||||
case '@' :
|
||||
case '|' :
|
||||
case '"' : ldp.append("\"");
|
||||
default : ldp.append(sTextOut.substring(i,i+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
636
source/java/writer2latex/latex/InlineConverter.java
Normal file
636
source/java/writer2latex/latex/InlineConverter.java
Normal file
|
@ -0,0 +1,636 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* InlineConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.latex.util.HeadingMap;
|
||||
|
||||
/**
|
||||
* <p>This class handles basic inline text.</p>
|
||||
*/
|
||||
public class InlineConverter extends ConverterHelper {
|
||||
|
||||
private String sTabstop = "\\ \\ ";
|
||||
private boolean bHasPdfannotation = false;
|
||||
|
||||
public InlineConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
// Get custom code for tab stops
|
||||
if (config.getTabstop().length()>0) {
|
||||
sTabstop = config.getTabstop();
|
||||
}
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bHasPdfannotation) {
|
||||
decl.append("\\newcommand\\pdfannotation[1]")
|
||||
.append("{\\ifx\\pdfoutput\\undefined\\marginpar{#1}\\else")
|
||||
.append("\\pdfstringdef\\tempstring{#1}\\marginpar{")
|
||||
.append("\\pdfannot width 5cm height 12pt depth 4cm ")
|
||||
.append("{ /Subtype /Text /Open false /Contents(\\tempstring) /Color [1 0 0]}")
|
||||
.append("}\\fi}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/** Handle a text:span element
|
||||
*/
|
||||
public void handleTextSpan(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (oc.isMathMode()) { handleTextSpanMath(node, ldp, oc); }
|
||||
else { handleTextSpanText(node, ldp, oc); }
|
||||
}
|
||||
|
||||
private void handleTextSpanMath(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// TODO: Handle a selection of formatting attributes: color, supscript...
|
||||
String sStyleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
StyleWithProperties style = ofr.getTextStyle(sStyleName);
|
||||
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(style));
|
||||
|
||||
// Convert formatting
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
if (style!=null) {
|
||||
String sPos = style.getProperty(XMLString.STYLE_TEXT_POSITION, true);
|
||||
if (sPos!=null) {
|
||||
if (sPos.startsWith("sub") || sPos.startsWith("-")) {
|
||||
ba.add("_{", "}");
|
||||
}
|
||||
else if (sPos.startsWith("super") || !sPos.startsWith("0%")) {
|
||||
ba.add("^{", "}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ldp.append(ba.getBefore());
|
||||
traverseInlineMath(node, ldp, oc);
|
||||
ldp.append(ba.getAfter());
|
||||
|
||||
// finally pop the font table
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
|
||||
private void handleTextSpanText(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String styleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
|
||||
// Check for strict handling of styles
|
||||
String sDisplayName = ofr.getTextStyles().getDisplayName(styleName);
|
||||
if (config.otherStyles()!=LaTeXConfig.ACCEPT && !config.getTextStyleMap().contains(sDisplayName)) {
|
||||
if (config.otherStyles()==LaTeXConfig.WARNING) {
|
||||
System.err.println("Warning: Text with style "+sDisplayName+" was ignored");
|
||||
}
|
||||
else if (config.otherStyles()==LaTeXConfig.ERROR) {
|
||||
ldp.append("% Error in source document: Text with style ")
|
||||
.append(palette.getI18n().convert(sDisplayName,false,oc.getLang()))
|
||||
.append(" was ignored").nl();
|
||||
}
|
||||
// Ignore this text:
|
||||
return;
|
||||
}
|
||||
|
||||
boolean styled = true;
|
||||
|
||||
// don't style it if a {foot|end}note is the only content
|
||||
if (onlyNote(node) || OfficeReader.getCharacterCount(node)==0) { styled = false; }
|
||||
|
||||
// Also don't style it if we're already within a verbatim environment
|
||||
if (oc.isVerbatim()) { styled = false; }
|
||||
|
||||
boolean bNoFootnotes = false;
|
||||
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getTextStyle(styleName)));
|
||||
|
||||
// Apply the style
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
Context ic = (Context) oc.clone();
|
||||
if (styled) { palette.getCharSc().applyTextStyle(styleName,ba,ic); }
|
||||
|
||||
// Footnote problems:
|
||||
// No footnotes in sub/superscript (will disappear)
|
||||
// No multiparagraph footnotes embedded in text command (eg. \textbf{..})
|
||||
// Simple solution: styled text element is forbidden footnote area
|
||||
if (styled && !ic.isInFootnote()) { bNoFootnotes = true; }
|
||||
|
||||
// Temp solution: Ignore hard formatting in header/footer (name clash problem)
|
||||
// only in package format.
|
||||
StyleWithProperties style = ofr.getTextStyle(styleName);
|
||||
if (ofr.isPackageFormat() && (style!=null && style.isAutomatic()) && ic.isInHeaderFooter()) {
|
||||
styled = false;
|
||||
}
|
||||
|
||||
if (styled) {
|
||||
if (bNoFootnotes) { ic.setNoFootnotes(true); }
|
||||
ldp.append(ba.getBefore());
|
||||
}
|
||||
|
||||
traverseInlineText(node,ldp,ic);
|
||||
|
||||
if (styled) {
|
||||
ldp.append(ba.getAfter());
|
||||
ic.setNoFootnotes(false);
|
||||
if (!ic.isInFootnote()) { palette.getNoteCv().flushFootnotes(ldp,oc); }
|
||||
}
|
||||
|
||||
// Flush any pending index marks and reference marks
|
||||
palette.getFieldCv().flushReferenceMarks(ldp,oc);
|
||||
palette.getIndexCv().flushIndexMarks(ldp,oc);
|
||||
|
||||
// finally pop the special table
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
|
||||
public void traverseInlineText(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (oc.isVerbatim()) {
|
||||
traverseVerbatimInlineText(node,ldp,oc);
|
||||
}
|
||||
else if (oc.isMathMode()) {
|
||||
traverseInlineMath(node,ldp,oc);
|
||||
}
|
||||
else {
|
||||
traverseOrdinaryInlineText(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
// Traverse ordinary inline text in text mode (temporarily changing to math
|
||||
// mode for a sequence of text:span with style "OOoLaTeX")
|
||||
private void traverseOrdinaryInlineText(Element node,LaTeXDocumentPortion ldp, Context oc) {
|
||||
Node childNode = node.getFirstChild();
|
||||
while (childNode!=null) {
|
||||
short nodeType = childNode.getNodeType();
|
||||
|
||||
switch (nodeType) {
|
||||
case Node.TEXT_NODE:
|
||||
String s = childNode.getNodeValue();
|
||||
if (s.length() > 0) {
|
||||
ldp.append(palette.getI18n().convert(s, false, oc.getLang()));
|
||||
}
|
||||
break;
|
||||
|
||||
case Node.ELEMENT_NODE:
|
||||
Element child = (Element)childNode;
|
||||
String sName = child.getTagName();
|
||||
if (sName.equals(XMLString.TEXT_SPAN)) {
|
||||
String sStyleName = child.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
boolean bIsMathSpan = "OOoLaTeX".equals(ofr.getTextStyles().getDisplayName(sStyleName));
|
||||
if (bIsMathSpan) {
|
||||
// Temporarily change to math mode
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setMathMode(true);
|
||||
|
||||
ldp.append("$");
|
||||
|
||||
Node remember;
|
||||
boolean bContinue = false;
|
||||
|
||||
do {
|
||||
handleTextSpanMath((Element)childNode, ldp, ic);
|
||||
remember = childNode;
|
||||
childNode = childNode.getNextSibling();
|
||||
bContinue = false;
|
||||
if (childNode!=null && childNode.getNodeType()==Node.ELEMENT_NODE &&
|
||||
childNode.getNodeName().equals(XMLString.TEXT_SPAN)) {
|
||||
sStyleName = Misc.getAttribute(childNode,XMLString.TEXT_STYLE_NAME);
|
||||
if ("OOoLaTeX".equals(ofr.getTextStyles().getDisplayName(sStyleName)))
|
||||
//child = (Element) childNode;
|
||||
bContinue = true;
|
||||
}
|
||||
} while(bContinue);
|
||||
childNode = remember;
|
||||
|
||||
ldp.append("$");
|
||||
}
|
||||
else {
|
||||
handleTextSpan(child,ldp,oc);
|
||||
}
|
||||
}
|
||||
else if (child.getNodeName().startsWith("draw:")) {
|
||||
palette.getDrawCv().handleDrawElement(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_S)) {
|
||||
if (config.ignoreDoubleSpaces()) {
|
||||
ldp.append(" ");
|
||||
}
|
||||
else {
|
||||
int count= Misc.getPosInteger(child.getAttribute(XMLString.TEXT_C),1);
|
||||
//String sSpace = config.ignoreDoubleSpaces() ? " " : "\\ ";
|
||||
for ( ; count > 0; count--) { ldp.append("\\ "); }
|
||||
}
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_TAB_STOP) || sName.equals(XMLString.TEXT_TAB)) { // text:tab in oasis
|
||||
// tab stops are not supported by the converter, but the special usage
|
||||
// of tab stops in header and footer can be emulated with \hfill
|
||||
// TODO: Sometimes extra \hfill should be added at end of line
|
||||
if (oc.isInHeaderFooter()) { ldp.append("\\hfill "); }
|
||||
else { ldp.append(sTabstop); }
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_LINE_BREAK)) {
|
||||
if (!oc.isInHeaderFooter() && !config.ignoreHardLineBreaks()) {
|
||||
ldp.append("\\newline").nl();
|
||||
}
|
||||
else { ldp.append(" "); }
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_A)) {
|
||||
palette.getFieldCv().handleAnchor(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.OFFICE_ANNOTATION)) {
|
||||
handleOfficeAnnotation(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_PAGE_NUMBER)) {
|
||||
palette.getFieldCv().handlePageNumber(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_PAGE_COUNT)) {
|
||||
palette.getFieldCv().handlePageCount(child,ldp,oc);
|
||||
}
|
||||
else if (oc.isInHeaderFooter()) {
|
||||
if (sName.equals(XMLString.TEXT_CHAPTER)) {
|
||||
handleChapterField(child,ldp,oc);
|
||||
}
|
||||
else if (sName.startsWith("text:")) {
|
||||
traverseInlineText(child,ldp,oc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// These tags are ignored in header and footer
|
||||
if (sName.equals(XMLString.TEXT_FOOTNOTE)) {
|
||||
palette.getNoteCv().handleFootnote(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ENDNOTE)) {
|
||||
palette.getNoteCv().handleEndnote(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_NOTE)) {
|
||||
if ("endnote".equals(child.getAttribute(XMLString.TEXT_NOTE_CLASS))) {
|
||||
palette.getNoteCv().handleEndnote(child,ldp,oc);
|
||||
}
|
||||
else {
|
||||
palette.getNoteCv().handleFootnote(child,ldp,oc);
|
||||
}
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_SEQUENCE)) {
|
||||
palette.getFieldCv().handleSequence(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_SEQUENCE_REF)) {
|
||||
palette.getFieldCv().handleSequenceRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_FOOTNOTE_REF)) {
|
||||
palette.getNoteCv().handleFootnoteRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ENDNOTE_REF)) {
|
||||
palette.getNoteCv().handleEndnoteRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_NOTE_REF)) { // oasis
|
||||
palette.getNoteCv().handleNoteRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_REFERENCE_MARK)) {
|
||||
palette.getFieldCv().handleReferenceMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_REFERENCE_MARK_START)) {
|
||||
palette.getFieldCv().handleReferenceMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_REFERENCE_REF)) {
|
||||
palette.getFieldCv().handleReferenceRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BOOKMARK)) {
|
||||
palette.getFieldCv().handleBookmark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BOOKMARK_START)) {
|
||||
palette.getFieldCv().handleBookmark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BOOKMARK_REF)) {
|
||||
palette.getFieldCv().handleBookmarkRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BIBLIOGRAPHY_MARK)) {
|
||||
palette.getBibCv().handleBibliographyMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ALPHABETICAL_INDEX_MARK)) {
|
||||
palette.getIndexCv().handleAlphabeticalIndexMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ALPHABETICAL_INDEX_MARK_START)) {
|
||||
palette.getIndexCv().handleAlphabeticalIndexMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.startsWith("text:")) {
|
||||
traverseInlineText(child,ldp,oc);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
childNode = childNode.getNextSibling();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* traverse inline text, ignoring any draw objects, footnotes, formatting and hyperlinks */
|
||||
public void traversePlainInlineText(Element node,LaTeXDocumentPortion ldp, Context oc) {
|
||||
String styleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getTextStyle(styleName)));
|
||||
|
||||
Node childNode = node.getFirstChild();
|
||||
while (childNode!=null) {
|
||||
short nodeType = childNode.getNodeType();
|
||||
|
||||
switch (nodeType) {
|
||||
case Node.TEXT_NODE:
|
||||
String s = childNode.getNodeValue();
|
||||
if (s.length() > 0) {
|
||||
// Need to protect ]
|
||||
for (int j=0; j<s.length(); j++) {
|
||||
if (s.charAt(j)!=']') {
|
||||
ldp.append(palette.getI18n().convert(Character.toString(s.charAt(j)),false,oc.getLang()));
|
||||
}
|
||||
else {
|
||||
ldp.append("{]}");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Node.ELEMENT_NODE:
|
||||
Element child = (Element)childNode;
|
||||
String sName = child.getTagName();
|
||||
if (sName.equals(XMLString.TEXT_SPAN)) {
|
||||
traversePlainInlineText(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_S)) {
|
||||
int count= Misc.getPosInteger(child.getAttribute(XMLString.TEXT_C),1);
|
||||
for ( ; count > 0; count--) {
|
||||
ldp.append("\\ ");
|
||||
}
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_TAB_STOP) || sName.equals(XMLString.TEXT_TAB)) { // text:tab in oasis
|
||||
// tab stops are not supported by the converter
|
||||
ldp.append(sTabstop);
|
||||
}
|
||||
else if (OfficeReader.isNoteElement(child)) {
|
||||
// ignore
|
||||
}
|
||||
else if (OfficeReader.isTextElement(child)) {
|
||||
traversePlainInlineText(child,ldp,oc);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
childNode = childNode.getNextSibling();
|
||||
}
|
||||
// finally pop the special table
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
|
||||
/* traverse inline math, ignoring any draw objects, footnotes, formatting and hyperlinks */
|
||||
public void traverseInlineMath(Element node,LaTeXDocumentPortion ldp, Context oc) {
|
||||
String styleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getTextStyle(styleName)));
|
||||
|
||||
Node childNode = node.getFirstChild();
|
||||
while (childNode!=null) {
|
||||
short nodeType = childNode.getNodeType();
|
||||
|
||||
switch (nodeType) {
|
||||
case Node.TEXT_NODE:
|
||||
String s = childNode.getNodeValue();
|
||||
ldp.append(palette.getI18n().convert(s,true,oc.getLang()));
|
||||
break;
|
||||
|
||||
case Node.ELEMENT_NODE:
|
||||
Element child = (Element)childNode;
|
||||
String sName = child.getTagName();
|
||||
if (sName.equals(XMLString.TEXT_S)) {
|
||||
int count= Misc.getPosInteger(child.getAttribute(XMLString.TEXT_C),1);
|
||||
for ( ; count > 0; count--) {
|
||||
ldp.append("\\ ");
|
||||
}
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_TAB_STOP) || sName.equals(XMLString.TEXT_TAB)) { // text:tab in oasis
|
||||
// tab stops are not supported by the converter
|
||||
ldp.append(" ");
|
||||
}
|
||||
else if (OfficeReader.isNoteElement(child)) {
|
||||
// ignore
|
||||
}
|
||||
else if (OfficeReader.isTextElement(child)) {
|
||||
traversePlainInlineText(child,ldp,oc);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
childNode = childNode.getNextSibling();
|
||||
}
|
||||
// finally pop the special table
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
|
||||
/* traverse verbatim inline text, ignoring any draw objects, footnotes, formatting and hyperlinks */
|
||||
private void traverseVerbatimInlineText(Element node,LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (node.hasChildNodes()) {
|
||||
|
||||
NodeList nList = node.getChildNodes();
|
||||
int len = nList.getLength();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
|
||||
Node childNode = nList.item(i);
|
||||
short nodeType = childNode.getNodeType();
|
||||
|
||||
switch (nodeType) {
|
||||
case Node.TEXT_NODE:
|
||||
String s = childNode.getNodeValue();
|
||||
if (s.length() > 0) {
|
||||
// text is copied verbatim! (Will be replaced by
|
||||
// question marks if outside inputenc)
|
||||
ldp.append(s);
|
||||
}
|
||||
break;
|
||||
|
||||
case Node.ELEMENT_NODE:
|
||||
Element child = (Element)childNode;
|
||||
String sName = child.getTagName();
|
||||
if (sName.equals(XMLString.TEXT_S)) {
|
||||
int count= Misc.getPosInteger(child.getAttribute(XMLString.TEXT_C),1);
|
||||
for ( ; count > 0; count--) {
|
||||
ldp.append(" ");
|
||||
}
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_TAB_STOP) || sName.equals(XMLString.TEXT_TAB)) { // text:tab in oasis
|
||||
// tab stops are not supported by the onverter
|
||||
ldp.append(sTabstop);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_LINE_BREAK)) {
|
||||
if (!oc.isNoLineBreaks()) { ldp.nl(); }
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_NOTE)) {
|
||||
// oasis; ignore
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_FOOTNOTE)) {
|
||||
// ignore
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ENDNOTE)) {
|
||||
// ignore
|
||||
}
|
||||
// The respective handlers know how to postpone these marks in verbatim context:
|
||||
else if (sName.equals(XMLString.TEXT_ALPHABETICAL_INDEX_MARK)) {
|
||||
palette.getIndexCv().handleAlphabeticalIndexMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ALPHABETICAL_INDEX_MARK_START)) {
|
||||
palette.getIndexCv().handleAlphabeticalIndexMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_REFERENCE_MARK)) {
|
||||
palette.getFieldCv().handleReferenceMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_REFERENCE_MARK_START)) {
|
||||
palette.getFieldCv().handleReferenceMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BOOKMARK)) {
|
||||
palette.getFieldCv().handleBookmark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BOOKMARK_START)) {
|
||||
palette.getFieldCv().handleBookmark(child,ldp,oc);
|
||||
}
|
||||
|
||||
else if (sName.startsWith("text:")) {
|
||||
traverseVerbatimInlineText(child,ldp,oc);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void traversePCDATA(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList nl = node.getChildNodes();
|
||||
int nLen = nl.getLength();
|
||||
for (int i=0; i<nLen; i++) {
|
||||
if (nl.item(i).getNodeType()==Node.TEXT_NODE) {
|
||||
ldp.append(palette.getI18n().convert(nl.item(i).getNodeValue(),false,oc.getLang()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleChapterField(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
HeadingMap hm = config.getHeadingMap();
|
||||
int nLevel = Misc.getPosInteger(node.getAttribute(XMLString.TEXT_OUTLINE_LEVEL),1);
|
||||
if (nLevel<=hm.getMaxLevel()) {
|
||||
int nLaTeXLevel = hm.getLevel(nLevel);
|
||||
if (nLaTeXLevel==1) {
|
||||
palette.getPageSc().setChapterField1(node.getAttribute(XMLString.TEXT_DISPLAY));
|
||||
ldp.append("{\\leftmark}");
|
||||
}
|
||||
else if (nLaTeXLevel==2) {
|
||||
palette.getPageSc().setChapterField2(node.getAttribute(XMLString.TEXT_DISPLAY));
|
||||
ldp.append("{\\rightmark}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Annotations
|
||||
|
||||
private void handleOfficeAnnotation(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sCommand = null;
|
||||
switch (config.notes()) {
|
||||
case LaTeXConfig.IGNORE: return;
|
||||
case LaTeXConfig.COMMENT:
|
||||
// Get the unformatted text of all paragraphs and insert each paragraph as a single comment
|
||||
ldp.append("%").nl();
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (Misc.isElement(child, XMLString.TEXT_P)) {
|
||||
ldp.append("%");
|
||||
traversePlainInlineText((Element)child, ldp, oc);
|
||||
ldp.nl();
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
return;
|
||||
case LaTeXConfig.PDFANNOTATION:
|
||||
bHasPdfannotation = true;
|
||||
sCommand = "\\pdfannotation";
|
||||
break;
|
||||
case LaTeXConfig.MARGINPAR:
|
||||
sCommand = "\\marginpar";
|
||||
break;
|
||||
case LaTeXConfig.CUSTOM:
|
||||
sCommand = config.getNotesCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the unformatted text of all paragraphs, separated by spaces
|
||||
ldp.append(sCommand).append("{");
|
||||
boolean bFirst = true;
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (Misc.isElement(child, XMLString.TEXT_P)) {
|
||||
if (!bFirst) ldp.append(" ");
|
||||
traversePlainInlineText((Element)child, ldp, oc);
|
||||
bFirst = false;
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
|
||||
}
|
||||
ldp.append("}");
|
||||
}
|
||||
|
||||
/* Check to see if this node has a footnote or endnote as the only subnode */
|
||||
private boolean onlyNote(Node node) {
|
||||
if (!node.hasChildNodes()) { return false; }
|
||||
NodeList nList = node.getChildNodes();
|
||||
int nLen = nList.getLength();
|
||||
|
||||
for (int i = 0; i < nLen; i++) {
|
||||
|
||||
Node child = nList.item(i);
|
||||
short nType = child.getNodeType();
|
||||
|
||||
switch (nType) {
|
||||
case Node.TEXT_NODE: return false;
|
||||
case Node.ELEMENT_NODE:
|
||||
if (!OfficeReader.isNoteElement(child)) { return false; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
543
source/java/writer2latex/latex/LaTeXConfig.java
Normal file
543
source/java/writer2latex/latex/LaTeXConfig.java
Normal file
|
@ -0,0 +1,543 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* LaTeXConfig.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import writer2latex.base.BooleanOption;
|
||||
import writer2latex.base.IntegerOption;
|
||||
import writer2latex.base.Option;
|
||||
import writer2latex.latex.util.HeadingMap;
|
||||
import writer2latex.latex.i18n.ClassicI18n;
|
||||
import writer2latex.latex.i18n.ReplacementTrie;
|
||||
import writer2latex.latex.util.StyleMap;
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
public class LaTeXConfig extends writer2latex.base.ConfigBase {
|
||||
protected int getOptionCount() { return 59; }
|
||||
protected String getDefaultConfigPath() { return "/writer2latex/latex/config/"; }
|
||||
|
||||
// Override setOption to be backwards compatible
|
||||
public void setOption(String sName,String sValue) {
|
||||
// this option has been renamed:
|
||||
if (sName.equals("keep_image_size")) { sName = "original_image_size"; }
|
||||
super.setOption(sName, sValue);
|
||||
}
|
||||
|
||||
// Backend
|
||||
public static final int GENERIC = 0;
|
||||
public static final int DVIPS = 1;
|
||||
public static final int PDFTEX = 2;
|
||||
public static final int UNSPECIFIED = 3;
|
||||
public static final int XETEX = 4;
|
||||
|
||||
// Formatting (must be ordered)
|
||||
public static final int IGNORE_ALL = 0;
|
||||
public static final int IGNORE_MOST = 1;
|
||||
public static final int CONVERT_BASIC = 2;
|
||||
public static final int CONVERT_MOST = 3;
|
||||
public static final int CONVERT_ALL = 4;
|
||||
// Page formatting
|
||||
public static final int CONVERT_HEADER_FOOTER = 5;
|
||||
// Handling of other formatting
|
||||
public static final int IGNORE = 0;
|
||||
public static final int ACCEPT = 1;
|
||||
public static final int WARNING = 2;
|
||||
public static final int ERROR = 3;
|
||||
|
||||
// Notes
|
||||
//public static final int IGNORE = 0;
|
||||
public static final int COMMENT = 1;
|
||||
public static final int PDFANNOTATION = 2;
|
||||
public static final int MARGINPAR = 3;
|
||||
public static final int CUSTOM = 4;
|
||||
|
||||
// Options
|
||||
protected int OPTION_COUNT = 59;
|
||||
|
||||
private static final int BACKEND = 0;
|
||||
private static final int NO_PREAMBLE = 1;
|
||||
private static final int NO_INDEX = 2;
|
||||
private static final int DOCUMENTCLASS = 3;
|
||||
private static final int GLOBAL_OPTIONS = 4;
|
||||
private static final int INPUTENCODING = 5;
|
||||
private static final int MULTILINGUAL = 6;
|
||||
private static final int GREEK_MATH = 7;
|
||||
private static final int USE_OOOMATH = 8;
|
||||
private static final int USE_PIFONT = 9;
|
||||
private static final int USE_IFSYM = 10;
|
||||
private static final int USE_WASYSYM = 11;
|
||||
private static final int USE_BBDING = 12;
|
||||
private static final int USE_EUROSYM = 13;
|
||||
private static final int USE_TIPA = 14;
|
||||
private static final int USE_COLOR = 15;
|
||||
private static final int USE_COLORTBL = 16;
|
||||
private static final int USE_GEOMETRY = 17;
|
||||
private static final int USE_FANCYHDR = 18;
|
||||
private static final int USE_HYPERREF = 19;
|
||||
private static final int USE_CAPTION = 20;
|
||||
private static final int USE_LONGTABLE = 21;
|
||||
private static final int USE_SUPERTABULAR = 22;
|
||||
private static final int USE_TABULARY = 23;
|
||||
private static final int USE_ENDNOTES = 24;
|
||||
private static final int USE_ULEM = 25;
|
||||
private static final int USE_LASTPAGE = 26;
|
||||
private static final int USE_TITLEREF = 27;
|
||||
private static final int USE_OOOREF = 28;
|
||||
private static final int USE_BIBTEX = 29;
|
||||
private static final int BIBTEX_STYLE = 30;
|
||||
private static final int EXTERNAL_BIBTEX_FILES = 31;
|
||||
private static final int FORMATTING = 32;
|
||||
private static final int PAGE_FORMATTING = 33;
|
||||
private static final int OTHER_STYLES = 34;
|
||||
private static final int IMAGE_CONTENT = 35;
|
||||
private static final int TABLE_CONTENT = 36;
|
||||
private static final int IGNORE_HARD_PAGE_BREAKS = 37;
|
||||
private static final int IGNORE_HARD_LINE_BREAKS = 38;
|
||||
private static final int IGNORE_EMPTY_PARAGRAPHS = 39;
|
||||
private static final int IGNORE_DOUBLE_SPACES = 40;
|
||||
private static final int ALIGN_FRAMES = 41;
|
||||
private static final int FLOAT_FIGURES = 42;
|
||||
private static final int FLOAT_TABLES = 43;
|
||||
private static final int FLOAT_OPTIONS = 44;
|
||||
private static final int FIGURE_SEQUENCE_NAME = 45;
|
||||
private static final int TABLE_SEQUENCE_NAME = 46;
|
||||
private static final int IMAGE_OPTIONS = 47;
|
||||
private static final int REMOVE_GRAPHICS_EXTENSION = 48;
|
||||
private static final int ORIGINAL_IMAGE_SIZE = 49;
|
||||
private static final int SIMPLE_TABLE_LIMIT = 50;
|
||||
private static final int NOTES = 51;
|
||||
private static final int METADATA = 52;
|
||||
private static final int TABSTOP = 53;
|
||||
private static final int WRAP_LINES_AFTER = 54;
|
||||
private static final int SPLIT_LINKED_SECTIONS = 55;
|
||||
private static final int SPLIT_TOPLEVEL_SECTIONS = 56;
|
||||
private static final int SAVE_IMAGES_IN_SUBDIR = 57;
|
||||
private static final int DEBUG = 58;
|
||||
|
||||
protected LinkedList customPreamble = new LinkedList();
|
||||
protected StyleMap par = new StyleMap();
|
||||
protected StyleMap parBlock = new StyleMap();
|
||||
protected StyleMap text = new StyleMap();
|
||||
protected StyleMap list = new StyleMap();
|
||||
protected StyleMap listItem = new StyleMap();
|
||||
protected StyleMap textAttr = new StyleMap();
|
||||
protected HeadingMap headingMap = new HeadingMap(5);
|
||||
protected Hashtable mathSymbols = new Hashtable();
|
||||
protected ReplacementTrie stringReplace = new ReplacementTrie();
|
||||
|
||||
public LaTeXConfig() {
|
||||
super();
|
||||
// create options with default values
|
||||
options[NO_PREAMBLE] = new BooleanOption("no_preamble","false");
|
||||
options[NO_INDEX] = new BooleanOption("no_index","false");
|
||||
options[DOCUMENTCLASS] = new Option("documentclass","article");
|
||||
options[GLOBAL_OPTIONS] = new Option("global_options","");
|
||||
options[BACKEND] = new IntegerOption("backend","pdftex") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
if ("generic".equals(sValue)) nValue = GENERIC;
|
||||
else if ("dvips".equals(sValue)) nValue = DVIPS;
|
||||
else if ("pdftex".equals(sValue)) nValue = PDFTEX;
|
||||
else if ("unspecified".equals(sValue)) nValue = UNSPECIFIED;
|
||||
else if ("xetex".equals(sValue)) nValue = XETEX;
|
||||
}
|
||||
};
|
||||
options[INPUTENCODING] = new IntegerOption("inputencoding",ClassicI18n.writeInputenc(ClassicI18n.ASCII)) {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
nValue = ClassicI18n.readInputenc(sValue);
|
||||
}
|
||||
};
|
||||
options[MULTILINGUAL] = new BooleanOption("multilingual","true");
|
||||
options[GREEK_MATH] = new BooleanOption("greek_math","true");
|
||||
options[USE_OOOMATH] = new BooleanOption("use_ooomath","false");
|
||||
options[USE_PIFONT] = new BooleanOption("use_pifont","false");
|
||||
options[USE_IFSYM] = new BooleanOption("use_ifsym","false");
|
||||
options[USE_WASYSYM] = new BooleanOption("use_wasysym","false");
|
||||
options[USE_BBDING] = new BooleanOption("use_bbding","false");
|
||||
options[USE_EUROSYM] = new BooleanOption("use_eurosym","false");
|
||||
options[USE_TIPA] = new BooleanOption("use_tipa","false");
|
||||
options[USE_COLOR] = new BooleanOption("use_color","true");
|
||||
options[USE_COLORTBL] = new BooleanOption("use_colortbl","false");
|
||||
options[USE_GEOMETRY] = new BooleanOption("use_geometry","false");
|
||||
options[USE_FANCYHDR] = new BooleanOption("use_fancyhdr","false");
|
||||
options[USE_HYPERREF] = new BooleanOption("use_hyperref","true");
|
||||
options[USE_CAPTION] = new BooleanOption("use_caption","false");
|
||||
options[USE_LONGTABLE] = new BooleanOption("use_longtable","false");
|
||||
options[USE_SUPERTABULAR] = new BooleanOption("use_supertabular","true");
|
||||
options[USE_TABULARY] = new BooleanOption("use_tabulary","false");
|
||||
options[USE_ENDNOTES] = new BooleanOption("use_endnotes","false");
|
||||
options[USE_ULEM] = new BooleanOption("use_ulem","false");
|
||||
options[USE_LASTPAGE] = new BooleanOption("use_lastpage","false");
|
||||
options[USE_TITLEREF] = new BooleanOption("use_titleref","false");
|
||||
options[USE_OOOREF] = new BooleanOption("use_oooref","false");
|
||||
options[USE_BIBTEX] = new BooleanOption("use_bibtex","false");
|
||||
options[BIBTEX_STYLE] = new Option("bibtex_style","plain");
|
||||
options[EXTERNAL_BIBTEX_FILES] = new Option("external_bibtex_files","");
|
||||
options[FORMATTING] = new IntegerOption("formatting","convert_basic") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
if ("convert_all".equals(sValue)) nValue = CONVERT_ALL;
|
||||
else if ("convert_most".equals(sValue)) nValue = CONVERT_MOST;
|
||||
else if ("convert_basic".equals(sValue)) nValue = CONVERT_BASIC;
|
||||
else if ("ignore_most".equals(sValue)) nValue = IGNORE_MOST;
|
||||
else if ("ignore_all".equals(sValue)) nValue = IGNORE_ALL;
|
||||
}
|
||||
};
|
||||
options[PAGE_FORMATTING] = new IntegerOption("page_formatting","convert_all") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
if ("convert_all".equals(sValue)) nValue = CONVERT_ALL;
|
||||
else if ("convert_header_footer".equals(sValue)) nValue = CONVERT_HEADER_FOOTER;
|
||||
else if ("ignore_all".equals(sValue)) nValue = IGNORE_ALL;
|
||||
}
|
||||
};
|
||||
options[OTHER_STYLES] = new ContentHandlingOption("other_styles","accept");
|
||||
options[IMAGE_CONTENT] = new ContentHandlingOption("image_content","accept");
|
||||
options[TABLE_CONTENT] = new ContentHandlingOption("table_content","accept");
|
||||
options[IGNORE_HARD_PAGE_BREAKS] = new BooleanOption("ignore_hard_page_breaks","false");
|
||||
options[IGNORE_HARD_LINE_BREAKS] = new BooleanOption("ignore_hard_line_breaks","false");
|
||||
options[IGNORE_EMPTY_PARAGRAPHS] = new BooleanOption("ignore_empty_paragraphs","false");
|
||||
options[IGNORE_DOUBLE_SPACES] = new BooleanOption("ignore_double_spaces","false");
|
||||
options[ALIGN_FRAMES] = new BooleanOption("align_frames","true");
|
||||
options[FLOAT_FIGURES] = new BooleanOption("float_figures","false");
|
||||
options[FLOAT_TABLES] = new BooleanOption("float_tables","false");
|
||||
options[FLOAT_OPTIONS] = new Option("float_options","h");
|
||||
options[FIGURE_SEQUENCE_NAME] = new BooleanOption("figure_sequence_name","");
|
||||
options[TABLE_SEQUENCE_NAME] = new BooleanOption("table_sequence_name","");
|
||||
options[IMAGE_OPTIONS] = new Option("image_options","");
|
||||
options[REMOVE_GRAPHICS_EXTENSION] = new BooleanOption("remove_graphics_extension","false");
|
||||
options[ORIGINAL_IMAGE_SIZE] = new BooleanOption("original_image_size","false");
|
||||
options[SIMPLE_TABLE_LIMIT] = new IntegerOption("simple_table_limit","0") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
nValue = Misc.getPosInteger(sValue,0);
|
||||
}
|
||||
};
|
||||
options[NOTES] = new IntegerOption("notes","comment") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
if ("ignore".equals(sValue)) nValue = IGNORE;
|
||||
else if ("comment".equals(sValue)) nValue = COMMENT;
|
||||
else if ("pdfannotation".equals(sValue)) nValue = PDFANNOTATION;
|
||||
else if ("marginpar".equals(sValue)) nValue = MARGINPAR;
|
||||
else nValue = CUSTOM;
|
||||
}
|
||||
};
|
||||
options[METADATA] = new BooleanOption("metadata","true");
|
||||
options[TABSTOP] = new Option("tabstop","");
|
||||
options[WRAP_LINES_AFTER] = new IntegerOption("wrap_lines_after","72") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
nValue = Misc.getPosInteger(sValue,0);
|
||||
}
|
||||
};
|
||||
options[SPLIT_LINKED_SECTIONS] = new BooleanOption("split_linked_sections","false");
|
||||
options[SPLIT_TOPLEVEL_SECTIONS] = new BooleanOption("split_toplevel_sections","false");
|
||||
options[SAVE_IMAGES_IN_SUBDIR] = new BooleanOption("save_images_in_subdir","false");
|
||||
options[DEBUG] = new BooleanOption("debug","false");
|
||||
// Headings for article class:
|
||||
headingMap.setLevelData(1,"section",1);
|
||||
headingMap.setLevelData(2,"subsection",2);
|
||||
headingMap.setLevelData(3,"subsubsection",3);
|
||||
headingMap.setLevelData(4,"paragraph",4);
|
||||
headingMap.setLevelData(5,"subparagraph",5);
|
||||
// Standard string replace:
|
||||
// Fix french spacing; replace nonbreaking space
|
||||
// right before em-dash, !, ?, : and ; (babel handles this)
|
||||
stringReplace.put("\u00A0\u2014"," \u2014",ClassicI18n.readFontencs("any"));
|
||||
stringReplace.put("\u00A0!"," !",ClassicI18n.readFontencs("any"));
|
||||
stringReplace.put("\u00A0?"," ?",ClassicI18n.readFontencs("any"));
|
||||
stringReplace.put("\u00A0:"," :",ClassicI18n.readFontencs("any"));
|
||||
stringReplace.put("\u00A0;"," ;",ClassicI18n.readFontencs("any"));
|
||||
// Right after opening guillemet and right before closing guillemet:
|
||||
// Here we must *keep* the non-breaking space
|
||||
// TODO: Use \og and \fg if the document contains french...
|
||||
//stringReplace.put("\u00AB\u00A0","\u00AB ",I18n.readFontencs("any"));
|
||||
//stringReplace.put("\u00A0\u00BB"," \u00BB",I18n.readFontencs("any"));
|
||||
}
|
||||
|
||||
protected void readInner(Element elm) {
|
||||
if (elm.getTagName().equals("style-map")) {
|
||||
String sName = elm.getAttribute("name");
|
||||
String sFamily = elm.getAttribute("family");
|
||||
if (sFamily.length()==0) { // try old name
|
||||
sFamily = elm.getAttribute("class");
|
||||
}
|
||||
String sBefore = elm.getAttribute("before");
|
||||
String sAfter = elm.getAttribute("after");
|
||||
boolean bLineBreak = !"false".equals(elm.getAttribute("line-break"));
|
||||
boolean bVerbatim = "true".equals(elm.getAttribute("verbatim"));
|
||||
if ("paragraph".equals(sFamily)) {
|
||||
par.put(sName,sBefore,sAfter,bLineBreak,bVerbatim);
|
||||
}
|
||||
if ("paragraph-block".equals(sFamily)) {
|
||||
String sNext = elm.getAttribute("next");
|
||||
parBlock.put(sName,sBefore,sAfter,sNext,bVerbatim);
|
||||
}
|
||||
else if ("text".equals(sFamily)) {
|
||||
text.put(sName,sBefore,sAfter,false,bVerbatim);
|
||||
}
|
||||
else if ("list".equals(sFamily)) {
|
||||
list.put(sName,sBefore,sAfter);
|
||||
}
|
||||
else if ("listitem".equals(sFamily)) {
|
||||
listItem.put(sName,sBefore,sAfter);
|
||||
}
|
||||
else if ("text-attribute".equals(sFamily)) {
|
||||
textAttr.put(sName, sBefore, sAfter);
|
||||
}
|
||||
}
|
||||
else if (elm.getTagName().equals("heading-map")) {
|
||||
readHeadingMap(elm);
|
||||
}
|
||||
else if (elm.getTagName().equals("string-replace")) {
|
||||
String sInput = elm.getAttribute("input");
|
||||
String sLaTeXCode = elm.getAttribute("latex-code");
|
||||
String sFontencs = elm.getAttribute("fontencs");
|
||||
int nFontencs = ClassicI18n.readFontencs(sFontencs.length()>0 ? sFontencs : "any");
|
||||
stringReplace.put(sInput,sLaTeXCode,nFontencs);
|
||||
}
|
||||
else if (elm.getTagName().equals("custom-preamble")) {
|
||||
Node child = elm.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (child.getNodeType()==Node.TEXT_NODE) {
|
||||
customPreamble.add(child.getNodeValue());
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
else if (elm.getTagName().equals("math-symbol-map")) {
|
||||
String sName = elm.getAttribute("name");
|
||||
String sLatex = elm.getAttribute("latex");
|
||||
mathSymbols.put(sName,sLatex);
|
||||
}
|
||||
}
|
||||
|
||||
public void readHeadingMap(Element node) {
|
||||
int nMaxLevel = Misc.getPosInteger(node.getAttribute("max-level"),0);
|
||||
headingMap.reset(nMaxLevel);
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (child.getNodeType()==Node.ELEMENT_NODE) {
|
||||
Element elm = (Element) child;
|
||||
if (elm.getTagName().equals("heading-level-map")) {
|
||||
int nWriterLevel = Misc.getPosInteger(elm.getAttribute("writer-level"),1);
|
||||
String sName = elm.getAttribute("name");
|
||||
int nLevel = Misc.getPosInteger(elm.getAttribute("level"),0);
|
||||
headingMap.setLevelData(nWriterLevel,sName,nLevel);
|
||||
}
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeInner(Document dom) {
|
||||
// Write math symbol map
|
||||
Enumeration msEnum = mathSymbols.keys();
|
||||
while (msEnum.hasMoreElements()) {
|
||||
String sName = (String) msEnum.nextElement();
|
||||
String sLatex = (String) mathSymbols.get(sName);
|
||||
Element msNode = dom.createElement("math-symbol-map");
|
||||
msNode.setAttribute("name",sName);
|
||||
msNode.setAttribute("latex",sLatex);
|
||||
dom.getDocumentElement().appendChild(msNode);
|
||||
}
|
||||
|
||||
writeStyleMap(dom,par,"paragraph");
|
||||
writeStyleMap(dom,parBlock,"paragraph-block");
|
||||
writeStyleMap(dom,text,"text");
|
||||
writeStyleMap(dom,list,"list");
|
||||
writeStyleMap(dom,listItem,"listitem");
|
||||
writeStyleMap(dom,textAttr,"text-attribute");
|
||||
|
||||
Element hmNode = dom.createElement("heading-map");
|
||||
hmNode.setAttribute("max-level",Integer.toString(headingMap.getMaxLevel()));
|
||||
dom.getDocumentElement().appendChild(hmNode);
|
||||
for (int i=1; i<=headingMap.getMaxLevel(); i++) {
|
||||
Element hlmNode = dom.createElement("heading-level-map");
|
||||
hlmNode.setAttribute("writer-level",Integer.toString(i));
|
||||
hlmNode.setAttribute("name",headingMap.getName(i));
|
||||
hlmNode.setAttribute("level",Integer.toString(headingMap.getLevel(i)));
|
||||
hmNode.appendChild(hlmNode);
|
||||
}
|
||||
|
||||
// TODO: Export string replacements
|
||||
//String[] sInputStrings = stringReplace.getInputStrings();
|
||||
/*
|
||||
int nSize = sInputStrings.size();
|
||||
for (int i=0; i<nSize; i++) {
|
||||
String sInput = sInputStrings[i];
|
||||
ReplacementTrieNode node = stringReplace.get(sInput);
|
||||
Element srNode = dom.createElement("string-replace");
|
||||
srNode.setAttribute("input",sInput);
|
||||
srNode.setAttribute("latex-code",node.getLaTeXCode());
|
||||
srNode.setAttribute("fontenc",I18n.writeFontencs(node.getFontencs()));
|
||||
hmNode.appendChild(srNode);
|
||||
}
|
||||
*/
|
||||
|
||||
writeContent(dom,customPreamble,"custom-preamble");
|
||||
|
||||
}
|
||||
|
||||
private void writeStyleMap(Document dom, StyleMap sm, String sFamily) {
|
||||
Enumeration smEnum = sm.getNames();
|
||||
while (smEnum.hasMoreElements()) {
|
||||
String sName = (String) smEnum.nextElement();
|
||||
Element smNode = dom.createElement("style-map");
|
||||
smNode.setAttribute("name",sName);
|
||||
smNode.setAttribute("family",sFamily);
|
||||
smNode.setAttribute("before",sm.getBefore(sName));
|
||||
smNode.setAttribute("after",sm.getAfter(sName));
|
||||
if (sm.getNext(sName)!=null) {
|
||||
smNode.setAttribute("next",sm.getNext(sName));
|
||||
}
|
||||
if (!sm.getLineBreak(sName)) {
|
||||
smNode.setAttribute("line-break","false");
|
||||
}
|
||||
if (sm.getVerbatim(sName)) {
|
||||
smNode.setAttribute("verbatim","true");
|
||||
}
|
||||
dom.getDocumentElement().appendChild(smNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeContent(Document dom, LinkedList list, String sElement) {
|
||||
Element node = dom.createElement(sElement);
|
||||
int nLen = list.size();
|
||||
for (int i=0; i<nLen; i++) {
|
||||
node.appendChild( dom.createTextNode( (String) list.get(i) ) );
|
||||
}
|
||||
dom.getDocumentElement().appendChild(node);
|
||||
}
|
||||
|
||||
// Convenience accessor methods
|
||||
|
||||
// String replace
|
||||
public ReplacementTrie getStringReplace() { return stringReplace; }
|
||||
|
||||
// Common options
|
||||
public boolean debug() { return ((BooleanOption) options[DEBUG]).getValue(); }
|
||||
|
||||
// General options
|
||||
public String getDocumentclass() { return options[DOCUMENTCLASS].getString(); }
|
||||
public String getGlobalOptions() { return options[GLOBAL_OPTIONS].getString(); }
|
||||
public int getBackend() { return ((IntegerOption) options[BACKEND]).getValue(); }
|
||||
public int getInputencoding() { return ((IntegerOption) options[INPUTENCODING]).getValue(); }
|
||||
public boolean multilingual() { return ((BooleanOption) options[MULTILINGUAL]).getValue(); }
|
||||
public boolean greekMath() { return ((BooleanOption) options[GREEK_MATH]).getValue(); }
|
||||
public boolean noPreamble() { return ((BooleanOption) options[NO_PREAMBLE]).getValue(); }
|
||||
public boolean noIndex() { return ((BooleanOption) options[NO_INDEX]).getValue(); }
|
||||
|
||||
// Package options
|
||||
public boolean useOoomath() { return ((BooleanOption) options[USE_OOOMATH]).getValue(); }
|
||||
public boolean usePifont() { return ((BooleanOption) options[USE_PIFONT]).getValue(); }
|
||||
public boolean useIfsym() { return ((BooleanOption) options[USE_IFSYM]).getValue(); }
|
||||
public boolean useWasysym() { return ((BooleanOption) options[USE_WASYSYM]).getValue(); }
|
||||
public boolean useBbding() { return ((BooleanOption) options[USE_BBDING]).getValue(); }
|
||||
public boolean useEurosym() { return ((BooleanOption) options[USE_EUROSYM]).getValue(); }
|
||||
public boolean useTipa() { return ((BooleanOption) options[USE_TIPA]).getValue(); }
|
||||
public boolean useColor() { return ((BooleanOption) options[USE_COLOR]).getValue(); }
|
||||
public boolean useColortbl() { return ((BooleanOption) options[USE_COLORTBL]).getValue(); }
|
||||
public boolean useGeometry() { return ((BooleanOption) options[USE_GEOMETRY]).getValue(); }
|
||||
public boolean useFancyhdr() { return ((BooleanOption) options[USE_FANCYHDR]).getValue(); }
|
||||
public boolean useHyperref() { return ((BooleanOption) options[USE_HYPERREF]).getValue(); }
|
||||
public boolean useCaption() { return ((BooleanOption) options[USE_CAPTION]).getValue(); }
|
||||
public boolean useLongtable() { return ((BooleanOption) options[USE_LONGTABLE]).getValue(); }
|
||||
public boolean useSupertabular() { return ((BooleanOption) options[USE_SUPERTABULAR]).getValue(); }
|
||||
public boolean useTabulary() { return ((BooleanOption) options[USE_TABULARY]).getValue(); }
|
||||
public boolean useEndnotes() { return ((BooleanOption) options[USE_ENDNOTES]).getValue(); }
|
||||
public boolean useUlem() { return ((BooleanOption) options[USE_ULEM]).getValue(); }
|
||||
public boolean useLastpage() { return ((BooleanOption) options[USE_LASTPAGE]).getValue(); }
|
||||
public boolean useTitleref() { return ((BooleanOption) options[USE_TITLEREF]).getValue(); }
|
||||
public boolean useOooref() { return ((BooleanOption) options[USE_OOOREF]).getValue(); }
|
||||
public boolean useBibtex() { return ((BooleanOption) options[USE_BIBTEX]).getValue(); }
|
||||
public String bibtexStyle() { return options[BIBTEX_STYLE].getString(); }
|
||||
public String externalBibtexFiles() { return options[EXTERNAL_BIBTEX_FILES].getString(); }
|
||||
|
||||
// Formatting options
|
||||
public int formatting() { return ((IntegerOption) options[FORMATTING]).getValue(); }
|
||||
public int pageFormatting() { return ((IntegerOption) options[PAGE_FORMATTING]).getValue(); }
|
||||
public int otherStyles() { return ((IntegerOption) options[OTHER_STYLES]).getValue(); }
|
||||
public int imageContent() { return ((IntegerOption) options[IMAGE_CONTENT]).getValue(); }
|
||||
public int tableContent() { return ((IntegerOption) options[TABLE_CONTENT]).getValue(); }
|
||||
public boolean ignoreHardPageBreaks() { return ((BooleanOption) options[IGNORE_HARD_PAGE_BREAKS]).getValue(); }
|
||||
public boolean ignoreHardLineBreaks() { return ((BooleanOption) options[IGNORE_HARD_LINE_BREAKS]).getValue(); }
|
||||
public boolean ignoreEmptyParagraphs() { return ((BooleanOption) options[IGNORE_EMPTY_PARAGRAPHS]).getValue(); }
|
||||
public boolean ignoreDoubleSpaces() { return ((BooleanOption) options[IGNORE_DOUBLE_SPACES]).getValue(); }
|
||||
|
||||
// Graphics options
|
||||
public boolean alignFrames() { return ((BooleanOption) options[ALIGN_FRAMES]).getValue(); }
|
||||
public boolean floatFigures() { return ((BooleanOption) options[FLOAT_FIGURES]).getValue(); }
|
||||
public boolean floatTables() { return ((BooleanOption) options[FLOAT_TABLES]).getValue(); }
|
||||
public String getFloatOptions() { return options[FLOAT_OPTIONS].getString(); }
|
||||
public String getFigureSequenceName() { return options[FIGURE_SEQUENCE_NAME].getString(); }
|
||||
public String getTableSequenceName() { return options[TABLE_SEQUENCE_NAME].getString(); }
|
||||
public String getImageOptions() { return options[IMAGE_OPTIONS].getString(); }
|
||||
public boolean removeGraphicsExtension() { return ((BooleanOption) options[REMOVE_GRAPHICS_EXTENSION]).getValue(); }
|
||||
public boolean originalImageSize() { return ((BooleanOption) options[ORIGINAL_IMAGE_SIZE]).getValue(); }
|
||||
|
||||
// Tables
|
||||
public int getSimpleTableLimit() { return ((IntegerOption) options[SIMPLE_TABLE_LIMIT]).getValue(); }
|
||||
|
||||
// Notes
|
||||
public int notes() { return ((IntegerOption) options[NOTES]).getValue(); }
|
||||
public String getNotesCommand() { return options[NOTES].getString(); }
|
||||
|
||||
// Metadata
|
||||
public boolean metadata() { return ((BooleanOption) options[METADATA]).getValue(); }
|
||||
|
||||
// Tab stops
|
||||
public String getTabstop() { return options[TABSTOP].getString(); }
|
||||
|
||||
// Files
|
||||
public int getWrapLinesAfter() { return ((IntegerOption) options[WRAP_LINES_AFTER]).getValue(); }
|
||||
public boolean splitLinkedSections() { return ((BooleanOption) options[SPLIT_LINKED_SECTIONS]).getValue(); }
|
||||
public boolean splitToplevelSections() { return ((BooleanOption) options[SPLIT_TOPLEVEL_SECTIONS]).getValue(); }
|
||||
public boolean saveImagesInSubdir() { return ((BooleanOption) options[SAVE_IMAGES_IN_SUBDIR]).getValue(); }
|
||||
|
||||
public Hashtable getMathSymbols() { return mathSymbols; }
|
||||
|
||||
public StyleMap getParStyleMap() { return par; }
|
||||
public StyleMap getParBlockStyleMap() { return parBlock; }
|
||||
public StyleMap getTextStyleMap() { return text; }
|
||||
public StyleMap getListStyleMap() { return list; }
|
||||
public StyleMap getListItemStyleMap() { return listItem; }
|
||||
public StyleMap getTextAttributeStyleMap() { return textAttr; }
|
||||
public HeadingMap getHeadingMap() { return headingMap; }
|
||||
public LinkedList getCustomPreamble() { return customPreamble; }
|
||||
|
||||
}
|
||||
|
152
source/java/writer2latex/latex/LaTeXDocument.java
Normal file
152
source/java/writer2latex/latex/LaTeXDocument.java
Normal file
|
@ -0,0 +1,152 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* LaTeXDocument.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import writer2latex.xmerge.Document;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
/**
|
||||
* <p>Class representing a LaTeX document.</p>
|
||||
*
|
||||
*/
|
||||
public class LaTeXDocument implements Document {
|
||||
private static final String FILE_EXTENSION = ".tex";
|
||||
|
||||
private String sName;
|
||||
|
||||
private String sEncoding = "ASCII";
|
||||
|
||||
private int nWrap;
|
||||
|
||||
private LaTeXDocumentPortion contents;
|
||||
|
||||
/**
|
||||
* <p>Constructs a new LaTeX Document.</p>
|
||||
*
|
||||
* <p>This new document is empty. Document data must added to the preamble and
|
||||
* the body using appropriate methods.</p>
|
||||
*
|
||||
* @param sName The name of the <code>LaTeXDocument</code>.
|
||||
* @param nWrap Lines should be wrapped after this position
|
||||
*/
|
||||
public LaTeXDocument(String sName,int nWrap) {
|
||||
this.nWrap = nWrap;
|
||||
this.sName = trimDocumentName(sName);
|
||||
contents = new LaTeXDocumentPortion(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This method is supposed to read <code>byte</code> data from the InputStream.
|
||||
* Currently it does nothing, since we don't need it.</p>
|
||||
*
|
||||
* @param is InputStream containing a LaTeX data file.
|
||||
*
|
||||
* @throws IOException In case of any I/O errors.
|
||||
*/
|
||||
public void read(InputStream is) throws IOException {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the <code>Document</code> name with no file extension.</p>
|
||||
*
|
||||
* @return The <code>Document</code> name with no file extension.
|
||||
*/
|
||||
public String getName() {
|
||||
return sName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the <code>Document</code> name with file extension.</p>
|
||||
*
|
||||
* @return The <code>Document</code> name with file extension.
|
||||
*/
|
||||
public String getFileName() {
|
||||
return new String(sName + FILE_EXTENSION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Writes out the <code>Document</code> content to the specified
|
||||
* <code>OutputStream</code>.</p>
|
||||
*
|
||||
* <p>This method may not be thread-safe.
|
||||
* Implementations may or may not synchronize this
|
||||
* method. User code (i.e. caller) must make sure that
|
||||
* calls to this method are thread-safe.</p>
|
||||
*
|
||||
* @param os <code>OutputStream</code> to write out the
|
||||
* <code>Document</code> content.
|
||||
*
|
||||
* @throws IOException If any I/O error occurs.
|
||||
*/
|
||||
public void write(OutputStream os) throws IOException {
|
||||
OutputStreamWriter osw = new OutputStreamWriter(os,sEncoding);
|
||||
contents.write(osw,nWrap,"\n");
|
||||
osw.flush();
|
||||
osw.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Set the output encoding to use when writing the document.</p>
|
||||
*/
|
||||
public void setEncoding(String sEncoding) { this.sEncoding = sEncoding; }
|
||||
|
||||
/**
|
||||
* <p>Returns the <code>LaTeXDocumentPortion</code>, that contains the
|
||||
* contents of the document.</p>
|
||||
*
|
||||
* @return The content <code>LaTeXDocumentPortion</code>.
|
||||
*/
|
||||
public LaTeXDocumentPortion getContents(){
|
||||
return contents;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility method to make sure the document name is stripped of any file
|
||||
* extensions before use.
|
||||
*/
|
||||
private String trimDocumentName(String name) {
|
||||
String temp = name.toLowerCase();
|
||||
|
||||
if (temp.endsWith(FILE_EXTENSION)) {
|
||||
// strip the extension
|
||||
int nlen = name.length();
|
||||
int endIndex = nlen - FILE_EXTENSION.length();
|
||||
name = name.substring(0,endIndex);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
214
source/java/writer2latex/latex/LaTeXDocumentPortion.java
Normal file
214
source/java/writer2latex/latex/LaTeXDocumentPortion.java
Normal file
|
@ -0,0 +1,214 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* LaTeXDocumentPortion.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2006 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2007-10-02)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Vector;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/** This class represents a portion of a LaTeX document. A portion is any
|
||||
number of lines, and may include subportions. */
|
||||
public class LaTeXDocumentPortion {
|
||||
|
||||
private Vector nodes; // The collection of all nodes in this portion
|
||||
|
||||
private StringBuffer curText; // The currently active node (always the last node)
|
||||
private boolean bEmpty; // Is the active node empty?
|
||||
|
||||
private boolean bWrap; // Do we allow line wrap in this portion?
|
||||
|
||||
public LaTeXDocumentPortion(boolean bWrap){
|
||||
this.bWrap = bWrap;
|
||||
nodes = new Vector();
|
||||
curText = new StringBuffer();
|
||||
bEmpty = true;
|
||||
}
|
||||
|
||||
/** Add another portion to the end of this portion */
|
||||
public LaTeXDocumentPortion append(LaTeXDocumentPortion ldp) {
|
||||
if (!bEmpty) {
|
||||
// add the current node to the node list and create new current node
|
||||
nodes.add(curText);
|
||||
curText = new StringBuffer();
|
||||
bEmpty = true;
|
||||
}
|
||||
nodes.add(ldp);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Add a string to the end of this portion */
|
||||
public LaTeXDocumentPortion append(String s){
|
||||
curText.append(s);
|
||||
bEmpty = false; // even if this is the empty string!
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Add a newline to the end of this portion */
|
||||
public LaTeXDocumentPortion nl(){
|
||||
curText.append("\n");
|
||||
bEmpty = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** write a segment of text (eg. a word) to the output */
|
||||
private void writeSegment(String s, int nStart, int nEnd, OutputStreamWriter osw) throws IOException {
|
||||
for (int i=nStart; i<nEnd; i++) { osw.write(s.charAt(i)); }
|
||||
}
|
||||
|
||||
/** write the contents of a StringBuffer to the output */
|
||||
private void writeBuffer(StringBuffer text, OutputStreamWriter osw, int nLineLen, String sNewline) throws IOException {
|
||||
String s = text.toString();
|
||||
int nLen = s.length();
|
||||
|
||||
int[] nBreakPoints = new int[100];
|
||||
int nLastBPIndex = 99;
|
||||
|
||||
int nStart = 0;
|
||||
|
||||
while (nStart<nLen) {
|
||||
// identify line and breakpoints
|
||||
int nBPIndex = 0;
|
||||
boolean bEscape = false;
|
||||
boolean bComment = false;
|
||||
int nNewline = nStart;
|
||||
char c;
|
||||
while (nNewline<nLen) {
|
||||
if (nBPIndex==nLastBPIndex) {
|
||||
nBreakPoints = Misc.doubleIntArray(nBreakPoints);
|
||||
nLastBPIndex = nBreakPoints.length-1;
|
||||
}
|
||||
c = s.charAt(nNewline);
|
||||
if (c=='\n') {
|
||||
nBreakPoints[nBPIndex++] = nNewline;
|
||||
break;
|
||||
}
|
||||
if (bEscape) { bEscape = false; }
|
||||
else if (c=='\\') { bEscape = true; }
|
||||
else if (c=='%') { bComment = true; }
|
||||
else if (!bComment && c==' ') { nBreakPoints[nBPIndex++] = nNewline; }
|
||||
nNewline++;
|
||||
}
|
||||
if (nBPIndex==nLastBPIndex) {
|
||||
nBreakPoints = Misc.doubleIntArray(nBreakPoints);
|
||||
nLastBPIndex = nBreakPoints.length-1;
|
||||
}
|
||||
if (nNewline==nLen) { nBreakPoints[nBPIndex++] = nNewline; }
|
||||
|
||||
// write out line
|
||||
int nCurLineLen = nBreakPoints[0]-nStart;
|
||||
writeSegment(s,nStart,nBreakPoints[0],osw);
|
||||
for (int i=0; i<nBPIndex-1; i++) {
|
||||
int nSegmentLen = nBreakPoints[i+1]-nBreakPoints[i];
|
||||
if (nSegmentLen+nCurLineLen>nLineLen) {
|
||||
// break line before this segment
|
||||
osw.write(sNewline);
|
||||
nCurLineLen = nSegmentLen;
|
||||
}
|
||||
else {
|
||||
// segment fits in current line
|
||||
osw.write(" ");
|
||||
nCurLineLen += nSegmentLen;
|
||||
}
|
||||
writeSegment(s,nBreakPoints[i]+1,nBreakPoints[i+1],osw);
|
||||
}
|
||||
osw.write(sNewline);
|
||||
nStart = nNewline+1;
|
||||
}
|
||||
}
|
||||
|
||||
/** write the contents of a StringBuffer to the output without wrap */
|
||||
private void writeBuffer(StringBuffer text, OutputStreamWriter osw, String sNewline) throws IOException {
|
||||
String s = text.toString();
|
||||
int nLen = s.length();
|
||||
|
||||
int nStart = 0;
|
||||
|
||||
while (nStart<nLen) {
|
||||
// identify line
|
||||
int nNewline = nStart;
|
||||
while (nNewline<nLen) {
|
||||
if (s.charAt(nNewline)=='\n') { break; }
|
||||
nNewline++;
|
||||
}
|
||||
|
||||
// write out line
|
||||
writeSegment(s,nStart,nNewline,osw);
|
||||
osw.write(sNewline);
|
||||
nStart = nNewline+1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Write this portion to the output (note: nLineLen=0 means no wrap) */
|
||||
public void write(OutputStreamWriter osw, int nLineLen, String sNewline) throws IOException {
|
||||
int n = nodes.size();
|
||||
for (int i=0; i<n; i++) {
|
||||
if (nodes.get(i) instanceof LaTeXDocumentPortion) {
|
||||
((LaTeXDocumentPortion) nodes.get(i)).write(osw,nLineLen,sNewline);
|
||||
}
|
||||
else if (bWrap && nLineLen>0) {
|
||||
writeBuffer((StringBuffer) nodes.get(i),osw,nLineLen,sNewline);
|
||||
}
|
||||
else {
|
||||
writeBuffer((StringBuffer) nodes.get(i),osw,sNewline);
|
||||
}
|
||||
}
|
||||
if (!bEmpty) { // write current node as well
|
||||
if (bWrap && nLineLen>0) {
|
||||
writeBuffer(curText,osw,nLineLen,sNewline);
|
||||
}
|
||||
else {
|
||||
writeBuffer(curText,osw,sNewline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the content of this LaTeXDocumentStream as a string */
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
int n = nodes.size();
|
||||
for (int i=0; i<n; i++) {
|
||||
if (nodes.get(i) instanceof LaTeXDocumentPortion) {
|
||||
buf.append(((LaTeXDocumentPortion) nodes.get(i)).toString());
|
||||
}
|
||||
else {
|
||||
buf.append(((StringBuffer) nodes.get(i)).toString());
|
||||
}
|
||||
}
|
||||
if (!bEmpty) { // write current node as well
|
||||
buf.append(curText.toString());
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end class LaTeXDocumentPortion
|
||||
|
||||
// TO DO: consider StringBuffer->ByteArrayOutputStream (performance??)
|
||||
|
384
source/java/writer2latex/latex/ListStyleConverter.java
Normal file
384
source/java/writer2latex/latex/ListStyleConverter.java
Normal file
|
@ -0,0 +1,384 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ListStyleConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/* This class creates LaTeX code from OOo list styles
|
||||
*/
|
||||
public class ListStyleConverter extends StyleConverter {
|
||||
boolean bNeedSaveEnumCounter = false;
|
||||
private Hashtable listStyleLevelNames = new Hashtable();
|
||||
|
||||
/** <p>Constructs a new <code>ListStyleConverter</code>.</p>
|
||||
*/
|
||||
public ListStyleConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST || !styleNames.isEmpty()) {
|
||||
decl.append("% List styles").nl();
|
||||
// May need an extra counter to handle continued numbering in lists
|
||||
if (bNeedSaveEnumCounter) {
|
||||
decl.append("\\newcounter{saveenum}").nl();
|
||||
}
|
||||
// If we export formatting, we need some hooks from lists to paragraphs:
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) {
|
||||
decl.append("\\newcommand\\writerlistleftskip{}").nl()
|
||||
.append("\\newcommand\\writerlistparindent{}").nl()
|
||||
.append("\\newcommand\\writerlistlabel{}").nl()
|
||||
.append("\\newcommand\\writerlistremovelabel{")
|
||||
.append("\\aftergroup\\let\\aftergroup\\writerlistparindent\\aftergroup\\relax")
|
||||
.append("\\aftergroup\\let\\aftergroup\\writerlistlabel\\aftergroup\\relax}").nl();
|
||||
}
|
||||
super.appendDeclarations(pack,decl);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply a list style to an ordered or unordered list.</p> */
|
||||
public void applyListStyle(String sStyleName, int nLevel, boolean bOrdered,
|
||||
boolean bContinue, BeforeAfter ba) {
|
||||
// Step 1. We may have a style map, this always takes precedence
|
||||
String sDisplayName = ofr.getListStyles().getDisplayName(sStyleName);
|
||||
if (config.getListStyleMap().contains(sDisplayName)) {
|
||||
ba.add(config.getListStyleMap().getBefore(sDisplayName),
|
||||
config.getListStyleMap().getAfter(sDisplayName));
|
||||
return;
|
||||
}
|
||||
// Step 2: The list style may not exist, or the user wants to ignore it.
|
||||
// In this case we create default lists
|
||||
ListStyle style = ofr.getListStyle(sStyleName);
|
||||
if (style==null || config.formatting()<=LaTeXConfig.IGNORE_MOST) {
|
||||
if (nLevel<=4) {
|
||||
if (bOrdered) {
|
||||
ba.add("\\begin{enumerate}","\\end{enumerate}");
|
||||
}
|
||||
else {
|
||||
ba.add("\\begin{itemize}","\\end{itemize}");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Step 3: Export as default lists, but redefine labels
|
||||
if (config.formatting()==LaTeXConfig.CONVERT_BASIC) {
|
||||
if (nLevel==1) {
|
||||
if (!styleNames.containsName(getDisplayName(sStyleName))) {
|
||||
createListStyleLabels(sStyleName);
|
||||
}
|
||||
ba.add("\\liststyle"+styleNames.getExportName(getDisplayName(sStyleName))+"\n","");
|
||||
}
|
||||
if (nLevel<=4) {
|
||||
String sCounterName = ((String[]) listStyleLevelNames.get(sStyleName))[nLevel];
|
||||
if (bContinue && style.isNumber(nLevel)) {
|
||||
bNeedSaveEnumCounter = true;
|
||||
ba.add("\\setcounter{saveenum}{\\value{"+sCounterName+"}}\n","");
|
||||
}
|
||||
if (bOrdered) {
|
||||
ba.add("\\begin{enumerate}","\\end{enumerate}");
|
||||
}
|
||||
else {
|
||||
ba.add("\\begin{itemize}","\\end{itemize}");
|
||||
}
|
||||
if (bContinue && style.isNumber(nLevel)) {
|
||||
ba.add("\n\\setcounter{"+sCounterName+"}{\\value{saveenum}}","");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Step 4: Export with formatting, as "Writer style" custom lists
|
||||
if (nLevel<=4) { // TODO: Max level should not be fixed
|
||||
if (!styleNames.containsName(getDisplayName(sStyleName))) {
|
||||
createListStyle(sStyleName);
|
||||
}
|
||||
String sTeXName="list"+styleNames.getExportName(getDisplayName(sStyleName))
|
||||
+"level"+Misc.int2roman(nLevel);
|
||||
if (!bContinue && style.isNumber(nLevel)) {
|
||||
int nStartValue = Misc.getPosInteger(style.getLevelProperty(nLevel,XMLString.TEXT_START_VALUE),1)-1;
|
||||
ba.add("\\setcounter{"+sTeXName+"}{"+Integer.toString(nStartValue)+"}\n","");
|
||||
}
|
||||
ba.add("\\begin{"+sTeXName+"}","\\end{"+sTeXName+"}");
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply a list style to a list item.</p> */
|
||||
public void applyListItemStyle(String sStyleName, int nLevel, boolean bHeader,
|
||||
boolean bRestart, int nStartValue, BeforeAfter ba) {
|
||||
// Step 1. We may have a style map, this always takes precedence
|
||||
String sDisplayName = ofr.getListStyles().getDisplayName(sStyleName);
|
||||
if (config.getListItemStyleMap().contains(sDisplayName)) {
|
||||
ba.add(config.getListItemStyleMap().getBefore(sDisplayName),
|
||||
config.getListItemStyleMap().getAfter(sDisplayName));
|
||||
return;
|
||||
}
|
||||
// Step 2: The list style may not exist, or the user wants to ignore it.
|
||||
// In this case we create default lists
|
||||
ListStyle style = ofr.getListStyle(sStyleName);
|
||||
if (style==null || config.formatting()<=LaTeXConfig.IGNORE_MOST) {
|
||||
if (nLevel<=4) {
|
||||
if (bHeader) { ba.add("\\item[] ",""); }
|
||||
else { ba.add("\\item ",""); }
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Step 3: Export as default lists (with redefined labels)
|
||||
if (config.formatting()==LaTeXConfig.CONVERT_BASIC) {
|
||||
if (nLevel<=4) {
|
||||
if (bHeader) {
|
||||
ba.add("\\item[] ","");
|
||||
}
|
||||
else if (bRestart && style.isNumber(nLevel)) {
|
||||
ba.add("\n\\setcounter{enum"+Misc.int2roman(nLevel)
|
||||
+"}{"+(nStartValue-1)+"}\n\\item ","");
|
||||
}
|
||||
else {
|
||||
ba.add("\\item ","");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Step 4: Export with formatting, as "Writer style" custom lists
|
||||
if (nLevel<=4 && !bHeader) { // TODO: Max level should not be fixed
|
||||
String sTeXName="list"+styleNames.getExportName(getDisplayName(sStyleName))
|
||||
+"level"+Misc.int2roman(nLevel);
|
||||
if (bRestart && style.isNumber(nLevel)) {
|
||||
ba.add("\\setcounter{"+sTeXName+"}{"+(nStartValue-1)+"}\n","");
|
||||
}
|
||||
ba.add("\\item ","");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** <p>Create labels for default lists (enumerate/itemize) based on
|
||||
* a List Style
|
||||
*/
|
||||
private void createListStyleLabels(String sStyleName) {
|
||||
String sTeXName = styleNames.getExportName(getDisplayName(sStyleName));
|
||||
declarations.append("\\newcommand\\liststyle")
|
||||
.append(sTeXName).append("{%").nl();
|
||||
ListStyle style = ofr.getListStyle(sStyleName);
|
||||
int nEnum = 0;
|
||||
int nItem = 0;
|
||||
String sName[] = new String[5];
|
||||
for (int i=1; i<=4; i++) {
|
||||
if (style.isNumber(i)) { sName[i]="enum"+Misc.int2roman(++nEnum); }
|
||||
else { sName[i]="item"+Misc.int2roman(++nItem); }
|
||||
}
|
||||
listStyleLevelNames.put(sStyleName, sName);
|
||||
createLabels(style, sName, 4, false, true, false, declarations);
|
||||
declarations.append("}").nl();
|
||||
}
|
||||
|
||||
/** <p>Create "Writer style" lists based on a List Style.
|
||||
<p>A list in writer is really a sequence of numbered paragraphs, so
|
||||
this is also how we implement it in LaTeX.
|
||||
The enivronment + redefined \item defines three hooks:
|
||||
\writerlistleftskip, \writerlistparindent, \writerlistlabel
|
||||
which are used by exported paragraph styles to apply numbering.
|
||||
*/
|
||||
private void createListStyle(String sStyleName) {
|
||||
ListStyle style = ofr.getListStyle(sStyleName);
|
||||
|
||||
// Create labels
|
||||
String sTeXName = styleNames.getExportName(getDisplayName(sStyleName));
|
||||
String[] sLevelName = new String[5];
|
||||
for (int i=1; i<=4; i++) {
|
||||
sLevelName[i]="list"+sTeXName+"level"+Misc.int2roman(i);
|
||||
}
|
||||
createLabels(style,sLevelName,4,true,false,true,declarations);
|
||||
|
||||
// Create environments
|
||||
for (int i=1; i<=4; i++) {
|
||||
String sSpaceBefore = getLength(style,i,XMLString.TEXT_SPACE_BEFORE);
|
||||
String sLabelWidth = getLength(style,i,XMLString.TEXT_MIN_LABEL_WIDTH);
|
||||
String sLabelDistance = getLength(style,i,XMLString.TEXT_MIN_LABEL_DISTANCE);
|
||||
String sTextAlign = style.getLevelStyleProperty(i,XMLString.FO_TEXT_ALIGN);
|
||||
String sAlignmentChar = "l"; // start (or left) is default
|
||||
if (sTextAlign!=null) {
|
||||
if ("end".equals(sTextAlign)) { sAlignmentChar="r"; }
|
||||
else if ("right".equals(sTextAlign)) { sAlignmentChar="r"; }
|
||||
else if ("center".equals(sTextAlign)) { sAlignmentChar="c"; }
|
||||
}
|
||||
declarations
|
||||
.append("\\newenvironment{")
|
||||
.append(sLevelName[i]).append("}{")
|
||||
.append("\\def\\writerlistleftskip{\\addtolength\\leftskip{")
|
||||
.append(Misc.add(sSpaceBefore,sLabelWidth)).append("}}")
|
||||
.append("\\def\\writerlistparindent{}")
|
||||
.append("\\def\\writerlistlabel{}");
|
||||
// Redefine \item
|
||||
declarations
|
||||
.append("\\def\\item{")
|
||||
.append("\\def\\writerlistparindent{\\setlength\\parindent{")
|
||||
.append("-").append(sLabelWidth).append("}}")
|
||||
.append("\\def\\writerlistlabel{");
|
||||
if (style.isNumber(i)) {
|
||||
declarations.append("\\stepcounter{")
|
||||
.append(sLevelName[i]).append("}");
|
||||
}
|
||||
declarations
|
||||
.append("\\makebox[").append(sLabelWidth).append("][")
|
||||
.append(sAlignmentChar).append("]{")
|
||||
.append("\\label").append(sLevelName[i]).append("}")
|
||||
.append("\\hspace{").append(sLabelDistance).append("}")
|
||||
.append("\\writerlistremovelabel}}}{}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Create LaTeX list labels from an OOo list style. Examples:</p>
|
||||
* <p>Bullets:</p>
|
||||
* <pre>\newcommand\labelliststylei{\textbullet}
|
||||
* \newcommand\labelliststyleii{*}
|
||||
* \newcommand\labelliststyleiii{\textstylebullet{>}}</pre>
|
||||
* <p>Numbering:</p>
|
||||
* <pre>\newcounter{liststylei}
|
||||
* \newcounter{liststyleii}[liststylei]
|
||||
* \newcounter{liststyleiii}[liststyleii]
|
||||
* \renewcommand\theliststylei{\Roman{liststylei}}
|
||||
* \renewcommand\theliststyleii{\Roman{liststylei}.\arabic{liststyleii}}
|
||||
* \renewcommand\theliststyleiii{\alph{liststyleiii}}
|
||||
* \newcommand\labelliststylei{\textstylelabel{\theliststylei .}}
|
||||
* \newcommand\labelliststyleii{\textstylelabel{\theliststyleii .}}
|
||||
* \newcommand\labelliststyleiii{\textstylelabel{\theliststyleiii )}}</pre>
|
||||
*
|
||||
* @param <code>style</code> the OOo list style to use
|
||||
* @param <code>sName</code> an array of label basenames to use
|
||||
* @param <code>nMaxLevel</code> the highest level in this numbering
|
||||
* @param <code>bDeclareCounters</code> true if counters should be declared (they may
|
||||
* exist already, eg. "section", "subsection"... or "enumi", "enumii"...
|
||||
* @param <code>bRenewLabels</code> true if labels should be defined with \renewcommand
|
||||
* @param <code>bUseTextStyle</code> true if labels should be formatted with the associated text style
|
||||
* (rather than \newcommand).
|
||||
* @param <code>ldp</code> the <code>LaTeXDocumentPortion</code> to add LaTeX code to.
|
||||
*/
|
||||
private void createLabels(ListStyle style, String[] sName, int nMaxLevel,
|
||||
boolean bDeclareCounters, boolean bRenewLabels,
|
||||
boolean bUseTextStyle, LaTeXDocumentPortion ldp) {
|
||||
// Declare counters if required (eg. "\newcounter{countername1}[countername2]")
|
||||
if (bDeclareCounters) {
|
||||
int j = 0;
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
if (style.isNumber(i)) {
|
||||
ldp.append("\\newcounter{").append(sName[i]).append("}");
|
||||
if (j>0) { ldp.append("[").append(sName[j]).append("]"); }
|
||||
ldp.nl();
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create numbering for each level (eg. "\arabic{countername}")
|
||||
String[] sNumFormat = new String[nMaxLevel+1];
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
String s = numFormat(style.getLevelProperty(i,XMLString.STYLE_NUM_FORMAT));
|
||||
if (s==null) { sNumFormat[i]=""; }
|
||||
else { sNumFormat[i] = s + "{" + sName[i] + "}"; }
|
||||
}
|
||||
// Create numberings (ie. define "\thecountername"):
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
if (style.isNumber(i)) {
|
||||
ldp.append("\\renewcommand\\the").append(sName[i]).append("{");
|
||||
int nLevels = Misc.getPosInteger(style.getLevelProperty(i,XMLString.TEXT_DISPLAY_LEVELS),1);
|
||||
for (int j=i-nLevels+1; j<i; j++) {
|
||||
if (style.isNumber(j)) {
|
||||
ldp.append(sNumFormat[j]).append(".");
|
||||
}
|
||||
}
|
||||
ldp.append(sNumFormat[i]);
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
}
|
||||
// Create labels (ie. define "\labelcountername"):
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
ldp.append(bRenewLabels ? "\\renewcommand" : "\\newcommand")
|
||||
.append("\\label").append(sName[i]).append("{");
|
||||
// Apply text style if required
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
if (bUseTextStyle) {
|
||||
String sStyleName = style.getLevelProperty(i,XMLString.TEXT_STYLE_NAME);
|
||||
palette.getCharSc().applyTextStyle(sStyleName,baText,new Context());
|
||||
}
|
||||
|
||||
// Create label content
|
||||
if (style.isNumber(i)) {
|
||||
String sPrefix = style.getLevelProperty(i,XMLString.STYLE_NUM_PREFIX);
|
||||
String sSuffix = style.getLevelProperty(i,XMLString.STYLE_NUM_SUFFIX);
|
||||
// Apply style
|
||||
ldp.append(baText.getBefore());
|
||||
if (sPrefix!=null) { ldp.append(sPrefix); }
|
||||
ldp.append("\\the").append(sName[i]);
|
||||
if (sSuffix!=null) { ldp.append(sSuffix); }
|
||||
ldp.append(baText.getAfter());
|
||||
}
|
||||
else if (style.isBullet(i)) {
|
||||
String sBullet = style.getLevelProperty(i,XMLString.TEXT_BULLET_CHAR);
|
||||
// Apply style
|
||||
ldp.append(baText.getBefore());
|
||||
if (sBullet!=null) {
|
||||
// Bullets are usually symbols, so this should be OK:
|
||||
ldp.append(palette.getI18n().convert(sBullet,false,"en"));
|
||||
}
|
||||
ldp.append(baText.getAfter());
|
||||
}
|
||||
else {
|
||||
// TODO: Support images!
|
||||
ldp.append("\\textbullet");
|
||||
}
|
||||
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper: Get a length property that defaults to 0cm. */
|
||||
private String getLength(ListStyle style,int nLevel,String sProperty) {
|
||||
String s = style.getLevelStyleProperty(nLevel,sProperty);
|
||||
if (s==null) { return "0cm"; }
|
||||
else { return s; }
|
||||
}
|
||||
|
||||
/* Helper: Get display name, or original name if it doesn't exist */
|
||||
private String getDisplayName(String sName) {
|
||||
String sDisplayName = ofr.getListStyles().getDisplayName(sName);
|
||||
return sDisplayName!=null ? sDisplayName : sName;
|
||||
}
|
||||
|
||||
/* Helper: Convert OOo number format to LaTeX number format */
|
||||
public static final String numFormat(String sFormat){
|
||||
if ("1".equals(sFormat)) { return "\\arabic"; }
|
||||
else if ("i".equals(sFormat)) { return "\\roman"; }
|
||||
else if ("I".equals(sFormat)) { return "\\Roman"; }
|
||||
else if ("a".equals(sFormat)) { return "\\alph"; }
|
||||
else if ("A".equals(sFormat)) { return "\\Alph"; }
|
||||
else { return null; }
|
||||
}
|
||||
|
||||
}
|
232
source/java/writer2latex/latex/MathmlConverter.java
Normal file
232
source/java/writer2latex/latex/MathmlConverter.java
Normal file
|
@ -0,0 +1,232 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* MathmlConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
//import java.util.Hashtable;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
//import writer2latex.latex.i18n.I18n;
|
||||
import writer2latex.office.MIMETypes;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.xmerge.EmbeddedObject;
|
||||
import writer2latex.xmerge.EmbeddedXMLObject;
|
||||
|
||||
/**
|
||||
* This class converts mathml nodes to LaTeX.
|
||||
* (Actually it only converts the starmath annotation currently, if available).
|
||||
*/
|
||||
public final class MathmlConverter extends ConverterHelper {
|
||||
|
||||
private StarMathConverter smc;
|
||||
|
||||
private boolean bContainsFormulas = false;
|
||||
|
||||
public MathmlConverter(OfficeReader ofr,LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
smc = new StarMathConverter(palette.getI18n(),config);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bContainsFormulas) {
|
||||
if (config.useOoomath()) {
|
||||
pack.append("\\usepackage{ooomath}").nl();
|
||||
}
|
||||
else {
|
||||
smc.appendDeclarations(pack,decl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String convert(Node settings, Node formula) {
|
||||
// TODO: Use settings to determine display mode/text mode
|
||||
// formula must be a math:math node
|
||||
// First try to find a StarMath annotation
|
||||
Node semantics = Misc.getChildByTagName(formula,XMLString.MATH_SEMANTICS);
|
||||
if (semantics!=null) {
|
||||
Node annotation = Misc.getChildByTagName(semantics,XMLString.MATH_ANNOTATION);
|
||||
if (annotation!=null) {
|
||||
String sStarMath = "";
|
||||
if (annotation.hasChildNodes()) {
|
||||
NodeList anl = annotation.getChildNodes();
|
||||
int nLen = anl.getLength();
|
||||
for (int i=0; i<nLen; i++) {
|
||||
if (anl.item(i).getNodeType() == Node.TEXT_NODE) {
|
||||
sStarMath+=anl.item(i).getNodeValue();
|
||||
}
|
||||
}
|
||||
bContainsFormulas = true;
|
||||
return smc.convert(sStarMath);
|
||||
}
|
||||
}
|
||||
}
|
||||
// No annotation was found. In this case we should convert the mathml,
|
||||
// but currently we ignore the problem.
|
||||
// TODO: Investigate if Vasil I. Yaroshevich's MathML->LaTeX
|
||||
// XSL transformation could be used here. (Potential problem:
|
||||
// OOo uses MathML 1.01, not MathML 2)
|
||||
return "\\text{Warning: No StarMath annotation}";
|
||||
}
|
||||
|
||||
// Data for display equations
|
||||
private Element theEquation = null;
|
||||
private Element theSequence = null;
|
||||
|
||||
/**Try to convert a paragraph as a display equation:
|
||||
* A paragraph which contains exactly one formula + at most one sequence
|
||||
* number is treated as a display equation. Other content must be brackets
|
||||
* or whitespace (possible with formatting).
|
||||
* @param node the paragraph
|
||||
* @param ldp the LaTeXDocumentPortion to contain the converted equation
|
||||
* @return true if the conversion was succesful, false if the paragraph
|
||||
* did not contain a display equation
|
||||
*/
|
||||
public boolean handleDisplayEquation(Element node, LaTeXDocumentPortion ldp) {
|
||||
theEquation = null;
|
||||
theSequence = null;
|
||||
if (parseDisplayEquation(node) && theEquation!=null) {
|
||||
if (theSequence!=null) {
|
||||
// Numbered equation
|
||||
ldp.append("\\begin{equation}");
|
||||
palette.getFieldCv().handleSequenceLabel(theSequence,ldp);
|
||||
ldp.nl()
|
||||
.append(convert(null,theEquation)).nl()
|
||||
.append("\\end{equation}").nl();
|
||||
}
|
||||
else {
|
||||
// Unnumbered equation
|
||||
ldp.append("\\begin{equation*}").nl()
|
||||
.append(convert(null,theEquation)).nl()
|
||||
.append("\\end{equation*}").nl();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean parseDisplayEquation(Node node) {
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
Node equation = getFormula(child);
|
||||
if (equation!=null) {
|
||||
if (theEquation==null) {
|
||||
theEquation = (Element) equation;
|
||||
}
|
||||
else { // two or more equations -> not a display
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (Misc.isElement(child)) {
|
||||
String sName = child.getNodeName();
|
||||
if (XMLString.TEXT_SEQUENCE.equals(sName)) {
|
||||
if (theSequence==null) {
|
||||
theSequence = (Element) child;
|
||||
}
|
||||
else { // two sequence numbers -> not a display
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (XMLString.TEXT_SPAN.equals(sName)) {
|
||||
if (!parseDisplayEquation(child)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (XMLString.TEXT_S.equals(sName)) {
|
||||
// Spaces are allowed
|
||||
}
|
||||
else if (XMLString.TEXT_TAB.equals(sName)) {
|
||||
// Tab stops are allowed
|
||||
}
|
||||
else if (XMLString.TEXT_TAB_STOP.equals(sName)) { // old
|
||||
// Tab stops are allowed
|
||||
}
|
||||
else {
|
||||
// Other elements -> not a display
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (Misc.isText(child)) {
|
||||
String s = child.getNodeValue();
|
||||
int nLen = s.length();
|
||||
for (int i=0; i<nLen; i++) {
|
||||
char c = s.charAt(i);
|
||||
if (c!='(' && c!=')' && c!='[' && c!=']' && c!='{' && c!='}' && c!=' ' && c!='\u00A0') {
|
||||
// Characters except brackets and whitespace -> not a display
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Extend OfficeReader to handle frames
|
||||
private Node getFormula(Node node) {
|
||||
if (Misc.isElement(node,XMLString.DRAW_FRAME)) {
|
||||
node=Misc.getFirstChildElement(node);
|
||||
}
|
||||
|
||||
String sHref = Misc.getAttribute(node,XMLString.XLINK_HREF);
|
||||
|
||||
if (sHref!=null) { // Embedded object in package or linked object
|
||||
if (ofr.isInPackage(sHref)) { // Embedded object in package
|
||||
if (sHref.startsWith("#")) { sHref=sHref.substring(1); }
|
||||
if (sHref.startsWith("./")) { sHref=sHref.substring(2); }
|
||||
EmbeddedObject object = palette.getEmbeddedObject(sHref);
|
||||
if (object!=null) {
|
||||
if (MIMETypes.MATH.equals(object.getType()) || MIMETypes.ODF.equals(object.getType())) { // Formula!
|
||||
try {
|
||||
Document formuladoc = ((EmbeddedXMLObject) object).getContentDOM();
|
||||
return Misc.getChildByTagName(formuladoc,XMLString.MATH_MATH);
|
||||
}
|
||||
catch (org.xml.sax.SAXException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (java.io.IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // flat xml, object is contained in node
|
||||
return Misc.getChildByTagName(node,XMLString.MATH_MATH);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
391
source/java/writer2latex/latex/NoteConverter.java
Normal file
391
source/java/writer2latex/latex/NoteConverter.java
Normal file
|
@ -0,0 +1,391 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* NoteConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.util.ExportNameCollection;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.PropertySet;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/**
|
||||
* <p>This class handles conversion of footnotes and endnotes, including
|
||||
* references. It takes advantage of the packages <code>endnotes.sty</code>
|
||||
* and <code>perpage.sty</code> if allowed in the configuration.</p>
|
||||
*/
|
||||
public class NoteConverter extends ConverterHelper {
|
||||
|
||||
private ExportNameCollection footnotenames = new ExportNameCollection(true);
|
||||
private ExportNameCollection endnotenames = new ExportNameCollection(true);
|
||||
private boolean bContainsEndnotes = false;
|
||||
private boolean bContainsFootnotes = false;
|
||||
// Keep track of footnotes (inside minipage etc.), that should be typeset later
|
||||
private LinkedList postponedFootnotes = new LinkedList();
|
||||
|
||||
public NoteConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
/** <p>Append declarations needed by the <code>NoteConverter</code> to
|
||||
* the preamble.
|
||||
* @param pack the <code>LaTeXDocumentPortion</code> to which
|
||||
* declarations of packages should be added (<code>\\usepackage</code>).
|
||||
* @param decl the <code>LaTeXDocumentPortion</code> to which
|
||||
* other declarations should be added.
|
||||
*/
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bContainsEndnotes) { pack.append("\\usepackage{endnotes}").nl(); }
|
||||
if (bContainsFootnotes) convertFootnotesConfiguration(decl);
|
||||
if (bContainsEndnotes) convertEndnotesConfiguration(decl);
|
||||
}
|
||||
|
||||
/** <p>Process a footnote (text:footnote tag)
|
||||
* @param node The element containing the footnote
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleFootnote(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInFootnote(true);
|
||||
|
||||
String sId = node.getAttribute(XMLString.TEXT_ID);
|
||||
Element fntbody = Misc.getChildByTagName(node,XMLString.TEXT_FOOTNOTE_BODY);
|
||||
if (fntbody==null) { // try oasis
|
||||
fntbody = Misc.getChildByTagName(node,XMLString.TEXT_NOTE_BODY);
|
||||
}
|
||||
if (fntbody != null) {
|
||||
bContainsFootnotes = true;
|
||||
if (ic.isNoFootnotes()) {
|
||||
ldp.append("\\footnotemark{}");
|
||||
postponedFootnotes.add(fntbody);
|
||||
}
|
||||
else {
|
||||
ldp.append("\\footnote");
|
||||
ldp.append("{");
|
||||
if (sId != null && ofr.hasFootnoteRefTo(sId)) {
|
||||
ldp.append("\\label{fnt:"+footnotenames.getExportName(sId)+"}");
|
||||
}
|
||||
traverseNoteBody(fntbody,ldp,ic);
|
||||
ldp.append("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Flush the queue of postponed footnotes */
|
||||
public void flushFootnotes(LaTeXDocumentPortion ldp, Context oc) {
|
||||
// We may still be in a context with no footnotes
|
||||
if (oc.isNoFootnotes()) { return; }
|
||||
// Type out all postponed footnotes:
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInFootnote(true);
|
||||
int n = postponedFootnotes.size();
|
||||
if (n==1) {
|
||||
ldp.append("\\footnotetext{");
|
||||
traverseNoteBody((Element) postponedFootnotes.get(0),ldp,ic);
|
||||
ldp.append("}").nl();
|
||||
postponedFootnotes.clear();
|
||||
}
|
||||
else if (n>1) {
|
||||
// Several footnotes; have to adjust the footnote counter
|
||||
ldp.append("\\addtocounter{footnote}{-"+n+"}").nl();
|
||||
for (int i=0; i<n; i++) {
|
||||
ldp.append("\\stepcounter{footnote}\\footnotetext{");
|
||||
traverseNoteBody((Element) postponedFootnotes.get(i),ldp,ic);
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
postponedFootnotes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process an endnote (text:endnote tag)
|
||||
* @param node The element containing the endnote
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleEndnote(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInFootnote(true);
|
||||
|
||||
String sId = node.getAttribute(XMLString.TEXT_ID);
|
||||
Element entbody = Misc.getChildByTagName(node,XMLString.TEXT_ENDNOTE_BODY);
|
||||
if (entbody==null) { // try oasis
|
||||
entbody = Misc.getChildByTagName(node,XMLString.TEXT_NOTE_BODY);
|
||||
}
|
||||
if (entbody != null) {
|
||||
if (ic.isNoFootnotes() && !config.useEndnotes()) {
|
||||
ldp.append("\\footnotemark()");
|
||||
postponedFootnotes.add(entbody);
|
||||
}
|
||||
else {
|
||||
if (config.useEndnotes()) {
|
||||
ldp.append("\\endnote");
|
||||
bContainsEndnotes = true;
|
||||
}
|
||||
else {
|
||||
ldp.append("\\footnote");
|
||||
bContainsFootnotes = true;
|
||||
}
|
||||
ldp.append("{");
|
||||
if (sId != null && ofr.hasEndnoteRefTo(sId)) {
|
||||
ldp.append("\\label{ent:"+endnotenames.getExportName(sId)+"}");
|
||||
}
|
||||
traverseNoteBody(entbody,ldp,ic);
|
||||
ldp.append("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Insert the endnotes into the documents.
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* the endnotes should be added.
|
||||
*/
|
||||
public void insertEndnotes(LaTeXDocumentPortion ldp) {
|
||||
if (bContainsEndnotes) {
|
||||
ldp.append("\\clearpage").nl()
|
||||
.append("\\theendnotes").nl();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** <p>Process a note reference (text:note-ref tag, oasis)
|
||||
* @param node The element containing the note reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleNoteRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sClass=node.getAttribute(XMLString.TEXT_NOTE_CLASS);
|
||||
if (sClass.equals("footnote")) { handleFootnoteRef(node,ldp,oc); }
|
||||
else if (sClass.equals("endnote")) { handleEndnoteRef(node,ldp,oc); }
|
||||
}
|
||||
|
||||
/** <p>Process a footnote reference (text:footnote-ref tag)
|
||||
* @param node The element containing the footnote reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleFootnoteRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sFormat = node.getAttribute(XMLString.TEXT_REFERENCE_FORMAT);
|
||||
String sName = node.getAttribute(XMLString.TEXT_REF_NAME);
|
||||
if (("page".equals(sFormat) || "".equals(sFormat)) && sName!=null) {
|
||||
ldp.append("\\pageref{fnt:"+footnotenames.getExportName(sName)+"}");
|
||||
}
|
||||
else if ("text".equals(sFormat) && sName!=null) {
|
||||
ldp.append("\\ref{fnt:"+footnotenames.getExportName(sName)+"}");
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traversePCDATA(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process an endnote reference (text:endnote-ref tag)
|
||||
* @param node The element containing the endnote reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleEndnoteRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sFormat = node.getAttribute(XMLString.TEXT_REFERENCE_FORMAT);
|
||||
String sName = node.getAttribute(XMLString.TEXT_REF_NAME);
|
||||
if (("page".equals(sFormat) || "".equals(sFormat)) && sName!=null) {
|
||||
ldp.append("\\pageref{ent:"+endnotenames.getExportName(sName)+"}");
|
||||
}
|
||||
else if ("text".equals(sFormat) && sName!=null) {
|
||||
ldp.append("\\ref{ent:"+endnotenames.getExportName(sName)+"}");
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traversePCDATA(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Add a footnote name. The method <code>handleFootnote</code> includes
|
||||
* a <code>\label</code> only if the footnote name is already known to the
|
||||
* <code>NoteConverter</code>. Hence this method is invoked by the prepass
|
||||
* for each footnote reference. The end result is, that only necessary
|
||||
* labels will be included.
|
||||
* @param sName the name (id) of the footnote
|
||||
*/
|
||||
public void addFootnoteName(String sName) { footnotenames.addName(sName); }
|
||||
|
||||
/** <p>Add an endnote name. The method <code>handleEndnote</code> includes
|
||||
* a <code>\label</code> only if the endnote name is already known to the
|
||||
* <code>NoteConverter</code>. Hence this method is invoked by the prepass
|
||||
* for each endnote reference. The end result is, that only necessary
|
||||
* labels will be included.
|
||||
* @param sName the name (id) of the endnote
|
||||
*/
|
||||
public void addEndnoteName(String sName) { endnotenames.addName(sName); }
|
||||
|
||||
/*
|
||||
* Process the contents of a footnote or endnote
|
||||
* TODO: Merge with BlockConverter.traverseBlockText?
|
||||
*/
|
||||
private void traverseNoteBody (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList nList = node.getChildNodes();
|
||||
int len = nList.getLength();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
Node childNode = nList.item(i);
|
||||
|
||||
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element child = (Element)childNode;
|
||||
String nodeName = child.getTagName();
|
||||
|
||||
palette.getInfo().addDebugInfo(child,ldp);
|
||||
|
||||
if (nodeName.equals(XMLString.TEXT_H)) {
|
||||
palette.getHeadingCv().handleHeading(child,ldp,oc);
|
||||
}
|
||||
|
||||
if (nodeName.equals(XMLString.TEXT_P)) {
|
||||
palette.getInlineCv().traverseInlineText(child,ldp,oc);
|
||||
if (i<len-1) {
|
||||
if (nList.item(i+1).getNodeName().startsWith(XMLString.TEXT_)) {
|
||||
ldp.append("\\par ");
|
||||
}
|
||||
else {
|
||||
ldp.nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (nodeName.equals(XMLString.TEXT_LIST)) { // oasis
|
||||
palette.getBlockCv().handleList(child,ldp,oc);
|
||||
}
|
||||
|
||||
if (nodeName.equals(XMLString.TEXT_ORDERED_LIST)) {
|
||||
palette.getBlockCv().handleList(child,ldp,oc);
|
||||
}
|
||||
|
||||
if (nodeName.equals(XMLString.TEXT_UNORDERED_LIST)) {
|
||||
palette.getBlockCv().handleList(child,ldp,oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert footnotes configuration.
|
||||
private void convertFootnotesConfiguration(LaTeXDocumentPortion ldp) {
|
||||
// Note: Continuation notices are not supported in LaTeX
|
||||
// TODO: Support text:footnotes-postion="document" (footnotes as endnotes)
|
||||
// TODO: Support text:start-numbering-at="page" (footnpag.sty/footmisc.sty)
|
||||
convertFootEndnotesConfiguration(ofr.getFootnotesConfiguration(),"foot",ldp);
|
||||
}
|
||||
|
||||
// Convert endnotes configuration.
|
||||
private void convertEndnotesConfiguration(LaTeXDocumentPortion ldp) {
|
||||
// Note: Continuation notices are not supported in LaTeX
|
||||
convertFootEndnotesConfiguration(ofr.getEndnotesConfiguration(),"end",ldp);
|
||||
}
|
||||
|
||||
/* Convert {foot|end}notes configuration.
|
||||
* Note: All {foot|end}notes are formatted with the default style for {foot|end}footnotes.
|
||||
* (This doesn't conform with the file format specification, but in LaTeX
|
||||
* all {foot|end}notes are usually formatted in a fixed style.)
|
||||
*/
|
||||
private void convertFootEndnotesConfiguration(PropertySet notes, String sType, LaTeXDocumentPortion ldp) {
|
||||
if (config.formatting()<LaTeXConfig.CONVERT_BASIC) { return; }
|
||||
String sTypeShort = sType.equals("foot") ? "fn" : "en";
|
||||
if (notes==null) { return; }
|
||||
ldp.append("% ").append(sType).append("notes configuration").nl()
|
||||
.append("\\makeatletter").nl();
|
||||
|
||||
// The numbering style is controlled by \the{foot|end}note
|
||||
String sFormat = notes.getProperty(XMLString.STYLE_NUM_FORMAT);
|
||||
if (sFormat!=null) {
|
||||
ldp.append("\\renewcommand\\the").append(sType).append("note{")
|
||||
.append(ListStyleConverter.numFormat(sFormat))
|
||||
.append("{").append(sType).append("note}}").nl();
|
||||
}
|
||||
|
||||
// Number {foot|end}notes by sections
|
||||
if ("chapter".equals(notes.getProperty(XMLString.TEXT_START_NUMBERING_AT))) {
|
||||
ldp.append("\\@addtoreset{").append(sType).append("note}{section}").nl();
|
||||
}
|
||||
|
||||
// Set start value offset (default 0)
|
||||
int nStartValue = Misc.getPosInteger(notes.getProperty(XMLString.TEXT_START_VALUE),0);
|
||||
if (nStartValue!=0) {
|
||||
ldp.append("\\setcounter{").append(sType).append("note}{"+nStartValue+"}").nl();
|
||||
}
|
||||
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) {
|
||||
// The formatting of the {foot|end}note citation is controlled by \@make{fn|en}mark
|
||||
String sCitBodyStyle = notes.getProperty(XMLString.TEXT_CITATION_BODY_STYLE_NAME);
|
||||
if (sCitBodyStyle!=null && ofr.getTextStyle(sCitBodyStyle)!=null) {
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
palette.getCharSc().applyTextStyle(sCitBodyStyle,baText,new Context());
|
||||
ldp.append("\\renewcommand\\@make").append(sTypeShort).append("mark{\\mbox{")
|
||||
.append(baText.getBefore())
|
||||
.append("\\@the").append(sTypeShort).append("mark")
|
||||
.append(baText.getAfter())
|
||||
.append("}}").nl();
|
||||
}
|
||||
|
||||
// The layout and formatting of the {foot|end}note is controlled by \@make{fn|en}text
|
||||
String sCitStyle = notes.getProperty(XMLString.TEXT_CITATION_STYLE_NAME);
|
||||
String sStyleName = notes.getProperty(XMLString.TEXT_DEFAULT_STYLE_NAME);
|
||||
if (sStyleName!=null) {
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
palette.getCharSc().applyTextStyle(sCitStyle,baText,new Context());
|
||||
StyleWithProperties style = ofr.getParStyle(sStyleName);
|
||||
if (style!=null) {
|
||||
BeforeAfter baPar = new BeforeAfter();
|
||||
palette.getCharSc().applyHardCharFormatting(style,baPar);
|
||||
ldp.append("\\renewcommand\\@make").append(sTypeShort)
|
||||
.append("text[1]{\\noindent")
|
||||
.append(baText.getBefore())
|
||||
.append("\\@the").append(sTypeShort).append("mark\\ ")
|
||||
.append(baText.getAfter())
|
||||
.append(baPar.getBefore())
|
||||
.append("#1")
|
||||
.append(baPar.getAfter());
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ldp.append("\\makeatother").nl();
|
||||
}
|
||||
|
||||
|
||||
}
|
16
source/java/writer2latex/latex/Package.html
Normal file
16
source/java/writer2latex/latex/Package.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The package writer2latex.latex</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>This package contains LaTeX specific code.</p>
|
||||
<p>It contains a <code>writerlatex.api.Converter</code> implementation for
|
||||
conversion into LaTeX.</p>
|
||||
<p>Since version 1.0 you can build Writer2LaTeX without this package if you
|
||||
don't need LaTeX support (in this case you can exclude writer2latex.bibtex as
|
||||
well).</p>
|
||||
</body>
|
||||
</html>
|
596
source/java/writer2latex/latex/PageStyleConverter.java
Normal file
596
source/java/writer2latex/latex/PageStyleConverter.java
Normal file
|
@ -0,0 +1,596 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* PageStyleConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.util.CSVList;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
// TODO: chngpage.sty??
|
||||
|
||||
/* This class creates LaTeX code from OOo page layouts/master pages
|
||||
*/
|
||||
public class PageStyleConverter extends StyleConverter {
|
||||
|
||||
// Value of attribute text:display of most recent text:chapter field
|
||||
// This is used to handle chaptermarks in headings
|
||||
private String sChapterField1 = null;
|
||||
private String sChapterField2 = null;
|
||||
|
||||
// The page layout used for the page geometry
|
||||
// (LaTeX only supports one page geometry per page)
|
||||
private PageLayout mainPageLayout;
|
||||
|
||||
/** <p>Constructs a new <code>PageStyleConverter</code>.</p>
|
||||
*/
|
||||
public PageStyleConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
// Determine the main page master
|
||||
MasterPage firstMasterPage = ofr.getFirstMasterPage();
|
||||
String sPageLayoutName = null;
|
||||
if (firstMasterPage!=null) {
|
||||
MasterPage nextMasterPage = ofr.getMasterPage(
|
||||
firstMasterPage.getProperty(XMLString.STYLE_NEXT_STYLE_NAME));
|
||||
if (nextMasterPage!=null) {
|
||||
sPageLayoutName = nextMasterPage.getPageLayoutName();
|
||||
}
|
||||
else {
|
||||
sPageLayoutName = firstMasterPage.getPageLayoutName();
|
||||
}
|
||||
}
|
||||
mainPageLayout = ofr.getPageLayout(sPageLayoutName);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (config.useFancyhdr()) { pack.append("\\usepackage{fancyhdr}").nl(); }
|
||||
// The first master page must be known
|
||||
MasterPage firstMasterPage = ofr.getFirstMasterPage();
|
||||
if (firstMasterPage!=null) {
|
||||
styleNames.addName(getDisplayName(firstMasterPage.getName()));
|
||||
}
|
||||
// Convert page geometry
|
||||
convertPageMasterGeometry(pack,decl);
|
||||
// Convert master pages
|
||||
convertMasterPages(decl);
|
||||
if (firstMasterPage!=null) {
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
applyMasterPage(firstMasterPage.getName(),ba);
|
||||
decl.append(ba.getBefore());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setChapterField1(String s) { sChapterField1 = s; }
|
||||
|
||||
public void setChapterField2(String s) { sChapterField2 = s; }
|
||||
|
||||
public boolean isTwocolumn() {
|
||||
return mainPageLayout!=null && mainPageLayout.getColCount()>1;
|
||||
}
|
||||
|
||||
/** <p>Apply page break properties from a style.</p>
|
||||
* @param style the style to use
|
||||
* @param bInherit true if inheritance from parent style should be used
|
||||
* @param ba a <code>BeforeAfter</code> to put code into
|
||||
*/
|
||||
public void applyPageBreak(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style==null) { return; }
|
||||
if (style.isAutomatic() && config.ignoreHardPageBreaks()) { return; }
|
||||
// A page break can be a simple page break before or after...
|
||||
String s = style.getProperty(XMLString.FO_BREAK_BEFORE,bInherit);
|
||||
if ("page".equals(s)) { ba.add("\\clearpage",""); }
|
||||
s = style.getProperty(XMLString.FO_BREAK_AFTER,bInherit);
|
||||
if ("page".equals(s)) { ba.add("","\\clearpage"); }
|
||||
// ...or it can be a new master page
|
||||
String sMasterPage = style.getMasterPageName();
|
||||
if (sMasterPage==null || sMasterPage.length()==0) { return; }
|
||||
ba.add("\\clearpage","");
|
||||
String sPageNumber=style.getProperty(XMLString.STYLE_PAGE_NUMBER);
|
||||
if (sPageNumber!=null) {
|
||||
int nPageNumber = Misc.getPosInteger(sPageNumber,1);
|
||||
ba.add("\\setcounter{page}{"+nPageNumber+"}","");
|
||||
}
|
||||
applyMasterPage(sMasterPage,ba);
|
||||
}
|
||||
|
||||
/** <p>Use a Master Page (pagestyle in LaTeX)</p>
|
||||
* @param sName name of the master page to use
|
||||
* @param ba the <code>BeforeAfter</code> to add code to.
|
||||
*/
|
||||
private void applyMasterPage(String sName, BeforeAfter ba) {
|
||||
if (config.pageFormatting()==LaTeXConfig.IGNORE_ALL) return;
|
||||
MasterPage style = ofr.getMasterPage(sName);
|
||||
if (style==null) { return; }
|
||||
String sNextName = style.getProperty(XMLString.STYLE_NEXT_STYLE_NAME);
|
||||
MasterPage nextStyle = ofr.getMasterPage(sNextName);
|
||||
if (style==nextStyle || nextStyle==null) {
|
||||
ba.add("\\pagestyle{"+styleNames.getExportName(getDisplayName(sName))+"}\n", "");
|
||||
}
|
||||
else {
|
||||
ba.add("\\pagestyle{"+styleNames.getExportName(getDisplayName(sNextName))+"}\n"+
|
||||
"\\thispagestyle{"+styleNames.getExportName(getDisplayName(sName))+"}\n","");
|
||||
}
|
||||
// todo: should warn the user if next master also contains a next-style-name;
|
||||
// LaTeX's page style mechanism cannot handle that
|
||||
}
|
||||
|
||||
/*
|
||||
* Process header or footer contents
|
||||
*/
|
||||
private void convertMasterPages(LaTeXDocumentPortion ldp) {
|
||||
if (config.pageFormatting()==LaTeXConfig.IGNORE_ALL) { return; }
|
||||
|
||||
Context context = new Context();
|
||||
context.resetFormattingFromStyle(ofr.getDefaultParStyle());
|
||||
context.setInHeaderFooter(true);
|
||||
|
||||
|
||||
Enumeration styles = ofr.getMasterPages().getStylesEnumeration();
|
||||
ldp.append("% Pages styles").nl();
|
||||
if (!config.useFancyhdr()) {
|
||||
ldp.append("\\makeatletter").nl();
|
||||
}
|
||||
while (styles.hasMoreElements()) {
|
||||
MasterPage style = (MasterPage) styles.nextElement();
|
||||
String sName = style.getName();
|
||||
if (styleNames.containsName(getDisplayName(sName))) {
|
||||
sChapterField1 = null;
|
||||
sChapterField2 = null;
|
||||
|
||||
String sPageLayout = style.getPageLayoutName();
|
||||
PageLayout pageLayout = ofr.getPageLayout(sPageLayout);
|
||||
|
||||
if (config.useFancyhdr()) {
|
||||
ldp.append("\\fancypagestyle{")
|
||||
.append(styleNames.getExportName(getDisplayName(sName)))
|
||||
.append("}{\\fancyhf{}").nl();
|
||||
// Header - odd or both
|
||||
ldp.append(" \\fancyhead[")
|
||||
.append(getParAlignment(style.getHeader()))
|
||||
.append(style.getHeaderLeft()!=null ? "O" : "")
|
||||
.append("]{");
|
||||
traverseHeaderFooter((Element)style.getHeader(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
// Header - even
|
||||
if (style.getHeaderLeft()!=null) {
|
||||
ldp.append(" \\fancyhead[")
|
||||
.append(getParAlignment(style.getHeaderLeft()))
|
||||
.append("E]{");
|
||||
traverseHeaderFooter((Element)style.getHeaderLeft(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
// Footer - odd or both
|
||||
ldp.append(" \\fancyfoot[")
|
||||
.append(getParAlignment(style.getFooter()))
|
||||
.append(style.getFooterLeft()!=null ? "O" : "")
|
||||
.append("]{");
|
||||
traverseHeaderFooter((Element)style.getFooter(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
// Footer - even
|
||||
if (style.getFooterLeft()!=null) {
|
||||
ldp.append(" \\fancyfoot[")
|
||||
.append(getParAlignment(style.getFooterLeft()))
|
||||
.append("E]{");
|
||||
traverseHeaderFooter((Element)style.getFooterLeft(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
// Rules
|
||||
ldp.append(" \\renewcommand\\headrulewidth{")
|
||||
.append(getBorderWidth(pageLayout,true))
|
||||
.append("}").nl()
|
||||
.append(" \\renewcommand\\footrulewidth{")
|
||||
.append(getBorderWidth(pageLayout,false))
|
||||
.append("}").nl();
|
||||
}
|
||||
else { // use low-level page styles
|
||||
ldp.append("\\newcommand\\ps@")
|
||||
.append(styleNames.getExportName(getDisplayName(sName)))
|
||||
.append("{").nl();
|
||||
// Header
|
||||
ldp.append(" \\renewcommand\\@oddhead{");
|
||||
traverseHeaderFooter((Element)style.getHeader(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
ldp.append(" \\renewcommand\\@evenhead{");
|
||||
if (style.getHeaderLeft()!=null) {
|
||||
traverseHeaderFooter((Element)style.getHeaderLeft(),ldp,context);
|
||||
}
|
||||
else if (style.getHeader()!=null) {
|
||||
ldp.append("\\@oddhead");
|
||||
}
|
||||
ldp.append("}").nl();
|
||||
// Footer
|
||||
ldp.append(" \\renewcommand\\@oddfoot{");
|
||||
traverseHeaderFooter((Element)style.getFooter(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
ldp.append(" \\renewcommand\\@evenfoot{");
|
||||
if (style.getFooterLeft()!=null) {
|
||||
traverseHeaderFooter((Element)style.getFooterLeft(),ldp,context);
|
||||
}
|
||||
else if (style.getFooter()!=null) {
|
||||
ldp.append("\\@oddfoot");
|
||||
}
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
|
||||
// Sectionmark and subsectionmark
|
||||
if (sChapterField1!=null) {
|
||||
ldp.append(" \\def\\sectionmark##1{\\markboth{");
|
||||
if ("name".equals(sChapterField1)) { ldp.append("##1"); }
|
||||
else if ("number".equals(sChapterField1) || "plain-number".equals(sChapterField1)) {
|
||||
ldp.append("\\thesection");
|
||||
}
|
||||
else { ldp.append("\\thesection\\ ##1"); }
|
||||
ldp.append("}{}}").nl();
|
||||
}
|
||||
if (sChapterField2!=null) {
|
||||
if (sChapterField1==null) {
|
||||
ldp.append(" \\def\\sectionmark##1{\\markboth{}{}}").nl();
|
||||
}
|
||||
ldp.append(" \\def\\subsectionmark##1{\\markright{");
|
||||
if ("name".equals(sChapterField2)) { ldp.append("##1"); }
|
||||
else if ("number".equals(sChapterField2) || "plain-number".equals(sChapterField1)) {
|
||||
ldp.append("\\thesubsection");
|
||||
}
|
||||
else { ldp.append("\\thesubsection\\ ##1"); }
|
||||
ldp.append("}{}}").nl();
|
||||
}
|
||||
// Page number (this is the only part of the page master used in each page style)
|
||||
if (pageLayout!=null) {
|
||||
String sNumFormat = pageLayout.getProperty(XMLString.STYLE_NUM_FORMAT);
|
||||
if (sNumFormat!=null) {
|
||||
ldp.append(" \\renewcommand\\thepage{")
|
||||
.append(ListStyleConverter.numFormat(sNumFormat))
|
||||
.append("{page}}").nl();
|
||||
}
|
||||
String sPageNumber = pageLayout.getProperty(XMLString.STYLE_FIRST_PAGE_NUMBER);
|
||||
if (sPageNumber!=null && !sPageNumber.equals("continue")) {
|
||||
ldp.append(" \\setcounter{page}{")
|
||||
.append(Integer.toString(Misc.getPosInteger(sPageNumber,0)))
|
||||
.append("}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
}
|
||||
if (!config.useFancyhdr()) {
|
||||
ldp.append("\\makeatother").nl();
|
||||
}
|
||||
}
|
||||
|
||||
// Get alignment of first paragraph in node
|
||||
private String getParAlignment(Node node) {
|
||||
String sAlign = "L";
|
||||
if (node!=null) {
|
||||
Element par = Misc.getChildByTagName(node,XMLString.TEXT_P);
|
||||
if (par!=null) {
|
||||
String sStyleName = Misc.getAttribute(par,XMLString.TEXT_STYLE_NAME);
|
||||
StyleWithProperties style = ofr.getParStyle(sStyleName);
|
||||
if (style!=null) {
|
||||
String s = style.getProperty(XMLString.FO_TEXT_ALIGN);
|
||||
if ("center".equals(s)) { sAlign = "C"; }
|
||||
else if ("end".equals(s)) { sAlign = "R"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
return sAlign;
|
||||
}
|
||||
|
||||
// Get border width from header/footer style
|
||||
private String getBorderWidth(PageLayout style, boolean bHeader) {
|
||||
if (style==null) { return "0pt"; }
|
||||
String sBorder;
|
||||
if (bHeader) {
|
||||
sBorder = style.getHeaderProperty(XMLString.FO_BORDER_BOTTOM);
|
||||
if (sBorder==null) {
|
||||
sBorder = style.getHeaderProperty(XMLString.FO_BORDER);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sBorder = style.getFooterProperty(XMLString.FO_BORDER_TOP);
|
||||
if (sBorder==null) {
|
||||
sBorder = style.getFooterProperty(XMLString.FO_BORDER);
|
||||
}
|
||||
}
|
||||
if (sBorder!=null && !sBorder.equals("none")) {
|
||||
return sBorder.substring(0,sBorder.indexOf(' '));
|
||||
}
|
||||
else {
|
||||
return "0pt";
|
||||
}
|
||||
}
|
||||
|
||||
private void traverseHeaderFooter(Element node, LaTeXDocumentPortion ldp, Context context) {
|
||||
if (node==null) { return; }
|
||||
// get first paragraph; all other content is ignored
|
||||
Element par = Misc.getChildByTagName(node,XMLString.TEXT_P);
|
||||
if (par==null) { return; }
|
||||
|
||||
String sStyleName = par.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
// Temp solution: Ignore hard formatting in header/footer (name clash problem)
|
||||
// only in package format. TODO: Find a better solution!
|
||||
StyleWithProperties style = ofr.getParStyle(sStyleName);
|
||||
if (style!=null && (!ofr.isPackageFormat() || !style.isAutomatic())) {
|
||||
palette.getCharSc().applyHardCharFormatting(style,ba);
|
||||
}
|
||||
|
||||
if (par.hasChildNodes()) {
|
||||
ldp.append(ba.getBefore());
|
||||
palette.getInlineCv().traverseInlineText(par,ldp,context);
|
||||
ldp.append(ba.getAfter());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: Reenable several geometries per document??
|
||||
private void convertPageMasterGeometry(LaTeXDocumentPortion pack, LaTeXDocumentPortion ldp) {
|
||||
if (config.pageFormatting()!=LaTeXConfig.CONVERT_ALL) { return; }
|
||||
if (mainPageLayout==null) { return; }
|
||||
|
||||
// Set global document options
|
||||
if ("mirrored".equals(mainPageLayout.getPageUsage())) {
|
||||
palette.addGlobalOption("twoside");
|
||||
}
|
||||
if (isTwocolumn()) {
|
||||
palette.addGlobalOption("twocolumn");
|
||||
}
|
||||
|
||||
// Collect all page geometry
|
||||
// 1. Page size
|
||||
String sPaperHeight = mainPageLayout.getAbsoluteProperty(XMLString.FO_PAGE_HEIGHT);
|
||||
String sPaperWidth = mainPageLayout.getAbsoluteProperty(XMLString.FO_PAGE_WIDTH);
|
||||
// 2. Margins
|
||||
String sMarginTop = mainPageLayout.getAbsoluteProperty(XMLString.FO_MARGIN_TOP);
|
||||
String sMarginBottom = mainPageLayout.getAbsoluteProperty(XMLString.FO_MARGIN_BOTTOM);
|
||||
String sMarginLeft = mainPageLayout.getAbsoluteProperty(XMLString.FO_MARGIN_LEFT);
|
||||
String sMarginRight = mainPageLayout.getAbsoluteProperty(XMLString.FO_MARGIN_RIGHT);
|
||||
// 3. Header+footer dimensions
|
||||
String sHeadHeight = "0cm";
|
||||
String sHeadSep = "0cm";
|
||||
String sFootHeight = "0cm";
|
||||
String sFootSep = "0cm";
|
||||
boolean bIncludeHead = false;
|
||||
boolean bIncludeFoot = false;
|
||||
// Look through all applied page layouts and use largest heights
|
||||
Enumeration masters = ofr.getMasterPages().getStylesEnumeration();
|
||||
while (masters.hasMoreElements()) {
|
||||
MasterPage master = (MasterPage) masters.nextElement();
|
||||
if (styleNames.containsName(getDisplayName(master.getName()))) {
|
||||
PageLayout layout = ofr.getPageLayout(master.getPageLayoutName());
|
||||
if (layout!=null) {
|
||||
if (layout.hasHeaderStyle()) {
|
||||
String sThisHeadHeight = layout.getHeaderProperty(XMLString.FO_MIN_HEIGHT);
|
||||
if (sThisHeadHeight!=null && Misc.isLessThan(sHeadHeight,sThisHeadHeight)) {
|
||||
sHeadHeight = sThisHeadHeight;
|
||||
}
|
||||
String sThisHeadSep = layout.getHeaderProperty(XMLString.FO_MARGIN_BOTTOM);
|
||||
if (sThisHeadSep!=null && Misc.isLessThan(sHeadSep,sThisHeadSep)) {
|
||||
sHeadSep = sThisHeadSep;
|
||||
}
|
||||
bIncludeHead = true;
|
||||
}
|
||||
if (layout.hasFooterStyle()) {
|
||||
String sThisFootHeight = layout.getFooterProperty(XMLString.FO_MIN_HEIGHT);
|
||||
if (sThisFootHeight!=null && Misc.isLessThan(sFootHeight,sThisFootHeight)) {
|
||||
sFootHeight = sThisFootHeight;
|
||||
}
|
||||
String sThisFootSep = layout.getFooterProperty(XMLString.FO_MARGIN_TOP);
|
||||
if (sThisFootSep!=null && Misc.isLessThan(sFootSep,sThisFootSep)) {
|
||||
sFootSep = sThisFootSep;
|
||||
}
|
||||
bIncludeFoot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Define 12pt as minimum height (the source may specify 0pt..)
|
||||
if (bIncludeHead && Misc.isLessThan(sHeadHeight,"12pt")) {
|
||||
sHeadHeight = "12pt";
|
||||
}
|
||||
if (bIncludeFoot && Misc.isLessThan(sFootHeight,"12pt")) {
|
||||
sFootHeight = "12pt";
|
||||
}
|
||||
|
||||
String sFootSkip = Misc.add(sFootHeight,sFootSep);
|
||||
|
||||
if (config.useGeometry()) {
|
||||
// Set up options for geometry.sty
|
||||
CSVList props = new CSVList(",");
|
||||
if (!standardPaperSize(sPaperWidth,sPaperHeight)) {
|
||||
props.addValue("paperwidth="+sPaperWidth);
|
||||
props.addValue("paperheight="+sPaperHeight);
|
||||
}
|
||||
props.addValue("top="+sMarginTop);
|
||||
props.addValue("bottom="+sMarginBottom);
|
||||
props.addValue("left="+sMarginLeft);
|
||||
props.addValue("right="+sMarginRight);
|
||||
if (bIncludeHead) {
|
||||
props.addValue("includehead");
|
||||
props.addValue("head="+sHeadHeight);
|
||||
props.addValue("headsep="+sHeadSep);
|
||||
}
|
||||
else {
|
||||
props.addValue("nohead");
|
||||
}
|
||||
if (bIncludeFoot) {
|
||||
props.addValue("includefoot");
|
||||
props.addValue("foot="+sFootHeight);
|
||||
props.addValue("footskip="+sFootSkip);
|
||||
}
|
||||
else {
|
||||
props.addValue("nofoot");
|
||||
}
|
||||
// Use the package
|
||||
pack.append("\\usepackage[").append(props.toString()).append("]{geometry}").nl();
|
||||
|
||||
}
|
||||
else {
|
||||
// Calculate text height and text width
|
||||
String sTextHeight = Misc.sub(sPaperHeight,sMarginTop);
|
||||
sTextHeight = Misc.sub(sTextHeight,sHeadHeight);
|
||||
sTextHeight = Misc.sub(sTextHeight,sHeadSep);
|
||||
sTextHeight = Misc.sub(sTextHeight,sFootSkip);
|
||||
sTextHeight = Misc.sub(sTextHeight,sMarginBottom);
|
||||
String sTextWidth = Misc.sub(sPaperWidth,sMarginLeft);
|
||||
sTextWidth = Misc.sub(sTextWidth,sMarginRight);
|
||||
|
||||
ldp.append("% Page layout (geometry)").nl();
|
||||
|
||||
// Page dimensions
|
||||
if (!standardPaperSize(sPaperWidth,sPaperHeight)) {
|
||||
ldp.append("\\setlength\\paperwidth{").append(sPaperWidth).append("}").nl()
|
||||
.append("\\setlength\\paperheight{").append(sPaperHeight).append("}").nl();
|
||||
}
|
||||
|
||||
// PDF page dimensions, only if hyperref.sty is not loaded
|
||||
if (config.getBackend()==LaTeXConfig.PDFTEX && !config.useHyperref()) {
|
||||
ldp.append("\\setlength\\pdfpagewidth{").append(sPaperWidth).append("}").nl()
|
||||
.append("\\setlength\\pdfpageheight{").append(sPaperHeight).append("}").nl();
|
||||
}
|
||||
|
||||
// Page starts in upper left corner of paper!!
|
||||
ldp.append("\\setlength\\voffset{-1in}").nl()
|
||||
.append("\\setlength\\hoffset{-1in}").nl();
|
||||
|
||||
// Margins
|
||||
ldp.append("\\setlength\\topmargin{").append(sMarginTop).append("}").nl()
|
||||
.append("\\setlength\\oddsidemargin{").append(sMarginLeft).append("}").nl();
|
||||
// Left margin for even (left) pages; only for mirrored page master
|
||||
if ("mirrored".equals(mainPageLayout.getPageUsage())) {
|
||||
ldp.append("\\setlength\\evensidemargin{").append(sMarginRight).append("}").nl();
|
||||
}
|
||||
|
||||
// Text size (sets bottom and right margins indirectly)
|
||||
ldp.append("\\setlength\\textheight{").append(sTextHeight).append("}").nl();
|
||||
ldp.append("\\setlength\\textwidth{").append(sTextWidth).append("}").nl();
|
||||
|
||||
// Header and footer
|
||||
ldp.append("\\setlength\\footskip{").append(sFootSkip).append("}").nl();
|
||||
ldp.append("\\setlength\\headheight{").append(sHeadHeight).append("}").nl();
|
||||
ldp.append("\\setlength\\headsep{").append(sHeadSep).append("}").nl();
|
||||
}
|
||||
|
||||
// Footnote rule
|
||||
// TODO: Support alignment.
|
||||
String sAdjustment = mainPageLayout.getFootnoteProperty(XMLString.STYLE_ADJUSTMENT);
|
||||
String sBefore = mainPageLayout.getFootnoteProperty(XMLString.STYLE_DISTANCE_BEFORE_SEP);
|
||||
if (sBefore==null) { sBefore = "1mm"; }
|
||||
String sAfter = mainPageLayout.getFootnoteProperty(XMLString.STYLE_DISTANCE_AFTER_SEP);
|
||||
if (sAfter==null) { sAfter = "1mm"; }
|
||||
String sHeight = mainPageLayout.getFootnoteProperty(XMLString.STYLE_WIDTH);
|
||||
if (sHeight==null) { sHeight = "0.2mm"; }
|
||||
String sWidth = mainPageLayout.getFootnoteProperty(XMLString.STYLE_REL_WIDTH);
|
||||
if (sWidth==null) { sWidth = "25%"; }
|
||||
sWidth=Float.toString(Misc.getFloat(sWidth.substring(0,sWidth.length()-1),1)/100);
|
||||
BeforeAfter baColor = new BeforeAfter();
|
||||
String sColor = mainPageLayout.getFootnoteProperty(XMLString.STYLE_COLOR);
|
||||
palette.getColorCv().applyColor(sColor,false,baColor,new Context());
|
||||
|
||||
String sSkipFootins = Misc.add(sBefore,sHeight);
|
||||
|
||||
ldp.append("% Footnote rule").nl()
|
||||
.append("\\setlength{\\skip\\footins}{").append(sSkipFootins).append("}").nl()
|
||||
.append("\\renewcommand\\footnoterule{\\vspace*{-").append(sHeight)
|
||||
.append("}");
|
||||
if ("right".equals(sAdjustment)) {
|
||||
ldp.append("\\setlength\\leftskip{0pt plus 1fil}\\setlength\\rightskip{0pt}");
|
||||
}
|
||||
else if ("center".equals(sAdjustment)) {
|
||||
ldp.append("\\setlength\\leftskip{0pt plus 1fil}\\setlength\\rightskip{0pt plus 1fil}");
|
||||
}
|
||||
else { // default left
|
||||
ldp.append("\\setlength\\leftskip{0pt}\\setlength\\rightskip{0pt plus 1fil}");
|
||||
}
|
||||
ldp.append("\\noindent")
|
||||
.append(baColor.getBefore()).append("\\rule{").append(sWidth)
|
||||
.append("\\columnwidth}{").append(sHeight).append("}")
|
||||
.append(baColor.getAfter())
|
||||
.append("\\vspace*{").append(sAfter).append("}}").nl();
|
||||
}
|
||||
|
||||
private boolean standardPaperSize(String sWidth, String sHeight) {
|
||||
if (standardPaperSize1(sWidth,sHeight)) {
|
||||
return true;
|
||||
}
|
||||
else if (standardPaperSize1(sHeight,sWidth)) {
|
||||
palette.addGlobalOption("landscape");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean standardPaperSize1(String sWidth, String sHeight) {
|
||||
// The list of known paper sizes in LaTeX's standard classes is rather short
|
||||
if (compare(sWidth, "210mm", "0.5mm") && compare(sHeight, "297mm", "0.5mm")) {
|
||||
palette.addGlobalOption("a4paper");
|
||||
return true;
|
||||
}
|
||||
else if (compare(sWidth, "148mm", "0.5mm") && compare(sHeight, "210mm", "0.5mm")) {
|
||||
palette.addGlobalOption("a5paper");
|
||||
return true;
|
||||
}
|
||||
else if (compare(sWidth, "176mm", "0.5mm") && compare(sHeight, "250mm", "0.5mm")) {
|
||||
palette.addGlobalOption("b5paper");
|
||||
return true;
|
||||
}
|
||||
else if (compare(sWidth, "8.5in", "0.02in") && compare(sHeight, "11in", "0.02in")) {
|
||||
palette.addGlobalOption("letterpaper");
|
||||
return true;
|
||||
}
|
||||
else if (compare(sWidth, "8.5in", "0.02in") && compare(sHeight, "14in", "0.02in")) {
|
||||
palette.addGlobalOption("legalpaper");
|
||||
return true;
|
||||
}
|
||||
else if (compare(sWidth, "7.25in", "0.02in") && compare(sHeight, "10.5in", "0.02in")) {
|
||||
palette.addGlobalOption("executivepaper");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean compare(String sLength1, String sLength2, String sTolerance) {
|
||||
return Misc.isLessThan(Misc.abs(Misc.sub(sLength1,sLength2)),sTolerance);
|
||||
}
|
||||
|
||||
/* Helper: Get display name, or original name if it doesn't exist */
|
||||
private String getDisplayName(String sName) {
|
||||
String sDisplayName = ofr.getMasterPages().getDisplayName(sName);
|
||||
return sDisplayName!=null ? sDisplayName : sName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
546
source/java/writer2latex/latex/ParConverter.java
Normal file
546
source/java/writer2latex/latex/ParConverter.java
Normal file
|
@ -0,0 +1,546 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ParConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
//import java.util.Hashtable;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
//import org.w3c.dom.Node;
|
||||
//import org.w3c.dom.NodeList;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
//import writer2latex.latex.util.HeadingMap;
|
||||
import writer2latex.latex.util.StyleMap;
|
||||
|
||||
/* <p>This class converts OpenDocument paragraphs (<code>text:p</code>) and
|
||||
* paragraph styles/formatting into LaTeX</p>
|
||||
* <p>Export of formatting depends on the option "formatting":</p>
|
||||
* <ul>
|
||||
* <li><code>ignore_all</code>
|
||||
* <li><code>ignore_most</code>
|
||||
* <li><code>convert_basic</code>
|
||||
* <li><code>convert_most</code>
|
||||
* <li><code>convert_all</code>
|
||||
* </ul>
|
||||
* <p>TODO: Captions and {foot|end}notes should also use this class
|
||||
*/
|
||||
public class ParConverter extends StyleConverter {
|
||||
|
||||
private boolean bNeedArrayBslash = false;
|
||||
|
||||
/** <p>Constructs a new <code>ParConverter</code>.</p>
|
||||
*/
|
||||
public ParConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bNeedArrayBslash) {
|
||||
// centering and raggedright redefines \\, fix this
|
||||
// Note: aviods nameclash with tabularx (arraybackslash)
|
||||
// TODO: Should perhaps choose to load tabularx instead?
|
||||
decl.append("\\makeatletter").nl()
|
||||
.append("\\newcommand\\arraybslash{\\let\\\\\\@arraycr}").nl()
|
||||
.append("\\makeatother").nl();
|
||||
}
|
||||
|
||||
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) {
|
||||
// We typeset with \raggedbottom since OOo doesn't use rubber lengths
|
||||
// TODO: Maybe turn vertical spacing from OOo into rubber lengths?
|
||||
decl.append("\\raggedbottom").nl();
|
||||
}
|
||||
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) {
|
||||
decl.append("% Paragraph styles").nl();
|
||||
// First default paragraph style
|
||||
palette.getCharSc().applyDefaultFont(ofr.getDefaultParStyle(),decl);
|
||||
super.appendDeclarations(pack,decl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Process a text:p tag</p>
|
||||
* @param node The text:h element node containing the heading
|
||||
* @param ldp The <code>LaTeXDocumentPortion</code> to add LaTeX code to
|
||||
* @param oc The current context
|
||||
* @param bLastInBlock If this is true, the paragraph is the
|
||||
* last one in a block, and we need no trailing blank line (eg. right before
|
||||
* \end{enumerate}).
|
||||
*/
|
||||
public void handleParagraph(Element node, LaTeXDocumentPortion ldp, Context oc, boolean bLastInBlock) {
|
||||
if (palette.getMathmlCv().handleDisplayEquation(node,ldp)) { return; }
|
||||
|
||||
// Get the style name for this paragraph
|
||||
String sStyleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
String sDisplayName = ofr.getParStyles().getDisplayName(sStyleName);
|
||||
|
||||
|
||||
// Check for strict handling of styles
|
||||
if (config.otherStyles()!=LaTeXConfig.ACCEPT && !config.getParStyleMap().contains(sDisplayName)) {
|
||||
if (config.otherStyles()==LaTeXConfig.WARNING) {
|
||||
System.err.println("Warning: A paragraph with style "+sDisplayName+" was ignored");
|
||||
}
|
||||
else if (config.otherStyles()==LaTeXConfig.ERROR) {
|
||||
ldp.append("% Error in source document: A paragraph with style ")
|
||||
.append(palette.getI18n().convert(sDisplayName,false,oc.getLang()))
|
||||
.append(" was ignored").nl();
|
||||
}
|
||||
// Ignore this paragraph:
|
||||
return;
|
||||
}
|
||||
|
||||
// Empty paragraphs are often (mis)used to achieve vertical spacing in WYSIWYG
|
||||
// word processors. Hence we translate an empty paragraph to \bigskip.
|
||||
// This also solves the problem that LaTeX ignores empty paragraphs, Writer doesn't.
|
||||
// In a well-structured document, an empty paragraph is probably a mistake,
|
||||
// hence the configuration can specify that it should be ignored.
|
||||
// Note: Don't use \bigskip in tables (this can lead to strange results)
|
||||
if (OfficeReader.isWhitespaceContent(node)) {
|
||||
// Always add page break; other formatting is ignored
|
||||
BeforeAfter baPage = new BeforeAfter();
|
||||
StyleWithProperties style = ofr.getParStyle(sStyleName);
|
||||
palette.getPageSc().applyPageBreak(style,true,baPage);
|
||||
if (!oc.isInTable()) { ldp.append(baPage.getBefore()); }
|
||||
if (!config.ignoreEmptyParagraphs()) {
|
||||
if (!oc.isInTable()) {
|
||||
ldp.nl().append("\\bigskip").nl();
|
||||
}
|
||||
else {
|
||||
ldp.append("~").nl();
|
||||
}
|
||||
if (!bLastInBlock) { ldp.nl(); }
|
||||
}
|
||||
if (!oc.isInTable()) { ldp.append(baPage.getAfter()); }
|
||||
return;
|
||||
}
|
||||
|
||||
Context ic = (Context) oc.clone();
|
||||
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getParStyle(sStyleName)));
|
||||
|
||||
// Apply the style
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
if (oc.isInTable()) {
|
||||
applyCellParStyle(sStyleName,ba,ic,OfficeReader.getCharacterCount(node)==0,bLastInBlock);
|
||||
}
|
||||
else {
|
||||
applyParStyle(sStyleName,ba,ic,OfficeReader.getCharacterCount(node)==0);
|
||||
}
|
||||
|
||||
// Do conversion
|
||||
ldp.append(ba.getBefore());
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,ic);
|
||||
ldp.append(ba.getAfter());
|
||||
// Add a blank line except within verbatim and last in a block:
|
||||
if (!bLastInBlock && !ic.isVerbatim() && !ic.isInSimpleTable()) { ldp.nl(); }
|
||||
|
||||
// Flush any pending index marks, reference marks and floating frames
|
||||
palette.getFieldCv().flushReferenceMarks(ldp,oc);
|
||||
palette.getIndexCv().flushIndexMarks(ldp,oc);
|
||||
palette.getDrawCv().flushFloatingFrames(ldp,oc);
|
||||
|
||||
// pop the font name
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
|
||||
private void applyCellParStyle(String sName, BeforeAfter ba, Context context, boolean bNoTextPar, boolean bLastInBlock) {
|
||||
// Paragraph formatting for paragraphs within table cells
|
||||
// We always use simple par styles here
|
||||
|
||||
// Add newline if *between* paragraphs
|
||||
if (!bLastInBlock) { ba.add("","\n"); }
|
||||
|
||||
if (context.isInSimpleTable()) {
|
||||
if (config.formatting()!=LaTeXConfig.IGNORE_ALL) {
|
||||
// only character formatting!
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style!=null) {
|
||||
palette.getI18n().applyLanguage(style,true,true,ba);
|
||||
palette.getCharSc().applyFont(style,true,true,ba,context);
|
||||
if (ba.getBefore().length()>0) { ba.add(" ",""); }
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bNoTextPar && (config.formatting()==LaTeXConfig.CONVERT_BASIC || config.formatting()==LaTeXConfig.IGNORE_MOST) ) {
|
||||
// only alignment!
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style!=null) {
|
||||
// Apply hard formatting attributes
|
||||
// Note: Left justified text is exported as full justified text!
|
||||
palette.getPageSc().applyPageBreak(style,false,ba);
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,true);
|
||||
if (bLastInBlock && context.isInLastTableColumn()) { // no grouping needed, but need to fix problem with \\
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering\\arraybslash ",""); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft\\arraybslash ",""); }
|
||||
bNeedArrayBslash = true;
|
||||
}
|
||||
else if (bLastInBlock) { // no grouping needed
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering ",""); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft ",""); }
|
||||
}
|
||||
else {
|
||||
if ("center".equals(sTextAlign)) { ba.add("{\\centering ","\\par}"); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("{\\raggedleft ","\\par}"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Export character formatting + alignment only
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
|
||||
// Apply hard formatting attributes
|
||||
// Note: Left justified text is exported as full justified text!
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style!=null) {
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,true);
|
||||
if (bLastInBlock && context.isInLastTableColumn()) { // no grouping needed, but need to fix problem with \\
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering\\arraybslash ",""); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft\\arraybslash ",""); }
|
||||
bNeedArrayBslash = true;
|
||||
}
|
||||
else if (bLastInBlock) { // no \par needed
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering ",""); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft ",""); }
|
||||
}
|
||||
else {
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering ","\\par"); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft ","\\par"); }
|
||||
}
|
||||
palette.getI18n().applyLanguage(style,true,true,baText);
|
||||
palette.getCharSc().applyFont(style,true,true,baText,context);
|
||||
}
|
||||
|
||||
// Assemble the bits. If there is any hard character formatting
|
||||
// or alignment we must group the contents.
|
||||
if (!baText.isEmpty() && !bLastInBlock) { ba.add("{","}"); }
|
||||
ba.add(baText.getBefore(),baText.getAfter());
|
||||
if (baText.getBefore().length()>0) { ba.add(" ",""); }
|
||||
}
|
||||
|
||||
// Update context
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style==null) { return; }
|
||||
context.updateFormattingFromStyle(style);
|
||||
context.setVerbatim(styleMap.getVerbatim(sName));
|
||||
}
|
||||
|
||||
|
||||
/** <p>Use a paragraph style in LaTeX.</p>
|
||||
* @param <code>sName</code> the name of the text style
|
||||
* @param <code>ba</code> a <code>BeforeAfter</code> to put code into
|
||||
* @param <code>context</code> the current context. This method will use and update the formatting context
|
||||
* @param <code>bNoTextPar</code> true if this paragraph has no text content (hence character formatting is not needed)
|
||||
*/
|
||||
private void applyParStyle(String sName, BeforeAfter ba, Context context, boolean bNoTextPar) {
|
||||
applyParStyle(sName,ba,context,bNoTextPar,true);
|
||||
}
|
||||
|
||||
private void applyParStyle(String sName, BeforeAfter ba, Context context, boolean bNoTextPar, boolean bBreakInside) {
|
||||
// No style specified?
|
||||
if (sName==null) { return; }
|
||||
|
||||
if (context.isInSimpleTable()) {
|
||||
if (config.formatting()!=LaTeXConfig.IGNORE_ALL) {
|
||||
// only character formatting!
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style!=null) {
|
||||
palette.getI18n().applyLanguage(style,true,true,ba);
|
||||
palette.getCharSc().applyFont(style,true,true,ba,context);
|
||||
if (ba.getBefore().length()>0) { ba.add(" ",""); }
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bNoTextPar && (config.formatting()==LaTeXConfig.CONVERT_BASIC || config.formatting()==LaTeXConfig.IGNORE_MOST) ) {
|
||||
// Always end with a line break
|
||||
ba.add("","\n");
|
||||
// only alignment!
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style!=null) {
|
||||
// Apply hard formatting attributes
|
||||
// Note: Left justified text is exported as full justified text!
|
||||
palette.getPageSc().applyPageBreak(style,false,ba);
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,true);
|
||||
if ("center".equals(sTextAlign)) { ba.add("{\\centering ","\\par}"); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("{\\raggedleft ","\\par}"); }
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Always end with a line break
|
||||
ba.add("","\n");
|
||||
// Apply the style
|
||||
if (!styleMap.contains(sName)) { createParStyle(sName); }
|
||||
String sBefore = styleMap.getBefore(sName);
|
||||
String sAfter = styleMap.getAfter(sName);
|
||||
ba.add(sBefore,sAfter);
|
||||
// Add line breaks inside?
|
||||
if (bBreakInside && styleMap.getLineBreak(sName)) {
|
||||
if (sBefore.length()>0) { ba.add("\n",""); }
|
||||
if (sAfter.length()>0 && !"}".equals(sAfter)) { ba.add("","\n"); }
|
||||
}
|
||||
}
|
||||
|
||||
// Update context
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style==null) { return; }
|
||||
context.updateFormattingFromStyle(style);
|
||||
context.setVerbatim(styleMap.getVerbatim(sName));
|
||||
}
|
||||
|
||||
/** <p>Convert a paragraph style to LaTeX. </p>
|
||||
* <p>A soft style is declared in <code>styleDeclarations</code> as
|
||||
* <code>\newenvironment...</code></p>
|
||||
* <p>A hard style is used by applying LaTeX code directly</p>
|
||||
* @param <code>sName</code> the OOo name of the style
|
||||
*/
|
||||
private void createParStyle(String sName) {
|
||||
// A paragraph style should always be created relative to main context
|
||||
Context context = (Context) palette.getMainContext().clone();
|
||||
// The style may already be declared in the configuration:
|
||||
String sDisplayName = ofr.getParStyles().getDisplayName(sName);
|
||||
StyleMap sm = config.getParStyleMap();
|
||||
if (sm.contains(sDisplayName)) {
|
||||
styleMap.put(sName,sm.getBefore(sDisplayName),sm.getAfter(sDisplayName),
|
||||
sm.getLineBreak(sDisplayName),sm.getVerbatim(sDisplayName));
|
||||
return;
|
||||
}
|
||||
// Does the style exist?
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style==null) {
|
||||
styleMap.put(sName,"","");
|
||||
return;
|
||||
}
|
||||
// Convert the style!
|
||||
switch (config.formatting()) {
|
||||
case LaTeXConfig.CONVERT_MOST:
|
||||
if (style.isAutomatic()) {
|
||||
createAutomaticParStyle(style,context);
|
||||
return;
|
||||
}
|
||||
case LaTeXConfig.CONVERT_ALL:
|
||||
createSoftParStyle(style,context);
|
||||
return;
|
||||
case LaTeXConfig.CONVERT_BASIC:
|
||||
case LaTeXConfig.IGNORE_MOST:
|
||||
createSimpleParStyle(style,context);
|
||||
return;
|
||||
case LaTeXConfig.IGNORE_ALL:
|
||||
default:
|
||||
styleMap.put(sName,"","");
|
||||
}
|
||||
}
|
||||
|
||||
private void createAutomaticParStyle(StyleWithProperties style, Context context) {
|
||||
// Hard paragraph formatting from this style should be ignored
|
||||
// (because the user wants to ignore hard paragraph formatting
|
||||
// or there is a style map for the parent.)
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
BeforeAfter baPar = new BeforeAfter();
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
|
||||
// Apply paragraph formatting from parent
|
||||
// If parent is verbatim, this is all
|
||||
String sParentName = style.getParentName();
|
||||
if (styleMap.getVerbatim(sParentName)) {
|
||||
styleMap.put(style.getName(),styleMap.getBefore(sParentName),styleMap.getAfter(sParentName),
|
||||
styleMap.getLineBreak(sParentName),styleMap.getVerbatim(sParentName));
|
||||
return;
|
||||
}
|
||||
applyParStyle(sParentName,baPar,context,false,false);
|
||||
|
||||
// Apply hard formatting properties:
|
||||
palette.getPageSc().applyPageBreak(style,false,ba);
|
||||
palette.getI18n().applyLanguage(style,true,false,baText);
|
||||
palette.getCharSc().applyFont(style,true,false,baText,context);
|
||||
|
||||
// Assemble the bits. If there is any hard character formatting
|
||||
// we must group the contents.
|
||||
if (baPar.isEmpty() && !baText.isEmpty()) { ba.add("{","}"); }
|
||||
else { ba.add(baPar.getBefore(),baPar.getAfter()); }
|
||||
ba.add(baText.getBefore(),baText.getAfter());
|
||||
boolean bLineBreak = styleMap.getLineBreak(sParentName);
|
||||
if (!bLineBreak && !baText.isEmpty()) { ba.add(" ",""); }
|
||||
styleMap.put(style.getName(),ba.getBefore(),ba.getAfter(),bLineBreak,false);
|
||||
}
|
||||
|
||||
private void createSimpleParStyle(StyleWithProperties style, Context context) {
|
||||
// Export character formatting + alignment only
|
||||
if (style.isAutomatic() && config.getParStyleMap().contains(ofr.getParStyles().getDisplayName(style.getParentName()))) {
|
||||
createAutomaticParStyle(style,context);
|
||||
return;
|
||||
}
|
||||
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
|
||||
// Apply hard formatting attributes
|
||||
// Note: Left justified text is exported as full justified text!
|
||||
palette.getPageSc().applyPageBreak(style,false,ba);
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,true);
|
||||
if ("center".equals(sTextAlign)) { baText.add("\\centering","\\par"); }
|
||||
else if ("end".equals(sTextAlign)) { baText.add("\\raggedleft","\\par"); }
|
||||
palette.getI18n().applyLanguage(style,true,true,baText);
|
||||
palette.getCharSc().applyFont(style,true,true,baText,context);
|
||||
|
||||
// Assemble the bits. If there is any hard character formatting
|
||||
// or alignment we must group the contents.
|
||||
if (!baText.isEmpty()) { ba.add("{","}"); }
|
||||
ba.add(baText.getBefore(),baText.getAfter());
|
||||
styleMap.put(style.getName(),ba.getBefore(),ba.getAfter());
|
||||
}
|
||||
|
||||
private void createSoftParStyle(StyleWithProperties style, Context context) {
|
||||
// This style should be converted to an enviroment, except if
|
||||
// it's automatic and there is a config style map for the parent
|
||||
if (style.isAutomatic() && config.getParStyleMap().contains(ofr.getParStyles().getDisplayName(style.getParentName()))) {
|
||||
createAutomaticParStyle(style,context);
|
||||
}
|
||||
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
applyParProperties(style,ba);
|
||||
ba.add("\\writerlistparindent\\writerlistleftskip","");
|
||||
palette.getI18n().applyLanguage(style,true,true,ba);
|
||||
ba.add("\\leavevmode","");
|
||||
palette.getCharSc().applyNormalFont(ba);
|
||||
palette.getCharSc().applyFont(style,true,true,ba,context);
|
||||
ba.add("\\writerlistlabel","");
|
||||
ba.add("\\ignorespaces","");
|
||||
// Declare the paragraph style (\newenvironment)
|
||||
String sTeXName = "style" + styleNames.getExportName(style.getDisplayName());
|
||||
styleMap.put(style.getName(),"\\begin{"+sTeXName+"}","\\end{"+sTeXName+"}");
|
||||
declarations.append("\\newenvironment{").append(sTeXName)
|
||||
.append("}{").append(ba.getBefore()).append("}{")
|
||||
.append(ba.getAfter()).append("}").nl();
|
||||
}
|
||||
|
||||
// Remaining methods are private helpers
|
||||
|
||||
/** <p>Apply line spacing from a style.</p>
|
||||
* @param <code>style</code> the paragraph style to use
|
||||
* @param <code>ba</code> a <code>BeforeAfter</code> to put code into
|
||||
*/
|
||||
private void applyLineSpacing(StyleWithProperties style, BeforeAfter ba) {
|
||||
if (style==null) { return; }
|
||||
String sLineHeight = style.getProperty(XMLString.FO_LINE_HEIGHT);
|
||||
if (sLineHeight==null || !sLineHeight.endsWith("%")) { return; }
|
||||
float fPercent=Misc.getFloat(sLineHeight.substring(0,sLineHeight.length()-1),100);
|
||||
// Do not allow less that 120% (LaTeX default)
|
||||
if (fPercent<120) { fPercent = 120; }
|
||||
ba.add("\\renewcommand\\baselinestretch{"+fPercent/120+"}","");
|
||||
}
|
||||
|
||||
/** <p>Helper: Create a horizontal border. Currently unused</p>
|
||||
*/
|
||||
/*private String createBorder(String sLeft, String sRight, String sTop,
|
||||
String sHeight, String sColor) {
|
||||
BeforeAfter baColor = new BeforeAfter();
|
||||
palette.getColorCv().applyColor(sColor,false,baColor, new Context());
|
||||
return "{\\setlength\\parindent{0pt}\\setlength\\leftskip{" + sLeft + "}"
|
||||
+ "\\setlength\\baselineskip{0pt}\\setlength\\parskip{" + sHeight + "}"
|
||||
+ baColor.getBefore()
|
||||
+ "\\rule{\\textwidth-" + sLeft + "-" + sRight + "}{" + sHeight + "}"
|
||||
+ baColor.getAfter()
|
||||
+ "\\par}";
|
||||
}*/
|
||||
|
||||
/** <p>Apply margin+alignment properties from a style.</p>
|
||||
* @param <code>style</code> the paragraph style to use
|
||||
* @param <code>ba</code> a <code>BeforeAfter</code> to put code into
|
||||
*/
|
||||
private void applyMargins(StyleWithProperties style, BeforeAfter ba) {
|
||||
// Read padding/margin/indentation properties:
|
||||
//String sPaddingTop = style.getAbsoluteLength(XMLString.FO_PADDING_TOP);
|
||||
//String sPaddingBottom = style.getAbsoluteLength(XMLString.FO_PADDING_BOTTOM);
|
||||
//String sPaddingLeft = style.getAbsoluteLength(XMLString.FO_PADDING_LEFT);
|
||||
//String sPaddingRight = style.getAbsoluteLength(XMLString.FO_PADDING_RIGHT);
|
||||
String sMarginTop = style.getAbsoluteLength(XMLString.FO_MARGIN_TOP);
|
||||
String sMarginBottom = style.getAbsoluteLength(XMLString.FO_MARGIN_BOTTOM);
|
||||
String sMarginLeft = style.getAbsoluteLength(XMLString.FO_MARGIN_LEFT);
|
||||
String sMarginRight = style.getAbsoluteLength(XMLString.FO_MARGIN_RIGHT);
|
||||
String sTextIndent;
|
||||
if ("true".equals(style.getProperty(XMLString.STYLE_AUTO_TEXT_INDENT))) {
|
||||
sTextIndent = "2em";
|
||||
}
|
||||
else {
|
||||
sTextIndent = style.getAbsoluteLength(XMLString.FO_TEXT_INDENT);
|
||||
}
|
||||
// Read alignment properties:
|
||||
boolean bRaggedLeft = false; // add 1fil to \leftskip
|
||||
boolean bRaggedRight = false; // add 1fil to \rightskip
|
||||
boolean bParFill = false; // add 1fil to \parfillskip
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN);
|
||||
if ("center".equals(sTextAlign)) {
|
||||
bRaggedLeft = true; bRaggedRight = true; // centered paragraph
|
||||
}
|
||||
else if ("start".equals(sTextAlign)) {
|
||||
bRaggedRight = true; bParFill = true; // left aligned paragraph
|
||||
}
|
||||
else if ("end".equals(sTextAlign)) {
|
||||
bRaggedLeft = true; // right aligned paragraph
|
||||
}
|
||||
else if (!"justify".equals(style.getProperty(XMLString.FO_TEXT_ALIGN_LAST))) {
|
||||
bParFill = true; // justified paragraph with ragged last line
|
||||
}
|
||||
// Create formatting:
|
||||
String sRubberMarginTop = Misc.multiply("10%",sMarginTop);
|
||||
if (Misc.length2px(sRubberMarginTop).equals("0")) { sRubberMarginTop="1pt"; }
|
||||
String sRubberMarginBottom = Misc.multiply("10%",sMarginBottom);
|
||||
if (Misc.length2px(sRubberMarginBottom).equals("0")) { sRubberMarginBottom="1pt"; }
|
||||
ba.add("\\setlength\\leftskip{"+sMarginLeft+(bRaggedLeft?" plus 1fil":"")+"}","");
|
||||
ba.add("\\setlength\\rightskip{"+sMarginRight+(bRaggedRight?" plus 1fil":"")+"}","");
|
||||
ba.add("\\setlength\\parindent{"+sTextIndent+"}","");
|
||||
ba.add("\\setlength\\parfillskip{"+(bParFill?"0pt plus 1fil":"0pt")+"}","");
|
||||
ba.add("\\setlength\\parskip{"+sMarginTop+" plus "+sRubberMarginTop+"}",
|
||||
"\\unskip\\vspace{"+sMarginBottom+" plus "+sRubberMarginBottom+"}");
|
||||
}
|
||||
|
||||
public void applyAlignment(StyleWithProperties style, boolean bIsSimple, boolean bInherit, BeforeAfter ba) {
|
||||
if (bIsSimple || style==null) { return; }
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,bInherit);
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering",""); }
|
||||
else if ("start".equals(sTextAlign)) { ba.add("\\raggedright",""); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft",""); }
|
||||
}
|
||||
|
||||
|
||||
/** <p>Apply all paragraph properties.</p>
|
||||
* @param <code>style</code> the paragraph style to use
|
||||
* @param <code>ba</code> a <code>BeforeAfter</code> to put code into
|
||||
*/
|
||||
private void applyParProperties(StyleWithProperties style, BeforeAfter ba) {
|
||||
palette.getPageSc().applyPageBreak(style,true,ba);
|
||||
ba.add("","\\par");
|
||||
applyLineSpacing(style,ba);
|
||||
applyMargins(style,ba);
|
||||
}
|
||||
|
||||
}
|
135
source/java/writer2latex/latex/SectionConverter.java
Normal file
135
source/java/writer2latex/latex/SectionConverter.java
Normal file
|
@ -0,0 +1,135 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* SectionConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.i18n.ClassicI18n;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/** <p>This class creates LaTeX code from OOo sections.
|
||||
* <p>Sections are converted to multicols environments using <code>multicol.sty</code>
|
||||
*/
|
||||
public class SectionConverter extends ConverterHelper {
|
||||
|
||||
// Do we need multicols.sty?
|
||||
private boolean bNeedMulticol = false;
|
||||
|
||||
// Filenames for external sections
|
||||
private ExportNameCollection fileNames = new ExportNameCollection(true);
|
||||
|
||||
/** <p>Constructs a new <code>SectionStyleConverter</code>.</p>
|
||||
*/
|
||||
public SectionConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bNeedMulticol) { pack.append("\\usepackage{multicol}").nl(); }
|
||||
}
|
||||
|
||||
/** <p> Process a section (text:section tag)</p>
|
||||
* @param node The element containing the section
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleSection(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// We may need a hyperlink target, add this first
|
||||
palette.getFieldCv().addTarget(node,"|region",ldp);
|
||||
|
||||
// Create new document, if desired
|
||||
String sFileName = null;
|
||||
Element source = Misc.getChildByTagName(node,XMLString.TEXT_SECTION_SOURCE);
|
||||
if (config.splitLinkedSections() && source!=null) {
|
||||
sFileName = fileNames.getExportName(Misc.removeExtension(Misc.urlDecode(source.getAttribute(XMLString.XLINK_HREF))));
|
||||
}
|
||||
else if (config.splitToplevelSections() && isToplevel(node)) {
|
||||
//sFileName = fileNames.getExportName(palette.getOutFileName()+node.getAttribute(XMLString.TEXT_NAME));
|
||||
sFileName = fileNames.getExportName(node.getAttribute(XMLString.TEXT_NAME));
|
||||
}
|
||||
|
||||
LaTeXDocumentPortion sectionLdp = ldp;
|
||||
if (sFileName!=null) {
|
||||
LaTeXDocument newDoc = new LaTeXDocument(sFileName,config.getWrapLinesAfter());
|
||||
if (config.getBackend()!=LaTeXConfig.XETEX) {
|
||||
newDoc.setEncoding(ClassicI18n.writeJavaEncoding(config.getInputencoding()));
|
||||
}
|
||||
else {
|
||||
newDoc.setEncoding("UTF-8");
|
||||
}
|
||||
palette.addDocument(newDoc);
|
||||
sectionLdp = newDoc.getContents();
|
||||
}
|
||||
|
||||
// Apply the style
|
||||
String sStyleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
Context ic = (Context) oc.clone();
|
||||
applySectionStyle(sStyleName,ba,ic);
|
||||
|
||||
// Do conversion
|
||||
ldp.append(ba.getBefore());
|
||||
if (sFileName!=null) {
|
||||
ldp.append("\\input{").append(sFileName).append("}").nl();
|
||||
}
|
||||
palette.getBlockCv().traverseBlockText(node,sectionLdp,ic);
|
||||
if (sectionLdp!=ldp) { sectionLdp.append("\\endinput").nl(); }
|
||||
ldp.append(ba.getAfter());
|
||||
}
|
||||
|
||||
// Create multicols environment as needed
|
||||
private void applySectionStyle(String sStyleName, BeforeAfter ba, Context context) {
|
||||
StyleWithProperties style = ofr.getSectionStyle(sStyleName);
|
||||
// Don't nest multicols and require at least 2 columns
|
||||
if (context.isInMulticols() || style==null || style.getColCount()<2) { return; }
|
||||
int nCols = style.getColCount();
|
||||
bNeedMulticol = true;
|
||||
context.setInMulticols(true);
|
||||
ba.add("\\begin{multicols}{"+(nCols>10 ? 10 : nCols)+"}\n", "\\end{multicols}\n");
|
||||
}
|
||||
|
||||
// return true if this node is *not* contained in a text:section element
|
||||
private boolean isToplevel(Node node) {
|
||||
Node parent = node.getParentNode();
|
||||
if (XMLString.TEXT_SECTION.equals(parent.getNodeName())) {
|
||||
return false;
|
||||
}
|
||||
else if (XMLString.OFFICE_BODY.equals(parent.getNodeName())) {
|
||||
return true;
|
||||
}
|
||||
return isToplevel(parent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
1618
source/java/writer2latex/latex/StarMathConverter.java
Normal file
1618
source/java/writer2latex/latex/StarMathConverter.java
Normal file
File diff suppressed because it is too large
Load diff
51
source/java/writer2latex/latex/StyleConverter.java
Normal file
51
source/java/writer2latex/latex/StyleConverter.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* StyleConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import writer2latex.latex.util.StyleMap;
|
||||
import writer2latex.util.ExportNameCollection;
|
||||
import writer2latex.office.OfficeReader;
|
||||
|
||||
/**
|
||||
* <p>This is an abstract superclass for style converters.</p>
|
||||
*/
|
||||
public abstract class StyleConverter extends ConverterHelper {
|
||||
|
||||
// Names and maps + necessary declarations for these styles
|
||||
protected ExportNameCollection styleNames = new ExportNameCollection(false);
|
||||
protected StyleMap styleMap = new StyleMap();
|
||||
protected LaTeXDocumentPortion declarations = new LaTeXDocumentPortion(false);
|
||||
|
||||
protected StyleConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
decl.append(declarations);
|
||||
}
|
||||
|
||||
}
|
366
source/java/writer2latex/latex/TableConverter.java
Normal file
366
source/java/writer2latex/latex/TableConverter.java
Normal file
|
@ -0,0 +1,366 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* TableConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/** <p>This class converts OpenDocument tables to LaTeX.</p>
|
||||
* <p>The following LaTeX packages are used; some of them are optional</p>
|
||||
* <p>array.sty, longtable.sty, supertabular.sty, tabulary.sty, hhline.sty,
|
||||
* colortbl.sty.</p>
|
||||
* <p>Options:</p>
|
||||
* <ul>
|
||||
* <li>use_longtable = true|false</li>
|
||||
* <li>use_supertabular = true|false</li>
|
||||
* <li>use_tabulary = true|false</li>
|
||||
* <li>use_colortbl = true|false</li>
|
||||
* <li>float_tables = true|false</li>
|
||||
* <li>float_options = <string></li>
|
||||
* <li>table_content = accept|ignore|warning|error</li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
public class TableConverter extends ConverterHelper {
|
||||
|
||||
private boolean bNeedLongtable = false;
|
||||
private boolean bNeedSupertabular = false;
|
||||
private boolean bNeedTabulary = false;
|
||||
private boolean bNeedColortbl = false;
|
||||
private boolean bContainsTables = false;
|
||||
|
||||
/** <p>Constructs a new <code>TableConverter</code>.</p>
|
||||
*/
|
||||
public TableConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
pack.append("\\usepackage{array}").nl(); // TODO: Make this optional
|
||||
if (bNeedLongtable) { pack.append("\\usepackage{longtable}").nl(); }
|
||||
if (bNeedSupertabular) { pack.append("\\usepackage{supertabular}").nl(); }
|
||||
if (bNeedTabulary) { pack.append("\\usepackage{tabulary}").nl(); }
|
||||
pack.append("\\usepackage{hhline}").nl(); // TODO: Make this optional
|
||||
if (bNeedColortbl) { pack.append("\\usepackage{colortbl}").nl(); }
|
||||
|
||||
// Set padding for table cells (1mm is default in OOo!)
|
||||
// For vertical padding we can only specify a relative size
|
||||
if (bContainsTables) {
|
||||
decl.append("\\setlength\\tabcolsep{1mm}").nl();
|
||||
decl.append("\\renewcommand\\arraystretch{1.3}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
// Export a lonely table caption
|
||||
public void handleCaption(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append("\\captionof{table}");
|
||||
palette.getCaptionCv().handleCaptionBody(node,ldp,oc,true);
|
||||
}
|
||||
|
||||
/** <p> Process a table (table:table or table:sub-table tag)</p>
|
||||
* @param node The element containing the table
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleTable(Element node, Element caption, boolean bCaptionAbove,
|
||||
LaTeXDocumentPortion ldp, Context oc) {
|
||||
|
||||
// Export table, if allowed by the configuration
|
||||
switch (config.tableContent()) {
|
||||
case LaTeXConfig.ACCEPT:
|
||||
new SingleTableConverter().handleTable(node,caption,bCaptionAbove,ldp,oc);
|
||||
bContainsTables = true;
|
||||
break;
|
||||
case LaTeXConfig.IGNORE:
|
||||
// Ignore table silently
|
||||
break;
|
||||
case LaTeXConfig.WARNING:
|
||||
System.err.println("Warning: Tables are not allowed");
|
||||
break;
|
||||
case LaTeXConfig.ERROR:
|
||||
ldp.append("% Error in document: A table was ignored");
|
||||
}
|
||||
}
|
||||
|
||||
// Inner class to convert a single table
|
||||
private class SingleTableConverter {
|
||||
private TableReader table;
|
||||
private TableFormatter formatter;
|
||||
private Element caption;
|
||||
private boolean bCaptionAbove;
|
||||
private BeforeAfter baTable;
|
||||
private BeforeAfter baTableAlign;
|
||||
|
||||
private void handleTable(Element node, Element caption, boolean bCaptionAbove,
|
||||
LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Store the caption
|
||||
this.caption = caption;
|
||||
this.bCaptionAbove = bCaptionAbove;
|
||||
|
||||
// Read the table
|
||||
table = ofr.getTableReader(node);
|
||||
|
||||
// Get formatter and update flags according to formatter
|
||||
formatter = new TableFormatter(ofr,config,palette,table,!oc.isInMulticols(),oc.isInTable());
|
||||
bContainsTables = true;
|
||||
bNeedLongtable |= formatter.isLongtable();
|
||||
bNeedSupertabular |= formatter.isSupertabular();
|
||||
bNeedTabulary |= formatter.isTabulary();
|
||||
bNeedColortbl |= formatter.isColortbl();
|
||||
|
||||
// Update the context
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInTable(true);
|
||||
ic.setInSimpleTable(formatter.isSimple());
|
||||
// Never allow footnotes in tables
|
||||
// (longtable.sty *does* allow footnotes in body, but not in head -
|
||||
// only consistent solution is to disallow all footnotes)
|
||||
ic.setNoFootnotes(true);
|
||||
|
||||
// Get table declarations
|
||||
baTable = new BeforeAfter();
|
||||
baTableAlign = new BeforeAfter();
|
||||
formatter.applyTableStyle(baTable,baTableAlign);
|
||||
|
||||
// Convert table
|
||||
if (formatter.isSupertabular()) {
|
||||
handleSupertabular(ldp,ic);
|
||||
}
|
||||
else if (formatter.isLongtable()) {
|
||||
handleLongtable(ldp,ic);
|
||||
}
|
||||
else if (config.floatTables() && !ic.isInFrame() && !table.isSubTable()) {
|
||||
handleTableFloat(ldp,ic);
|
||||
}
|
||||
else {
|
||||
handleTabular(ldp,ic);
|
||||
}
|
||||
|
||||
// Insert any pending footnotes
|
||||
palette.getNoteCv().flushFootnotes(ldp,oc);
|
||||
}
|
||||
|
||||
private void handleSupertabular(LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append(baTableAlign.getBefore());
|
||||
|
||||
// Caption
|
||||
if (caption!=null) {
|
||||
handleCaption(bCaptionAbove ? "\\topcaption" : "\\bottomcaption",
|
||||
ldp,oc);
|
||||
}
|
||||
|
||||
// Table head
|
||||
ldp.append("\\tablehead{");
|
||||
handleHeaderRows(ldp,oc);
|
||||
ldp.append("}");
|
||||
|
||||
// The table
|
||||
handleHyperTarget(ldp);
|
||||
ldp.append(baTable.getBefore()).nl();
|
||||
handleBodyRows(ldp,oc);
|
||||
ldp.append(baTable.getAfter()).nl();
|
||||
|
||||
ldp.append(baTableAlign.getAfter());
|
||||
}
|
||||
|
||||
private void handleLongtable(LaTeXDocumentPortion ldp, Context oc) {
|
||||
handleHyperTarget(ldp);
|
||||
ldp.append(baTable.getBefore()).nl();
|
||||
|
||||
// Caption above
|
||||
if (caption!=null && bCaptionAbove) {
|
||||
handleCaption("\\caption",ldp,oc);
|
||||
ldp.append("\\\\").nl();
|
||||
handleHeaderRows(ldp,oc);
|
||||
ldp.nl().append("\\endfirsthead").nl();
|
||||
}
|
||||
|
||||
// Table head
|
||||
if (table.getFirstBodyRow()>0) {
|
||||
handleHeaderRows(ldp,oc);
|
||||
ldp.nl().append("\\endhead").nl();
|
||||
}
|
||||
|
||||
// Caption below
|
||||
if (caption!=null && !bCaptionAbove) {
|
||||
handleCaption("\\caption",ldp,oc);
|
||||
ldp.append("\\endlastfoot").nl();
|
||||
}
|
||||
|
||||
// Table body
|
||||
handleBodyRows(ldp,oc);
|
||||
|
||||
ldp.append(baTable.getAfter()).nl();
|
||||
}
|
||||
|
||||
private void handleTableFloat(LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append("\\begin{table}");
|
||||
if (config.getFloatOptions().length()>0) {
|
||||
ldp.append("[").append(config.getFloatOptions()).append("]");
|
||||
}
|
||||
ldp.nl();
|
||||
|
||||
ldp.append(baTableAlign.getBefore());
|
||||
|
||||
// Caption above
|
||||
if (caption!=null && bCaptionAbove) {
|
||||
handleCaption("\\caption",ldp,oc);
|
||||
}
|
||||
|
||||
// The table
|
||||
handleHyperTarget(ldp);
|
||||
ldp.append(baTable.getBefore()).nl();
|
||||
handleHeaderRows(ldp,oc);
|
||||
ldp.nl();
|
||||
handleBodyRows(ldp,oc);
|
||||
ldp.append(baTable.getAfter()).nl();
|
||||
|
||||
// Caption below
|
||||
if (caption!=null && !bCaptionAbove) {
|
||||
handleCaption("\\caption",ldp,oc);
|
||||
}
|
||||
|
||||
ldp.append(baTableAlign.getAfter());
|
||||
|
||||
ldp.append("\\end{table}").nl();
|
||||
}
|
||||
|
||||
private void handleTabular(LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append(baTableAlign.getBefore());
|
||||
|
||||
// Caption above
|
||||
if (caption!=null && bCaptionAbove) {
|
||||
TableConverter.this.handleCaption(caption,ldp,oc);
|
||||
}
|
||||
|
||||
// The table
|
||||
handleHyperTarget(ldp);
|
||||
ldp.append(baTable.getBefore()).nl();
|
||||
if (table.getFirstBodyRow()>0) {
|
||||
handleHeaderRows(ldp,oc);
|
||||
ldp.nl();
|
||||
}
|
||||
handleBodyRows(ldp,oc);
|
||||
ldp.append(baTable.getAfter()).nl();
|
||||
|
||||
// Caption below
|
||||
if (caption!=null && !bCaptionAbove) {
|
||||
TableConverter.this.handleCaption(caption,ldp,oc);
|
||||
}
|
||||
|
||||
ldp.append(baTableAlign.getAfter());
|
||||
}
|
||||
|
||||
private void handleCaption(String sCommand, LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append(sCommand);
|
||||
palette.getCaptionCv().handleCaptionBody(caption,ldp,oc,false);
|
||||
}
|
||||
|
||||
private void handleHyperTarget(LaTeXDocumentPortion ldp) {
|
||||
// We may need a hyperlink target
|
||||
if (!table.isSubTable()) {
|
||||
palette.getFieldCv().addTarget(table.getTableName(),"|table",ldp);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleHeaderRows(LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Note: does *not* add newline after last row
|
||||
if (table.getFirstBodyRow()>0) {
|
||||
|
||||
// Add interrow material before first row:
|
||||
String sInter = formatter.getInterrowMaterial(0);
|
||||
if (sInter.length()>0) {
|
||||
ldp.append(sInter).nl();
|
||||
}
|
||||
|
||||
// Add header rows
|
||||
handleRows(0,table.getFirstBodyRow(),ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleBodyRows(LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (table.getFirstBodyRow()==0) {
|
||||
// No head, add interrow material before first row:
|
||||
String sInter = formatter.getInterrowMaterial(0);
|
||||
if (sInter.length()>0) {
|
||||
ldp.append(sInter).nl();
|
||||
}
|
||||
}
|
||||
|
||||
// Add body rows
|
||||
handleRows(table.getFirstBodyRow(),table.getRowCount(),ldp,oc);
|
||||
ldp.nl();
|
||||
}
|
||||
|
||||
private void handleRows(int nStart, int nEnd, LaTeXDocumentPortion ldp, Context oc) {
|
||||
int nColCount = table.getColCount();
|
||||
for (int nRow=nStart; nRow<nEnd; nRow++) {
|
||||
// Export columns in this row
|
||||
Context icRow = (Context) oc.clone();
|
||||
BeforeAfter baRow = new BeforeAfter();
|
||||
formatter.applyRowStyle(nRow,baRow,icRow);
|
||||
if (!baRow.isEmpty()) {
|
||||
ldp.append(baRow.getBefore());
|
||||
if (!formatter.isSimple()) { ldp.nl(); }
|
||||
}
|
||||
int nCol = 0;
|
||||
while (nCol<nColCount) {
|
||||
Element cell = (Element) table.getCell(nRow,nCol);
|
||||
if (XMLString.TABLE_TABLE_CELL.equals(cell.getNodeName())) {
|
||||
Context icCell = (Context) icRow.clone();
|
||||
BeforeAfter baCell = new BeforeAfter();
|
||||
formatter.applyCellStyle(nRow,nCol,baCell,icCell);
|
||||
ldp.append(baCell.getBefore());
|
||||
if (nCol==nColCount-1) { icCell.setInLastTableColumn(true); }
|
||||
palette.getBlockCv().traverseBlockText(cell,ldp,icCell);
|
||||
ldp.append(baCell.getAfter());
|
||||
}
|
||||
// Otherwise ignore; the cell is covered by a \multicolumn entry.
|
||||
// (table:covered-table-cell)
|
||||
int nColSpan = Misc.getPosInteger(cell.getAttribute(
|
||||
XMLString.TABLE_NUMBER_COLUMNS_SPANNED),1);
|
||||
if (nCol+nColSpan<nColCount) {
|
||||
if (formatter.isSimple()) { ldp.append(" & "); }
|
||||
else { ldp.append(" &").nl(); }
|
||||
}
|
||||
nCol+=nColSpan;
|
||||
}
|
||||
ldp.append("\\\\").append(formatter.getInterrowMaterial(nRow+1));
|
||||
// Add newline, except after last row
|
||||
if (nRow<nEnd-1) { ldp.nl(); }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
451
source/java/writer2latex/latex/TableFormatter.java
Normal file
451
source/java/writer2latex/latex/TableFormatter.java
Normal file
|
@ -0,0 +1,451 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* TableFormatter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-19)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/**
|
||||
* <p>This class converts OOo table styles to LaTeX.</p>
|
||||
* <p> In OOo the table style is distributed on table, column and cell styles.
|
||||
* <p> In LaTeX we have to rearrange this information slightly, so this class
|
||||
* takes care of that.</p>
|
||||
*/
|
||||
public class TableFormatter extends ConverterHelper {
|
||||
|
||||
//private boolean bApplyCellFormat;
|
||||
private TableReader table;
|
||||
private char[][] cAlign;
|
||||
private char[] cGlobalAlign;
|
||||
private boolean[][] bHBorder;
|
||||
private boolean[][] bVBorder;
|
||||
private boolean[] bGlobalVBorder;
|
||||
private String[] sRowColor;
|
||||
private String[][] sCellColor;
|
||||
private String[] sColumnWidth;
|
||||
private boolean bIsLongtable;
|
||||
private boolean bIsSupertabular;
|
||||
private boolean bIsTabulary;
|
||||
private boolean bIsColortbl;
|
||||
private boolean bIsSimple;
|
||||
|
||||
/** <p>Constructor: Create from a TableReader.</p>
|
||||
*/
|
||||
public TableFormatter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette,
|
||||
TableReader table, boolean bAllowPageBreak, boolean bIsInTable) {
|
||||
super(ofr,config,palette);
|
||||
this.table = table;
|
||||
//bApplyCellFormat = config.formatting()>=LaTeXConfig.CONVERT_MOST;
|
||||
int nRowCount = table.getRowCount();
|
||||
int nColCount = table.getColCount();
|
||||
int nSimpleTableLimit = config.getSimpleTableLimit();
|
||||
|
||||
// Step 1: Collect alignment and identify simple tables
|
||||
bIsSimple = true;
|
||||
cAlign = new char[nRowCount][nColCount];
|
||||
cGlobalAlign = new char[nColCount];
|
||||
// Keep track of characters to be counted
|
||||
int[] nPendingChars = new int[nRowCount];
|
||||
int[] nPendingColSpan = new int[nRowCount];
|
||||
int nTableWidth = 0;
|
||||
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
// Collect chars to be counted in this column
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
Element cell = table.getCell(nRow, nCol);
|
||||
if (Misc.isElement(cell, XMLString.TABLE_TABLE_CELL)) {
|
||||
// Now we're here: Collect alignment
|
||||
if (OfficeReader.isSingleParagraph(cell)) {
|
||||
Node par = Misc.getChildByTagName(cell,XMLString.TEXT_P);
|
||||
StyleWithProperties style = ofr.getParStyle(Misc.getAttribute(par,XMLString.TEXT_STYLE_NAME));
|
||||
cAlign[nRow][nCol] = 'l';
|
||||
if (style!=null) {
|
||||
String sAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,true);
|
||||
if ("center".equals(sAlign)) { cAlign[nRow][nCol] = 'c'; }
|
||||
else if ("end".equals(sAlign)) { cAlign[nRow][nCol] = 'r'; }
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// Found cell with more than one paragraph
|
||||
bIsSimple = false;
|
||||
}
|
||||
// Collect characters (the cell contains this many characters that should be distributed over that many columns)
|
||||
nPendingChars[nRow] = OfficeReader.getCharacterCount(cell);
|
||||
nPendingColSpan[nRow] = Misc.getPosInteger(cell.getAttribute(XMLString.TABLE_NUMBER_COLUMNS_SPANNED), 1);
|
||||
}
|
||||
}
|
||||
// Determine the number of characters to count *now* (because they cannot be postponed to next column)
|
||||
int nColChars = 0;
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
if (nPendingColSpan[nRow]==1) {
|
||||
nColChars = Math.max(nColChars, nPendingChars[nRow]);
|
||||
}
|
||||
}
|
||||
// Reduce pending chars and increase table width
|
||||
nTableWidth += nColChars;
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
if (nPendingColSpan[nRow]>=1) {
|
||||
nPendingChars[nRow] = Math.max(0, nPendingChars[nRow]-nColChars);
|
||||
nPendingColSpan[nRow]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nTableWidth>nSimpleTableLimit) bIsSimple = false;
|
||||
|
||||
// Step 2: Create global alignment
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
int nCenter = 0;
|
||||
int nRight = 0;
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
if (cAlign[nRow][nCol]=='c') { nCenter++; }
|
||||
else if (cAlign[nRow][nCol]=='r') { nRight++; }
|
||||
}
|
||||
cGlobalAlign[nCol] = 'l';
|
||||
int nLeft = nColCount-nCenter-nRight;
|
||||
if (nCenter>nLeft) {
|
||||
if (nRight>nLeft) { cGlobalAlign[nCol] = 'r'; }
|
||||
else { cGlobalAlign[nCol] = 'c'; }
|
||||
}
|
||||
else if (nRight>nLeft) {
|
||||
cGlobalAlign[nCol] = 'r';
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Initialize borders:
|
||||
bHBorder = new boolean[nRowCount+1][nColCount];
|
||||
for (int nRow=0; nRow<=nRowCount; nRow++) {
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
bHBorder[nRow][nCol] = false;
|
||||
}
|
||||
}
|
||||
bVBorder = new boolean[nRowCount][nColCount+1];
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
for (int nCol=0; nCol<=nColCount; nCol++) {
|
||||
bVBorder[nRow][nCol] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Collect borders from cell styles:
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
int nCol = 0;
|
||||
while (nCol<nColCount) {
|
||||
Node cell = table.getCell(nRow,nCol);
|
||||
String sStyleName = Misc.getAttribute(cell,XMLString.TABLE_STYLE_NAME);
|
||||
StyleWithProperties style = ofr.getCellStyle(sStyleName);
|
||||
int nColSpan = Misc.getPosInteger(Misc.getAttribute(cell,
|
||||
XMLString.TABLE_NUMBER_COLUMNS_SPANNED),1);
|
||||
boolean bLeft = false;
|
||||
boolean bRight = false;
|
||||
boolean bTop = false;
|
||||
boolean bBottom = false;
|
||||
if (style!=null) {
|
||||
String sBorder = style.getProperty(XMLString.FO_BORDER);
|
||||
if (sBorder!=null && !"none".equals(sBorder)) {
|
||||
bLeft = true; bRight = true; bTop = true; bBottom = true;
|
||||
}
|
||||
sBorder = style.getProperty(XMLString.FO_BORDER_LEFT);
|
||||
if (sBorder!=null && !"none".equals(sBorder)) {
|
||||
bLeft = true;
|
||||
}
|
||||
sBorder = style.getProperty(XMLString.FO_BORDER_RIGHT);
|
||||
if (sBorder!=null && !"none".equals(sBorder)) {
|
||||
bRight = true;
|
||||
}
|
||||
sBorder = style.getProperty(XMLString.FO_BORDER_TOP);
|
||||
if (sBorder!=null && !"none".equals(sBorder)) {
|
||||
bTop = true;
|
||||
}
|
||||
sBorder = style.getProperty(XMLString.FO_BORDER_BOTTOM);
|
||||
if (sBorder!=null && !"none".equals(sBorder)) {
|
||||
bBottom = true;
|
||||
}
|
||||
}
|
||||
bVBorder[nRow][nCol] |= bLeft;
|
||||
bVBorder[nRow][nCol+nColSpan] |= bRight;
|
||||
do {
|
||||
bHBorder[nRow][nCol] |= bTop;
|
||||
bHBorder[nRow+1][nCol] |= bBottom;
|
||||
nCol++;
|
||||
} while (--nColSpan>0);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5: Create global vertical borders based on simple majority
|
||||
// (in order to minimize the number of \multicolum{1} entries)
|
||||
bGlobalVBorder = new boolean[nColCount+1];
|
||||
for (int nCol=0; nCol<=nColCount; nCol++) {
|
||||
int nBalance = 0;
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
nBalance += bVBorder[nRow][nCol] ? 1 : -1;
|
||||
}
|
||||
bGlobalVBorder[nCol] = nBalance>0;
|
||||
}
|
||||
|
||||
// Step 6: Get background colors
|
||||
sRowColor = new String[nRowCount];
|
||||
sCellColor = new String[nRowCount][nColCount];
|
||||
if (config.useColortbl()) {
|
||||
// Table background
|
||||
String sTableColor = null;
|
||||
StyleWithProperties tableStyle = ofr.getTableStyle(table.getTableStyleName());
|
||||
if (tableStyle!=null) {
|
||||
sTableColor = tableStyle.getProperty(XMLString.FO_BACKGROUND_COLOR);
|
||||
}
|
||||
|
||||
// Row background
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
StyleWithProperties rowStyle = ofr.getRowStyle(table.getRow(nRow).getStyleName());
|
||||
if (rowStyle!=null) {
|
||||
sRowColor[nRow] = rowStyle.getProperty(XMLString.FO_BACKGROUND_COLOR);
|
||||
}
|
||||
if (sRowColor[nRow]==null) {
|
||||
sRowColor[nRow] = sTableColor;
|
||||
}
|
||||
if (sRowColor[nRow]!=null) {
|
||||
bIsColortbl = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Cell background
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
StyleWithProperties cellStyle = ofr.getCellStyle(Misc.getAttribute(table.getCell(nRow,nCol),XMLString.TABLE_STYLE_NAME));
|
||||
if (cellStyle!=null) {
|
||||
sCellColor[nRow][nCol] = cellStyle.getProperty(XMLString.FO_BACKGROUND_COLOR);
|
||||
if (sCellColor[nRow][nCol]!=null) {
|
||||
bIsColortbl = true;
|
||||
if (sCellColor[nRow][nCol].equals(sRowColor[nRow])) {
|
||||
// Avoid redundant cell background
|
||||
sCellColor[nRow][nCol] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Step 7: Read column style information
|
||||
sColumnWidth = new String[nColCount];
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
StyleWithProperties colStyle
|
||||
= ofr.getColumnStyle(table.getCol(nCol).getStyleName());
|
||||
if (colStyle!=null) {
|
||||
sColumnWidth[nCol]
|
||||
= colStyle.getProperty(XMLString.STYLE_COLUMN_WIDTH);
|
||||
}
|
||||
if (sColumnWidth[nCol]==null) { // Emergency! should never happen!
|
||||
sColumnWidth[nCol]="2cm";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 8: Identify longtable, supertabular or tabulary
|
||||
bIsLongtable = false; bIsSupertabular = false; bIsTabulary = false;
|
||||
if (!table.isSubTable() && !bIsInTable) {
|
||||
String sStyleName = table.getTableStyleName();
|
||||
StyleWithProperties style = ofr.getTableStyle(sStyleName);
|
||||
boolean bMayBreak = style==null ||
|
||||
!"false".equals(style.getProperty(XMLString.STYLE_MAY_BREAK_BETWEEN_ROWS));
|
||||
if (config.useLongtable() && bMayBreak && bAllowPageBreak) {
|
||||
bIsLongtable = true;
|
||||
}
|
||||
else if (config.useSupertabular() && bMayBreak && bAllowPageBreak) {
|
||||
bIsSupertabular = true;
|
||||
}
|
||||
else if (!bIsSimple && config.useTabulary()) {
|
||||
bIsTabulary = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** is this a longtable? */
|
||||
public boolean isLongtable() { return bIsLongtable; }
|
||||
|
||||
/** is this a supertabular? */
|
||||
public boolean isSupertabular() { return bIsSupertabular; }
|
||||
|
||||
/** is this a tabulary? */
|
||||
public boolean isTabulary() { return bIsTabulary; }
|
||||
|
||||
/** is this a colortbl? */
|
||||
public boolean isColortbl() { return bIsColortbl; }
|
||||
|
||||
/** is this a simple table (lcr columns rather than p{})? */
|
||||
public boolean isSimple() { return bIsSimple; }
|
||||
|
||||
/**
|
||||
* <p>Create table environment based on table style.</p>
|
||||
* <p>Returns eg. "\begin{longtable}{m{2cm}|m{4cm}}", "\end{longtable}".</p>
|
||||
*/
|
||||
public void applyTableStyle(BeforeAfter ba, BeforeAfter baAlign) {
|
||||
// Read formatting info from table style
|
||||
// Only supported properties are alignment and may-break-between-rows.
|
||||
String sStyleName = table.getTableStyleName();
|
||||
StyleWithProperties style = ofr.getTableStyle(sStyleName);
|
||||
char cAlign = 'c';
|
||||
if (style!=null && !table.isSubTable()) {
|
||||
String s = style.getProperty(XMLString.TABLE_ALIGN);
|
||||
if ("left".equals(s)) { cAlign='l'; }
|
||||
else if ("right".equals(s)) { cAlign='r'; }
|
||||
}
|
||||
String sAlign="center";
|
||||
switch (cAlign) {
|
||||
case 'c': sAlign="center"; break;
|
||||
case 'r': sAlign="flushright"; break;
|
||||
case 'l': sAlign="flushleft";
|
||||
}
|
||||
|
||||
// Create table alignment (for supertabular, tabular and tabulary)
|
||||
if (!bIsLongtable && !table.isSubTable()) {
|
||||
baAlign.add("\\begin{"+sAlign+"}\n","\\end{"+sAlign+"}\n");
|
||||
}
|
||||
|
||||
// Create table declaration
|
||||
if (bIsLongtable) {
|
||||
ba.add("\\begin{longtable}["+cAlign+"]", "\\end{longtable}");
|
||||
}
|
||||
else if (bIsSupertabular) {
|
||||
ba.add("\\begin{supertabular}","\\end{supertabular}");
|
||||
}
|
||||
else if (bIsTabulary) {
|
||||
ba.add("\\begin{tabulary}{"+table.getTableWidth()+"}","\\end{tabulary}");
|
||||
}
|
||||
else if (!table.isSubTable()) {
|
||||
ba.add("\\begin{tabular}","\\end{tabular}");
|
||||
}
|
||||
else { // subtables should occupy the entire width, including padding!
|
||||
ba.add("\\hspace*{-\\tabcolsep}\\begin{tabular}",
|
||||
"\\end{tabular}\\hspace*{-\\tabcolsep}");
|
||||
}
|
||||
|
||||
// columns
|
||||
ba.add("{","");
|
||||
if (bGlobalVBorder[0]) { ba.add("|",""); }
|
||||
int nColCount = table.getColCount();
|
||||
for (int nCol=0; nCol<nColCount; nCol++){
|
||||
if (bIsSimple) {
|
||||
ba.add(Character.toString(cGlobalAlign[nCol]),"");
|
||||
}
|
||||
else if (!bIsTabulary) {
|
||||
// note: The column width in OOo includes padding, which we subtract
|
||||
ba.add("m{"+Misc.add(sColumnWidth[nCol],"-0.2cm")+"}","");
|
||||
}
|
||||
else {
|
||||
ba.add("J","");
|
||||
}
|
||||
if (bGlobalVBorder[nCol+1]) { ba.add("|",""); }
|
||||
}
|
||||
ba.add("}","");
|
||||
}
|
||||
|
||||
/** <p>Create interrow material</p> */
|
||||
public String getInterrowMaterial(int nRow) {
|
||||
int nColCount = table.getColCount();
|
||||
int nCount = 0;
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
if (bHBorder[nRow][nCol]) { nCount++; }
|
||||
}
|
||||
if (nCount==0) { // no borders at this row
|
||||
return "";
|
||||
}
|
||||
else if (nCount==nColCount) { // complete set of borders
|
||||
return "\\hline";
|
||||
}
|
||||
else { // individual borders for each column
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("\\hhline{");
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
if (bHBorder[nRow][nCol]) { buf.append("-"); }
|
||||
else { buf.append("~"); }
|
||||
}
|
||||
buf.append("}");
|
||||
/* TODO: hhline.sty should be optional, and i not used, do as before:
|
||||
boolean bInCline = false;
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
if (bInCline && !bHBorder[nRow][nCol]) { // close \cline
|
||||
buf.append(nCol).append("}");
|
||||
bInCline = false;
|
||||
}
|
||||
else if (!bInCline && bHBorder[nRow][nCol]) { // open \cline
|
||||
buf.append("\\cline{").append(nCol+1).append("-");
|
||||
bInCline = true;
|
||||
}
|
||||
}
|
||||
if (bInCline) { buf.append(nColCount).append("}"); }
|
||||
*/
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Get material to put before a table row (background color)
|
||||
*/
|
||||
public void applyRowStyle(int nRow, BeforeAfter ba, Context context) {
|
||||
palette.getColorCv().applyBgColor("\\rowcolor",sRowColor[nRow],ba,context);
|
||||
}
|
||||
|
||||
/** Get material to put before and after a table cell.
|
||||
* In case of columnspan or different borders this will contain a \multicolumn command.
|
||||
*/
|
||||
public void applyCellStyle(int nRow, int nCol, BeforeAfter ba, Context context) {
|
||||
Node cell = table.getCell(nRow,nCol);
|
||||
int nColSpan = Misc.getPosInteger(Misc.getAttribute(cell,
|
||||
XMLString.TABLE_NUMBER_COLUMNS_SPANNED),1);
|
||||
// Construct column declaration as needed
|
||||
boolean bNeedLeft = (nCol==0) && (bVBorder[nRow][0]!=bGlobalVBorder[0]);
|
||||
boolean bNeedRight = bVBorder[nRow][nCol+1]!=bGlobalVBorder[nCol+1];
|
||||
boolean bNeedAlign = bIsSimple && cGlobalAlign[nCol]!=cAlign[nRow][nCol];
|
||||
// calculate column width
|
||||
String sTotalColumnWidth = sColumnWidth[nCol];
|
||||
for (int i=nCol+1; i<nCol+nColSpan; i++) {
|
||||
sTotalColumnWidth = Misc.add(sTotalColumnWidth,sColumnWidth[i]);
|
||||
}
|
||||
sTotalColumnWidth = Misc.add(sTotalColumnWidth,"-0.2cm");
|
||||
|
||||
if (bNeedAlign || bNeedLeft || bNeedRight || nColSpan>1) {
|
||||
ba.add("\\multicolumn{"+nColSpan+"}{","");
|
||||
if (nCol==0 && bVBorder[nRow][0]) { ba.add("|",""); }
|
||||
if (bIsSimple) {
|
||||
ba.add(Character.toString(cAlign[nRow][nCol]),"");
|
||||
}
|
||||
else {
|
||||
ba.add("m{"+sTotalColumnWidth+"}","");
|
||||
}
|
||||
if (bVBorder[nRow][nCol+nColSpan]) { ba.add("|",""); }
|
||||
ba.add("}{","}");
|
||||
}
|
||||
|
||||
palette.getColorCv().applyBgColor("\\cellcolor",sCellColor[nRow][nCol],ba,context);
|
||||
|
||||
}
|
||||
}
|
77
source/java/writer2latex/latex/config/clean.xml
Normal file
77
source/java/writer2latex/latex/config/clean.xml
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- clean.xml
|
||||
This is a sample configuration file for Writer2LaTeX.
|
||||
The options are set to produce a clean
|
||||
LaTeX file from an arbitrary Writer document
|
||||
- at the expense of loss of formatting.
|
||||
An even cleaner LaTeX file is produced with ultraclean.xml.
|
||||
-->
|
||||
|
||||
<config>
|
||||
<option name="documentclass" value="article" />
|
||||
<option name="backend" value="generic" />
|
||||
<option name="inputencoding" value="ascii" />
|
||||
<option name="multilingual" value="false" />
|
||||
<option name="use_ooomath" value="false" />
|
||||
<option name="use_color" value="true" />
|
||||
<option name="use_colortbl" value="false" />
|
||||
<option name="use_geometry" value="true" />
|
||||
<option name="use_fancyhdr" value="false" />
|
||||
<option name="use_hyperref" value="true" />
|
||||
<option name="use_caption" value="true" />
|
||||
<option name="use_endnotes" value="false" />
|
||||
<option name="use_bibtex" value="true" />
|
||||
<option name="bibtex_style" value="plain" />
|
||||
<option name="formatting" value="ignore_most" />
|
||||
<option name="page_formatting" value="convert_geometry" />
|
||||
<option name="ignore_empty_paragraphs" value="true" />
|
||||
<option name="ignore_hard_page_breaks" value="false" />
|
||||
<option name="ignore_hard_line_breaks" value="false" />
|
||||
<option name="ignore_double_spaces" value="true" />
|
||||
<option name="debug" value="false" />
|
||||
<heading-map max-level="5">
|
||||
<heading-level-map writer-level="1" name="section" level="1" />
|
||||
<heading-level-map writer-level="2" name="subsection" level="2" />
|
||||
<heading-level-map writer-level="3" name="subsubsection" level="3" />
|
||||
<heading-level-map writer-level="4" name="paragraph" level="4" />
|
||||
<heading-level-map writer-level="5" name="subparagraph" level="5" />
|
||||
</heading-map>
|
||||
<custom-preamble />
|
||||
|
||||
<!-- Style maps: These rules defines how styles in OOo are mapped to LaTeX code.
|
||||
A number of predefined Writer styles are converted -->
|
||||
|
||||
<!-- "Title" is mapped to \maketitle. If the user chooses to export meta data,
|
||||
the author and date will be inserted automatically -->
|
||||
<style-map name="Title" class="paragraph" before="\title{" after="} \maketitle" line-break="false" />
|
||||
|
||||
<!-- "Quotations" is mapped to a quotation environment -->
|
||||
<style-map name="Quotations" family="paragraph-block" next="Quotations" before="\begin{quotation}" after="\end{quotation}" />
|
||||
<style-map name="Quotations" family="paragraph" before="" after="" />
|
||||
|
||||
<!-- Preformatted Text is mapped to a verbatim environment
|
||||
Note the attribute verbatim, which instructs OOo to output the content
|
||||
verbatim (characters not available in the inputencoding will be replaced
|
||||
by question marks; other content will be lost). -->
|
||||
<style-map name="Preformatted Text" family="paragraph-block" next="Preformatted Text" before="\begin{verbatim}" after="\end{verbatim}" />
|
||||
<style-map name="Preformatted Text" family="paragraph" before="" after="" verbatim="true" />
|
||||
|
||||
<!-- "Horizontal line" is mapped to a \hrule -->
|
||||
<style-map name="Horizontal Line" family="paragraph" before="" after=" \begin{center}\hrule\end{center}" />
|
||||
|
||||
<!-- "Emphasis" text style is mapped to \emph -->
|
||||
<style-map name="Emphasis" family="text" before="\emph{" after="}" />
|
||||
|
||||
<!-- "Strong Emphasis" text style is mapped to \textbf -->
|
||||
<style-map name="Strong Emphasis" family="text" before="\textbf{" after="}" />
|
||||
|
||||
<!-- "Teletype" text style is mapped to \texttt -->
|
||||
<style-map name="Teletype" family="text" before="\texttt{" after="}" />
|
||||
|
||||
<!-- "List Heading" and "List Contents" are mapped to a description environment -->
|
||||
<style-map name="List Heading" family="paragraph-block" next="List Heading;List Contents" before="\begin{description}" after="\end{description}"/>
|
||||
<style-map name="List Heading" family="paragraph" before="\item[" after="]" line-break="false" />
|
||||
<style-map name="List Contents" family="paragraph" before="" after="" />
|
||||
|
||||
</config>
|
||||
|
8
source/java/writer2latex/latex/config/default.xml
Normal file
8
source/java/writer2latex/latex/config/default.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- default.xml
|
||||
This is a sample configuration file for Writer2LaTeX.
|
||||
It sets no options, thus using defaults everywhere
|
||||
-->
|
||||
|
||||
<config/>
|
||||
|
43
source/java/writer2latex/latex/config/pdfprint.xml
Normal file
43
source/java/writer2latex/latex/config/pdfprint.xml
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- pdfprint.xml
|
||||
This is a sample configuration file for Writer2LaTeX.
|
||||
The output will be for pdfTeX, using all the packages pifont, ifsym,
|
||||
wasysym, eurosym, hyperref, endnotes and ulem. -->
|
||||
|
||||
<config>
|
||||
<option name="documentclass" value="article" />
|
||||
<option name="backend" value="pdftex" />
|
||||
<option name="inputencoding" value="ascii" />
|
||||
<option name="use_geometry" value="true" />
|
||||
<option name="use_fancyhdr" value="true" />
|
||||
<option name="use_ooomath" value="true" />
|
||||
<option name="use_pifont" value="true" />
|
||||
<option name="use_ifsym" value="true" />
|
||||
<option name="use_wasysym" value="true" />
|
||||
<option name="use_eurosym" value="true" />
|
||||
<option name="use_color" value="true" />
|
||||
<option name="use_colortbl" value="true" />
|
||||
<option name="use_hyperref" value="true" />
|
||||
<option name="use_endnotes" value="true" />
|
||||
<option name="use_ulem" value="true" />
|
||||
<option name="use_lastpage" value="true" />
|
||||
<option name="formatting" value="convert_all" />
|
||||
<option name="page_formatting" value="convert_all" />
|
||||
<option name="ignore_empty_paragraphs" value="false" />
|
||||
<option name="ignore_hard_page_breaks" value="false" />
|
||||
<option name="ignore_hard_line_breaks" value="false" />
|
||||
<option name="ignore_double_spaces" value="false" />
|
||||
<option name="debug" value="false" />
|
||||
<heading-map max-level="5">
|
||||
<heading-level-map writer-level="1" name="section" level="1" />
|
||||
<heading-level-map writer-level="2" name="subsection" level="2" />
|
||||
<heading-level-map writer-level="3" name="subsubsection" level="3" />
|
||||
<heading-level-map writer-level="4" name="paragraph" level="4" />
|
||||
<heading-level-map writer-level="5" name="subparagraph" level="5" />
|
||||
</heading-map>
|
||||
<!-- We add \sloppy to avoid overful hboxes. To get better results,
|
||||
this should be removed and overful hboxes fixed by hand. -->
|
||||
<custom-preamble>\sloppy</custom-preamble>
|
||||
|
||||
</config>
|
||||
|
50
source/java/writer2latex/latex/config/pdfscreen.xml
Normal file
50
source/java/writer2latex/latex/config/pdfscreen.xml
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- pdfscreen.xml
|
||||
This is a sample configuration file for Writer2LaTeX.
|
||||
The output will be for pdfTeX, using all the packages pifont, ifsym,
|
||||
wasysym, eurosym, hyperref, endnotes and ulem.
|
||||
The package pdfscreen.sty will be loaded to create a pdf file
|
||||
suitable for viewing on screen. -->
|
||||
|
||||
<config>
|
||||
<option name="documentclass" value="article" />
|
||||
<option name="backend" value="pdftex" />
|
||||
<option name="inputencoding" value="ascii" />
|
||||
<option name="use_ooomath" value="true" />
|
||||
<option name="use_pifont" value="true" />
|
||||
<option name="use_ifsym" value="true" />
|
||||
<option name="use_wasysym" value="true" />
|
||||
<option name="use_bbding" value="false" />
|
||||
<option name="use_eurosym" value="true" />
|
||||
<option name="use_color" value="true" />
|
||||
<option name="use_colortbl" value="true" />
|
||||
<option name="use_hyperref" value="true" />
|
||||
<option name="use_endnotes" value="true" />
|
||||
<option name="use_ulem" value="true" />
|
||||
<option name="use_lastpage" value="true" />
|
||||
<option name="formatting" value="convert_all" />
|
||||
<option name="page_formatting" value="ignore_all" />
|
||||
<option name="ignore_empty_paragraphs" value="false" />
|
||||
<option name="ignore_hard_page_breaks" value="false" />
|
||||
<option name="ignore_hard_line_breaks" value="false" />
|
||||
<option name="ignore_double_spaces" value="true" />
|
||||
<option name="debug" value="false" />
|
||||
<heading-map max-level="5">
|
||||
<heading-level-map writer-level="1" name="section" level="1" />
|
||||
<heading-level-map writer-level="2" name="subsection" level="2" />
|
||||
<heading-level-map writer-level="3" name="subsubsection" level="3" />
|
||||
<heading-level-map writer-level="4" name="paragraph" level="4" />
|
||||
<heading-level-map writer-level="5" name="subparagraph" level="5" />
|
||||
</heading-map>
|
||||
|
||||
<!-- load pdfscreen.sty with suitable options. (Note that export of page
|
||||
formatting is disabled above; pdfscreen.sty takes care of page setup.)
|
||||
The lines are relatively short, so we add \sloppy to avoid overful hboxes.
|
||||
-->
|
||||
<custom-preamble>\usepackage{palatino}
|
||||
\usepackage[bluelace,screen,nopanel,sectionbreak]{pdfscreen}
|
||||
%\hypersetup{pdfpagemode={FullScreen}}
|
||||
\margins{0.5in}{0.5in}{0.5in}{0.5in}
|
||||
\screensize{6in}{8in}
|
||||
\sloppy</custom-preamble>
|
||||
</config>
|
77
source/java/writer2latex/latex/config/ultraclean.xml
Normal file
77
source/java/writer2latex/latex/config/ultraclean.xml
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- ultraclean.xml
|
||||
This is a sample configuration file for Writer2LaTeX.
|
||||
The options are set to produce the cleanest possible
|
||||
LaTeX file from an arbitrary Writer document
|
||||
- by removing practically all formatting.
|
||||
-->
|
||||
|
||||
|
||||
<config>
|
||||
<option name="documentclass" value="article" />
|
||||
<option name="backend" value="generic" />
|
||||
<option name="inputencoding" value="ascii" />
|
||||
<option name="multilingual" value="false" />
|
||||
<option name="use_ooomath" value="false" />
|
||||
<option name="use_color" value="false" />
|
||||
<option name="use_colortbl" value="false" />
|
||||
<option name="use_geometry" value="false" />
|
||||
<option name="use_fancyhdr" value="false" />
|
||||
<option name="use_hyperref" value="false" />
|
||||
<option name="use_caption" value="true" />
|
||||
<option name="use_endnotes" value="false" />
|
||||
<option name="use_bibtex" value="true" />
|
||||
<option name="bibtex_style" value="plain" />
|
||||
<option name="formatting" value="ignore_all" />
|
||||
<option name="page_formatting" value="ignore_all" />
|
||||
<option name="ignore_empty_paragraphs" value="true" />
|
||||
<option name="ignore_hard_page_breaks" value="true" />
|
||||
<option name="ignore_hard_line_breaks" value="true" />
|
||||
<option name="ignore_double_spaces" value="true" />
|
||||
<option name="debug" value="false" />
|
||||
<heading-map max-level="5">
|
||||
<heading-level-map writer-level="1" name="section" level="1" />
|
||||
<heading-level-map writer-level="2" name="subsection" level="2" />
|
||||
<heading-level-map writer-level="3" name="subsubsection" level="3" />
|
||||
<heading-level-map writer-level="4" name="paragraph" level="4" />
|
||||
<heading-level-map writer-level="5" name="subparagraph" level="5" />
|
||||
</heading-map>
|
||||
<custom-preamble />
|
||||
|
||||
<!-- Style maps: These rules defines how styles in OOo are mapped to LaTeX code.
|
||||
A number of predefined Writer styles are converted -->
|
||||
|
||||
<!-- "Title" is mapped to \maketitle. If the user chooses to export meta data,
|
||||
the author and date will be inserted automatically -->
|
||||
<style-map name="Title" class="paragraph" before="\title{" after="} \maketitle" line-break="false" />
|
||||
|
||||
<!-- "Quotations" is mapped to a quotation environment -->
|
||||
<style-map name="Quotations" family="paragraph-block" next="Quotations" before="\begin{quotation}" after="\end{quotation}" />
|
||||
<style-map name="Quotations" family="paragraph" before="" after="" />
|
||||
|
||||
<!-- Preformatted Text is mapped to a verbatim environment
|
||||
Note the attribute verbatim, which instructs OOo to output the content
|
||||
verbatim (characters not available in the inputencoding will be replaced
|
||||
by question marks; other content will be lost). -->
|
||||
<style-map name="Preformatted Text" family="paragraph-block" next="Preformatted Text" before="\begin{verbatim}" after="\end{verbatim}" />
|
||||
<style-map name="Preformatted Text" family="paragraph" before="" after="" verbatim="true" />
|
||||
|
||||
<!-- "Horizontal line" is mapped to a \hrule -->
|
||||
<style-map name="Horizontal Line" family="paragraph" before="" after=" \begin{center}\hrule\end{center}" />
|
||||
|
||||
<!-- "Emphasis" text style is mapped to \emph -->
|
||||
<style-map name="Emphasis" family="text" before="\emph{" after="}" />
|
||||
|
||||
<!-- "Strong Emphasis" text style is mapped to \textbf -->
|
||||
<style-map name="Strong Emphasis" family="text" before="\textbf{" after="}" />
|
||||
|
||||
<!-- "Teletype" text style is mapped to \texttt -->
|
||||
<style-map name="Teletype" family="text" before="\texttt{" after="}" />
|
||||
|
||||
<!-- "List Heading" and "List Contents" are mapped to a description environment -->
|
||||
<style-map name="List Heading" family="paragraph-block" next="List Heading;List Contents" before="\begin{description}" after="\end{description}"/>
|
||||
<style-map name="List Heading" family="paragraph" before="\item[" after="]" line-break="false" />
|
||||
<style-map name="List Contents" family="paragraph" before="" after="" />
|
||||
|
||||
</config>
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue