/* * File: math_write.h * Purpose: Write math paragraphs in LaTeX * Author: Alejandro Aguilar Sierra * Created: January 1996 * Description: * * Dependencies: Xlib, XForms * * Copyright: (c) 1996, 1997 Alejandro Aguilar Sierra * * 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 #include "LString.h" #include "math_inset.h" #include "math_iter.h" #include "math_parser.h" extern char const *latex_mathenv[]; extern char *latex_mathspace[]; // quite a hack i know. Should be done with return values... static int number_of_newlines; char const *math_font_name[] = { "mathrm", "mathcal", "mathbf", "mathsf", "mathtt", "mathit", "textrm" }; void MathSpaceInset::Write(FILE *outf) { if (space>=0 && space<6) { LString output; MathSpaceInset::Write(output); fprintf(outf, "%s", output.c_str()); } } void MathSpaceInset::Write(LString &outf) { if (space>=0 && space<6) { outf += '\\'; outf += latex_mathspace[space]; outf += ' '; } } void MathDotsInset::Write(FILE *outf) { LString output; MathDotsInset::Write(output); fprintf(outf, "%s", output.c_str()); } void MathDotsInset::Write(LString &outf) { outf += '\\'; outf += name; outf += ' '; } void MathSqrtInset::Write(FILE *outf) { LString output; MathSqrtInset::Write(output); fprintf(outf, "%s", output.c_str()); } void MathSqrtInset::Write(LString &outf) { outf += '\\'; outf += name; outf += '{'; MathParInset::Write(outf); outf += '}'; } void MathDelimInset::Write(FILE *outf) { LString output; MathDelimInset::Write(output); fprintf(outf, "%s", output.c_str()); } void MathDelimInset::Write(LString &outf) { 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; outf += "\\left"; if (l) { outf += '\\'; outf += l->name; outf += ' '; } else { if (left=='{' || left=='}') { outf += '\\'; outf += (char) left; outf += ' '; } else { outf += (char) left; outf += ' '; } } MathParInset::Write(outf); outf += "\\right"; if (r) { outf += '\\'; outf += r->name; outf += ' '; } else { if (right=='{' || right=='}') { outf += '\\'; outf += (char) right; outf += ' '; } else { outf += (char) right; outf += ' '; } } } void MathDecorationInset::Write(FILE *outf) { LString output; MathDecorationInset::Write(output); fprintf(outf, "%s", output.c_str()); } void MathDecorationInset::Write(LString &outf) { latexkeys* l = lm_get_key_by_id(deco, LM_TK_WIDE); outf += '\\'; outf += l->name; outf += '{'; MathParInset::Write(outf); outf += '}'; } void MathAccentInset::Write(FILE *outf) { LString output; MathAccentInset::Write(output); fprintf(outf, "%s", output.c_str()); } void MathAccentInset::Write(LString &outf) { latexkeys* l = lm_get_key_by_id(code, LM_TK_ACCENT); outf += '\\'; outf += l->name; if (code!=LM_not) outf += '{'; else outf += ' '; if (inset) { inset->Write(outf); } else { if (fn>=LM_TC_RM && fn<=LM_TC_TEXTRM) { outf += '\\'; outf += math_font_name[fn-LM_TC_RM]; outf += '{'; } if (MathIsSymbol(fn)) { latexkeys *l = lm_get_key_by_id(c, LM_TK_SYM); if (l) { outf += '\\'; outf += l->name; outf += ' '; } } else outf += (char) c; if (fn>=LM_TC_RM && fn<=LM_TC_TEXTRM) outf += '}'; } if (code!=LM_not) outf += '}'; } void MathBigopInset::Write(FILE *outf) { LString output; MathBigopInset::Write(output); fprintf(outf, "%s", output.c_str()); } void MathBigopInset::Write(LString &outf) { bool limp = GetLimits(); outf += '\\'; outf += name; if (limp && !(sym!=LM_int && sym!=LM_oint && (GetStyle()==LM_ST_DISPLAY))) outf += "\\limits "; else if (!limp && (sym!=LM_int && sym!=LM_oint && (GetStyle()==LM_ST_DISPLAY))) outf += "\\nolimits "; else outf += ' '; } void MathFracInset::Write(FILE *outf) { LString output; MathFracInset::Write(output); fprintf(outf, "%s", output.c_str()); } void MathFracInset::Write(LString &outf) { outf += '\\'; outf += name; outf += '{'; MathParInset::Write(outf); outf += "}{"; den->Write(outf); outf += '}'; } void MathParInset::Write(FILE *outf) { if (!array) return; LString output; MathParInset::Write(output); fprintf(outf, "%s", output.c_str()); } void MathParInset::Write(LString &outf) { 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) { outf += '\\'; outf += l->name; outf += ' '; } } 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) { outf += '\\'; outf += math_font_name[data.FCode()-LM_TC_RM]; outf += '{'; } 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) { outf += '\\'; outf += l->name; outf += ' '; } else { fprintf(stderr, "Illegal symbol code[%u %d %d]", *s, ls, data.FCode()); } } else { // Is there a standard logical XOR? if ((data.FCode()==LM_TC_TEX && *s!='{' && *s!='}') || (data.FCode()==LM_TC_SPECIAL)) outf += '\\'; else { if (*s=='{') brace++; if (*s=='}') brace--; } if (*s=='}' && data.FCode()==LM_TC_TEX && brace<0) fprintf(stderr, "Math warning: Unexpected closing brace.\n"); else outf += (char) *s; } s++; ls--; } if (data.FCode()>=LM_TC_RM && data.FCode()<=LM_TC_TEXTRM) outf += '}'; } else if (MathIsInset(cx)) { MathedInset *p = data.GetInset(); if (cx==LM_TC_UP) outf += "^{"; if (cx==LM_TC_DOWN) outf += "_{"; p->Write(outf); if (cx==LM_TC_UP || cx==LM_TC_DOWN) outf += '}'; data.Next(); } else switch(cx) { case LM_TC_TAB: { outf += " & "; data.Next(); break; } case LM_TC_CR: { if (crow) { if (!crow->isNumbered()) { outf +="\\nonumber "; } if (crow->getLabel()) { outf += "\\label{"; outf += crow->getLabel(); outf += "} "; } crow = crow->getNext(); } outf += "\\\\\n"; number_of_newlines++; data.Next(); break; } default: fprintf(stderr, "WMath Error: unrecognized code[%d]", cx); return; } } if (crow) { if (!crow->isNumbered()) { outf +="\\nonumber "; } if (crow->getLabel()) { outf += "\\label{"; outf += crow->getLabel(); outf += "} "; } } while (brace>0) { outf += '}'; brace--; } } void MathMatrixInset::Write(FILE *outf) { LString output; MathMatrixInset::Write(output); fprintf(outf, "%s", output.c_str()); } void MathMatrixInset::Write(LString &outf) { if (GetType() == LM_OT_MATRIX){ outf += "\\begin{"; outf += name; outf += '}'; if (v_align=='t' || v_align=='b') { outf += '['; outf += (char) v_align; outf += ']'; } outf += '{'; outf += h_align; outf += "}\n"; number_of_newlines++; } MathParInset::Write(outf); if (GetType() == LM_OT_MATRIX){ outf += "\n\\end{"; outf += name; outf += '}'; number_of_newlines++; } } void mathed_write(MathParInset* p, FILE* outf, int* newlines, char fragile, char const* label) { LString output; mathed_write(p, output, newlines, fragile, label); fprintf(outf, "%s", output.c_str()); } extern int tex_code_break_column; void mathed_write(MathParInset* p, LString& outf, int* newlines, char fragile, char const* label) { number_of_newlines = 0; short mathed_env = p->GetType(); if (mathed_env==LM_EN_INTEXT) { if (fragile) outf += "\\protect"; outf += "\\( "; // changed from " \\( " (Albrecht Dress) } else { if (! outf.suffixIs('\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++; } if (mathed_env==LM_EN_DISPLAY){ outf += "\\[\n"; } else { outf += "\\begin{"; outf += latex_mathenv[mathed_env]; outf += "}\n"; } number_of_newlines++; } if (label && label[0]>' ' && mathed_env==LM_EN_EQUATION){ outf += "\\label{"; outf += label; outf += "}\n"; number_of_newlines++; } p->Write(outf); if (mathed_env==LM_EN_INTEXT){ if (fragile) outf += "\\protect"; outf += " \\)"; } else if (mathed_env==LM_EN_DISPLAY){ outf += "\\]\n"; number_of_newlines++; } else { outf += "\n\\end{"; outf += latex_mathenv[mathed_env]; outf += "}\n"; number_of_newlines+=2; } *newlines = number_of_newlines; }