1999-09-27 18:44:28 +00:00
|
|
|
/*
|
|
|
|
* File: math_write.h
|
|
|
|
* Purpose: Write math paragraphs in LaTeX
|
|
|
|
* Author: Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
|
|
|
|
* Created: January 1996
|
|
|
|
* Description:
|
|
|
|
*
|
|
|
|
* Dependencies: Xlib, XForms
|
|
|
|
*
|
2000-03-09 03:36:48 +00:00
|
|
|
* Copyright: 1996, 1997 Alejandro Aguilar Sierra
|
1999-09-27 18:44:28 +00:00
|
|
|
*
|
|
|
|
* Version: 0.8beta, Mathed & Lyx project.
|
|
|
|
*
|
|
|
|
* You are free to use and modify this code under the terms of
|
|
|
|
* the GNU General Public Licence version 2 or later.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
2000-01-06 02:44:26 +00:00
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
#include "LString.h"
|
|
|
|
#include "math_inset.h"
|
|
|
|
#include "math_iter.h"
|
|
|
|
#include "math_parser.h"
|
1999-10-02 16:21:10 +00:00
|
|
|
#include "support/lstrings.h"
|
1999-10-07 18:44:17 +00:00
|
|
|
#include "debug.h"
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2000-04-04 00:19:15 +00:00
|
|
|
using std::ostream;
|
2000-03-28 02:18:55 +00:00
|
|
|
using std::endl;
|
|
|
|
|
1999-11-15 11:06:41 +00:00
|
|
|
extern char const * latex_mathenv[];
|
|
|
|
extern char * latex_mathspace[];
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
// quite a hack i know. Should be done with return values...
|
|
|
|
static int number_of_newlines;
|
|
|
|
|
1999-11-15 11:06:41 +00:00
|
|
|
char const * math_font_name[] = {
|
1999-09-27 18:44:28 +00:00
|
|
|
"mathrm",
|
|
|
|
"mathcal",
|
|
|
|
"mathbf",
|
|
|
|
"mathsf",
|
|
|
|
"mathtt",
|
|
|
|
"mathit",
|
|
|
|
"textrm"
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void
|
1999-12-07 00:44:53 +00:00
|
|
|
MathSpaceInset::Write(ostream & os)
|
2000-03-07 01:14:37 +00:00
|
|
|
{
|
|
|
|
if (space >= 0 && space < 6) {
|
|
|
|
os << '\\' << latex_mathspace[space] << ' ';
|
|
|
|
}
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
1999-12-07 00:44:53 +00:00
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
void
|
1999-12-07 00:44:53 +00:00
|
|
|
MathDotsInset::Write(ostream & os)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2000-03-07 01:14:37 +00:00
|
|
|
os << '\\' << name << ' ';
|
1999-12-07 00:44:53 +00:00
|
|
|
}
|
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
|
1999-12-07 00:44:53 +00:00
|
|
|
void MathSqrtInset::Write(ostream & os)
|
2000-03-07 01:14:37 +00:00
|
|
|
{
|
|
|
|
os << '\\' << name << '{';
|
|
|
|
MathParInset::Write(os);
|
|
|
|
os << '}';
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-12-07 00:44:53 +00:00
|
|
|
void MathDelimInset::Write(ostream & os)
|
2000-03-07 01:14:37 +00:00
|
|
|
{
|
|
|
|
latexkeys * l = (left != '|') ? lm_get_key_by_id(left, LM_TK_SYM): 0;
|
|
|
|
latexkeys * r = (right != '|') ? lm_get_key_by_id(right, LM_TK_SYM): 0;
|
|
|
|
os << "\\left";
|
|
|
|
if (l) {
|
|
|
|
os << '\\' << l->name << ' ';
|
|
|
|
} else {
|
|
|
|
if (left == '{' || left == '}') {
|
|
|
|
os << '\\' << char(left) << ' ';
|
|
|
|
} else {
|
|
|
|
os << char(left) << ' ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MathParInset::Write(os);
|
|
|
|
os << "\\right";
|
|
|
|
if (r) {
|
|
|
|
os << '\\' << r->name << ' ';
|
|
|
|
} else {
|
|
|
|
if (right == '{' || right == '}') {
|
|
|
|
os << '\\' << char(right) << ' ';
|
|
|
|
} else {
|
|
|
|
os << char(right) << ' ';
|
|
|
|
}
|
|
|
|
}
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-12-07 00:44:53 +00:00
|
|
|
void MathDecorationInset::Write(ostream & os)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2000-03-07 01:14:37 +00:00
|
|
|
latexkeys * l = lm_get_key_by_id(deco, LM_TK_WIDE);
|
|
|
|
os << '\\' << l->name << '{';
|
|
|
|
MathParInset::Write(os);
|
|
|
|
os << '}';
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
1999-12-07 00:44:53 +00:00
|
|
|
|
|
|
|
void MathAccentInset::Write(ostream & os)
|
2000-03-07 01:14:37 +00:00
|
|
|
{
|
|
|
|
latexkeys * l = lm_get_key_by_id(code, LM_TK_ACCENT);
|
|
|
|
os << '\\' << l->name;
|
|
|
|
if (code!= LM_not)
|
|
|
|
os << '{';
|
|
|
|
else
|
|
|
|
os << ' ';
|
|
|
|
|
|
|
|
if (inset) {
|
|
|
|
inset->Write(os);
|
|
|
|
} else {
|
|
|
|
if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM) {
|
|
|
|
os << '\\'
|
|
|
|
<< math_font_name[fn-LM_TC_RM]
|
|
|
|
<< '{';
|
|
|
|
}
|
|
|
|
if (MathIsSymbol(fn)) {
|
|
|
|
latexkeys * l = lm_get_key_by_id(c, LM_TK_SYM);
|
|
|
|
if (l) {
|
|
|
|
os << '\\' << l->name << ' ';
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
os << char(c);
|
|
|
|
|
|
|
|
if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM)
|
|
|
|
os << '}';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (code!= LM_not)
|
|
|
|
os << '}';
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-12-07 00:44:53 +00:00
|
|
|
void MathBigopInset::Write(ostream & os)
|
2000-03-07 01:14:37 +00:00
|
|
|
{
|
|
|
|
bool limp = GetLimits();
|
|
|
|
|
|
|
|
os << '\\' << name;
|
|
|
|
|
|
|
|
if (limp && !(sym != LM_int && sym != LM_oint
|
|
|
|
&& (GetStyle() == LM_ST_DISPLAY)))
|
|
|
|
os << "\\limits ";
|
|
|
|
else
|
|
|
|
if (!limp && (sym != LM_int && sym != LM_oint
|
|
|
|
&& (GetStyle() == LM_ST_DISPLAY)))
|
|
|
|
os << "\\nolimits ";
|
|
|
|
else
|
|
|
|
os << ' ';
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
1999-12-07 00:44:53 +00:00
|
|
|
|
|
|
|
void MathFracInset::Write(ostream & os)
|
2000-03-07 01:14:37 +00:00
|
|
|
{
|
|
|
|
os << '\\' << name << '{';
|
|
|
|
MathParInset::Write(os);
|
|
|
|
os << "}{";
|
|
|
|
den->Write(os);
|
|
|
|
os << '}';
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
1999-12-07 00:44:53 +00:00
|
|
|
|
|
|
|
void MathParInset::Write(ostream & os)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2000-03-07 01:14:37 +00:00
|
|
|
if (!array) return;
|
|
|
|
int brace = 0;
|
|
|
|
latexkeys * l;
|
|
|
|
MathedIter data(array);
|
|
|
|
// hack
|
|
|
|
MathedRowSt const * crow = getRowSt();
|
|
|
|
data.Reset();
|
|
|
|
|
|
|
|
if (!Permit(LMPF_FIXED_SIZE)) {
|
|
|
|
l = lm_get_key_by_id(size, LM_TK_STY);
|
|
|
|
if (l) {
|
|
|
|
os << '\\' << l->name << ' ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (data.OK()) {
|
|
|
|
byte cx = data.GetChar();
|
|
|
|
if (cx >= ' ') {
|
|
|
|
int ls;
|
|
|
|
byte * s = data.GetString(ls);
|
|
|
|
|
|
|
|
if (data.FCode() >= LM_TC_RM && data.FCode() <= LM_TC_TEXTRM) {
|
|
|
|
os << '\\' << math_font_name[data.FCode()-LM_TC_RM] << '{';
|
|
|
|
}
|
|
|
|
while (ls > 0) {
|
|
|
|
if (MathIsSymbol(data.FCode())) {
|
|
|
|
l = lm_get_key_by_id(*s, (data.FCode() == LM_TC_BSYM) ?
|
|
|
|
LM_TK_BIGSYM : LM_TK_SYM);
|
|
|
|
if (l) {
|
|
|
|
os << '\\' << l->name << ' ';
|
|
|
|
} else {
|
|
|
|
lyxerr << "Illegal symbol code[" << *s
|
|
|
|
<< " " << ls << " " << data.FCode() << "]";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Is there a standard logical XOR?
|
|
|
|
if ((data.FCode() == LM_TC_TEX && *s != '{' && *s != '}') ||
|
|
|
|
(data.FCode() == LM_TC_SPECIAL))
|
|
|
|
os << '\\';
|
|
|
|
else {
|
|
|
|
if (*s == '{') ++brace;
|
|
|
|
if (*s == '}') --brace;
|
|
|
|
}
|
|
|
|
if (*s == '}' && data.FCode() == LM_TC_TEX && brace < 0)
|
|
|
|
lyxerr <<"Math warning: Unexpected closing brace."
|
|
|
|
<< endl;
|
|
|
|
else
|
|
|
|
os << char(*s);
|
|
|
|
}
|
|
|
|
++s; --ls;
|
|
|
|
}
|
|
|
|
if (data.FCode()>= LM_TC_RM && data.FCode()<= LM_TC_TEXTRM)
|
|
|
|
os << '}';
|
|
|
|
} else
|
|
|
|
if (MathIsInset(cx)) {
|
|
|
|
MathedInset * p = data.GetInset();
|
|
|
|
if (cx == LM_TC_UP)
|
|
|
|
os << "^{";
|
|
|
|
if (cx == LM_TC_DOWN)
|
|
|
|
os << "_{";
|
|
|
|
p->Write(os);
|
|
|
|
if (cx == LM_TC_UP || cx == LM_TC_DOWN)
|
|
|
|
os << '}';
|
|
|
|
data.Next();
|
|
|
|
} else
|
|
|
|
switch(cx) {
|
|
|
|
case LM_TC_TAB:
|
|
|
|
{
|
|
|
|
os << " & ";
|
|
|
|
data.Next();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LM_TC_CR:
|
|
|
|
{
|
|
|
|
if (crow) {
|
|
|
|
if (!crow->isNumbered()) {
|
|
|
|
os << "\\nonumber ";
|
|
|
|
}
|
|
|
|
if (crow->getLabel()) {
|
|
|
|
os << "\\label{"
|
|
|
|
<< crow->getLabel()
|
|
|
|
<< "} ";
|
|
|
|
}
|
|
|
|
crow = crow->getNext();
|
|
|
|
}
|
|
|
|
os << "\\\\\n";
|
|
|
|
++number_of_newlines;
|
|
|
|
data.Next();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
lyxerr << "WMath Error: unrecognized code[" << cx << "]";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (crow) {
|
|
|
|
if (!crow->isNumbered()) {
|
|
|
|
os << "\\nonumber ";
|
|
|
|
}
|
|
|
|
if (crow->getLabel()) {
|
|
|
|
os << "\\label{"
|
|
|
|
<< crow->getLabel()
|
|
|
|
<< "} ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if 1
|
|
|
|
while (brace > 0) {
|
|
|
|
os << '}';
|
|
|
|
--brace;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
// Something like this should work too:
|
|
|
|
os << string(brace, '}'); // not one-off error I hope.
|
|
|
|
#endif
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-12-07 00:44:53 +00:00
|
|
|
void MathMatrixInset::Write(ostream & os)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2000-03-07 01:14:37 +00:00
|
|
|
if (GetType() == LM_OT_MATRIX){
|
|
|
|
os << "\\begin{"
|
|
|
|
<< name
|
|
|
|
<< '}';
|
|
|
|
if (v_align == 't' || v_align == 'b') {
|
|
|
|
os << '['
|
|
|
|
<< char(v_align)
|
|
|
|
<< ']';
|
|
|
|
}
|
|
|
|
os << '{'
|
|
|
|
<< h_align
|
|
|
|
<< "}\n";
|
|
|
|
++number_of_newlines;
|
|
|
|
}
|
|
|
|
MathParInset::Write(os);
|
|
|
|
if (GetType() == LM_OT_MATRIX){
|
|
|
|
os << "\n\\end{"
|
|
|
|
<< name
|
|
|
|
<< '}';
|
|
|
|
++number_of_newlines;
|
|
|
|
}
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
1999-12-07 00:44:53 +00:00
|
|
|
|
|
|
|
void mathed_write(MathParInset * p, ostream & os, int * newlines,
|
|
|
|
char fragile, char const * label)
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2000-03-07 01:14:37 +00:00
|
|
|
number_of_newlines = 0;
|
|
|
|
short mathed_env = p->GetType();
|
|
|
|
|
|
|
|
if (mathed_env == LM_EN_INTEXT) {
|
|
|
|
if (fragile) os << "\\protect";
|
|
|
|
os << "\\( "; // changed from " \\( " (Albrecht Dress)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Thinko!
|
|
|
|
// Is this '\n' really needed, what can go wrong
|
2000-04-08 17:02:02 +00:00
|
|
|
//if it is not there? The reason why I want to avoid this is
|
|
|
|
// because of the "backlook" into the output stream.
|
|
|
|
// Lgb.
|
2000-03-07 01:14:37 +00:00
|
|
|
#warning Thinko!
|
|
|
|
#if 0
|
|
|
|
if (!suffixIs(outf, '\n')) {
|
|
|
|
// in batchmode we need to make sure
|
|
|
|
// a space before an equation doesn't
|
|
|
|
// make the LaTeX output different
|
|
|
|
// compared to "Exported LaTeX" ARRae
|
|
|
|
// Modified to work in a cleaner and hopefully more general way
|
|
|
|
// (JMarc)
|
|
|
|
outf += "\n";
|
|
|
|
++number_of_newlines;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (mathed_env == LM_EN_DISPLAY){
|
|
|
|
os << "\\[\n";
|
|
|
|
} else {
|
|
|
|
os << "\\begin{"
|
|
|
|
<< latex_mathenv[mathed_env]
|
|
|
|
<< "}\n";
|
|
|
|
}
|
|
|
|
++number_of_newlines;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (label && label[0] > ' ' && mathed_env == LM_EN_EQUATION){
|
|
|
|
os << "\\label{"
|
|
|
|
<< label
|
|
|
|
<< "}\n";
|
|
|
|
++number_of_newlines;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->Write(os);
|
|
|
|
|
|
|
|
if (mathed_env == LM_EN_INTEXT){
|
|
|
|
if (fragile) os << "\\protect";
|
|
|
|
os << " \\)";
|
|
|
|
}
|
|
|
|
else if (mathed_env == LM_EN_DISPLAY) {
|
|
|
|
os << "\\]\n";
|
|
|
|
++number_of_newlines;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
os << "\n\\end{"
|
|
|
|
<< latex_mathenv[mathed_env]
|
|
|
|
<< "}\n";
|
|
|
|
number_of_newlines += 2;
|
|
|
|
}
|
|
|
|
*newlines = number_of_newlines;
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|