3 * Purpose: Write math paragraphs in LaTeX
4 * Author: Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
5 * Created: January 1996
8 * Dependencies: Xlib, XForms
10 * Copyright: (c) 1996, 1997 Alejandro Aguilar Sierra
12 * Version: 0.8beta, Mathed & Lyx project.
14 * You are free to use and modify this code under the terms of
15 * the GNU General Public Licence version 2 or later.
21 #include "math_inset.h"
22 #include "math_iter.h"
23 #include "math_parser.h"
24 #include "support/lstrings.h"
27 extern char const * latex_mathenv[];
28 extern char * latex_mathspace[];
30 // quite a hack i know. Should be done with return values...
31 static int number_of_newlines;
33 char const * math_font_name[] = {
45 MathSpaceInset::Write(ostream & os)
47 #ifdef USE_OSTREAM_ONLY
48 if (space >= 0 && space < 6) {
49 os << '\\' << latex_mathspace[space] << ' ';
52 if (space >= 0 && space < 6) {
54 MathSpaceInset::Write(output);
61 #ifndef USE_OSTREAM_ONLY
63 MathSpaceInset::Write(string & outf)
65 if (space >= 0 && space < 6) {
67 outf += latex_mathspace[space];
75 MathDotsInset::Write(ostream & os)
77 #ifdef USE_OSTREAM_ONLY
78 os << '\\' << name << ' ';
81 MathDotsInset::Write(output);
87 #ifndef USE_OSTREAM_ONLY
89 MathDotsInset::Write(string & outf)
98 void MathSqrtInset::Write(ostream & os)
100 #ifdef USE_OSTREAM_ONLY
101 os << '\\' << name << '{';
102 MathParInset::Write(os);
106 MathSqrtInset::Write(output);
112 #ifndef USE_OSTREAM_ONLY
113 void MathSqrtInset::Write(string & outf)
118 MathParInset::Write(outf);
124 void MathDelimInset::Write(ostream & os)
126 #ifdef USE_OSTREAM_ONLY
127 latexkeys * l = (left != '|') ? lm_get_key_by_id(left, LM_TK_SYM): 0;
128 latexkeys * r = (right != '|') ? lm_get_key_by_id(right, LM_TK_SYM): 0;
131 os << '\\' << l->name << ' ';
133 if (left == '{' || left == '}') {
134 os << '\\' << char(left) << ' ';
136 os << char(left) << ' ';
139 MathParInset::Write(os);
142 os << '\\' << r->name << ' ';
144 if (right == '{' || right == '}') {
145 os << '\\' << char(right) << ' ';
147 os << char(right) << ' ';
152 MathDelimInset::Write(output);
158 #ifndef USE_OSTREAM_ONLY
159 void MathDelimInset::Write(string & outf)
161 latexkeys * l = (left != '|') ? lm_get_key_by_id(left, LM_TK_SYM): 0;
162 latexkeys * r = (right != '|') ? lm_get_key_by_id(right, LM_TK_SYM): 0;
169 if (left == '{' || left == '}') {
178 MathParInset::Write(outf);
185 if (right == '{' || right == '}') {
198 void MathDecorationInset::Write(ostream & os)
200 #ifdef USE_OSTREAM_ONLY
201 latexkeys * l = lm_get_key_by_id(deco, LM_TK_WIDE);
202 os << '\\' << l->name << '{';
203 MathParInset::Write(os);
207 MathDecorationInset::Write(output);
213 #ifndef USE_OSTREAM_ONLY
214 void MathDecorationInset::Write(string & outf)
216 latexkeys * l = lm_get_key_by_id(deco, LM_TK_WIDE);
220 MathParInset::Write(outf);
226 void MathAccentInset::Write(ostream & os)
228 #ifdef USE_OSTREAM_ONLY
229 latexkeys * l = lm_get_key_by_id(code, LM_TK_ACCENT);
230 os << '\\' << l->name;
239 if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM) {
241 << math_font_name[fn-LM_TC_RM]
244 if (MathIsSymbol(fn)) {
245 latexkeys * l = lm_get_key_by_id(c, LM_TK_SYM);
247 os << '\\' << l->name << ' ';
252 if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM)
260 MathAccentInset::Write(output);
266 #ifndef USE_OSTREAM_ONLY
267 void MathAccentInset::Write(string & outf)
269 latexkeys * l = lm_get_key_by_id(code, LM_TK_ACCENT);
280 if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM) {
282 outf += math_font_name[fn-LM_TC_RM];
285 if (MathIsSymbol(fn)) {
286 latexkeys *l = lm_get_key_by_id(c, LM_TK_SYM);
295 if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM)
305 void MathBigopInset::Write(ostream & os)
307 #ifdef USE_OSTREAM_ONLY
308 bool limp = GetLimits();
312 if (limp && !(sym != LM_int && sym != LM_oint
313 && (GetStyle() == LM_ST_DISPLAY)))
316 if (!limp && (sym != LM_int && sym != LM_oint
317 && (GetStyle() == LM_ST_DISPLAY)))
323 MathBigopInset::Write(output);
329 #ifndef USE_OSTREAM_ONLY
330 void MathBigopInset::Write(string & outf)
332 bool limp = GetLimits();
337 if (limp && !(sym!= LM_int && sym!= LM_oint && (GetStyle() == LM_ST_DISPLAY)))
340 if (!limp && (sym!= LM_int && sym!= LM_oint && (GetStyle() == LM_ST_DISPLAY)))
341 outf += "\\nolimits ";
348 void MathFracInset::Write(ostream & os)
350 #ifdef USE_OSTREAM_ONLY
351 os << '\\' << name << '{';
352 MathParInset::Write(os);
358 MathFracInset::Write(output);
364 #ifndef USE_OSTREAM_ONLY
365 void MathFracInset::Write(string & outf)
370 MathParInset::Write(outf);
378 void MathParInset::Write(ostream & os)
380 #ifdef USE_OSTREAM_ONLY
384 MathedIter data(array);
386 MathedRowSt const * crow = getRowSt();
389 if (!Permit(LMPF_FIXED_SIZE)) {
390 l = lm_get_key_by_id(size, LM_TK_STY);
392 os << '\\' << l->name << ' ';
396 byte cx = data.GetChar();
399 byte * s = data.GetString(ls);
401 if (data.FCode() >= LM_TC_RM && data.FCode() <= LM_TC_TEXTRM) {
402 os << '\\' << math_font_name[data.FCode()-LM_TC_RM] << '{';
405 if (MathIsSymbol(data.FCode())) {
406 l = lm_get_key_by_id(*s, (data.FCode() == LM_TC_BSYM) ?
407 LM_TK_BIGSYM : LM_TK_SYM);
409 os << '\\' << l->name << ' ';
411 lyxerr << "Illegal symbol code[" << *s
412 << " " << ls << " " << data.FCode() << "]";
415 // Is there a standard logical XOR?
416 if ((data.FCode() == LM_TC_TEX && *s != '{' && *s != '}') ||
417 (data.FCode() == LM_TC_SPECIAL))
420 if (*s == '{') ++brace;
421 if (*s == '}') --brace;
423 if (*s == '}' && data.FCode() == LM_TC_TEX && brace < 0)
424 lyxerr <<"Math warning: Unexpected closing brace."
431 if (data.FCode()>= LM_TC_RM && data.FCode()<= LM_TC_TEXTRM)
434 if (MathIsInset(cx)) {
435 MathedInset * p = data.GetInset();
438 if (cx == LM_TC_DOWN)
441 if (cx == LM_TC_UP || cx == LM_TC_DOWN)
455 if (!crow->isNumbered()) {
458 if (crow->getLabel()) {
463 crow = crow->getNext();
466 ++number_of_newlines;
471 lyxerr << "WMath Error: unrecognized code[" << cx << "]";
477 if (!crow->isNumbered()) {
480 if (crow->getLabel()) {
492 // Something like this should work too:
493 os << string(brace, '}'); // not one-off error I hope.
498 MathParInset::Write(output);
504 #ifndef USE_OSTREAM_ONLY
505 void MathParInset::Write(string & outf)
510 MathedIter data(array);
512 MathedRowSt const * crow = getRowSt();
515 if (!Permit(LMPF_FIXED_SIZE)) {
516 l = lm_get_key_by_id(size, LM_TK_STY);
524 byte cx = data.GetChar();
527 byte * s = data.GetString(ls);
529 if (data.FCode()>= LM_TC_RM && data.FCode()<= LM_TC_TEXTRM) {
531 outf += math_font_name[data.FCode()-LM_TC_RM];
535 if (MathIsSymbol(data.FCode())) {
536 l = lm_get_key_by_id(*s,(data.FCode() == LM_TC_BSYM)?LM_TK_BIGSYM:LM_TK_SYM);
542 lyxerr << "Illegal symbol code[" << *s
543 << " " << ls << " " << data.FCode() << "]";
546 // Is there a standard logical XOR?
547 if ((data.FCode() == LM_TC_TEX && *s!= '{' && *s!= '}') ||
548 (data.FCode() == LM_TC_SPECIAL))
551 if (*s == '{') ++brace;
552 if (*s == '}') --brace;
554 if (*s == '}' && data.FCode() == LM_TC_TEX && brace<0)
555 lyxerr <<"Math warning: Unexpected closing brace."
562 if (data.FCode()>= LM_TC_RM && data.FCode()<= LM_TC_TEXTRM)
565 if (MathIsInset(cx)) {
566 MathedInset *p = data.GetInset();
569 if (cx == LM_TC_DOWN)
572 if (cx == LM_TC_UP || cx == LM_TC_DOWN)
586 if (!crow->isNumbered()) {
587 outf += "\\nonumber ";
589 if (crow->getLabel()) {
591 outf += crow->getLabel();
594 crow = crow->getNext();
597 ++number_of_newlines;
602 lyxerr << "WMath Error: unrecognized code[" << cx << "]";
608 if (!crow->isNumbered()) {
609 outf += "\\nonumber ";
611 if (crow->getLabel()) {
613 outf += crow->getLabel();
625 void MathMatrixInset::Write(ostream & os)
627 #ifdef USE_OSTREAM_ONLY
628 if (GetType() == LM_OT_MATRIX){
632 if (v_align == 't' || v_align == 'b') {
640 ++number_of_newlines;
642 MathParInset::Write(os);
643 if (GetType() == LM_OT_MATRIX){
647 ++number_of_newlines;
651 MathMatrixInset::Write(output);
657 #ifndef USE_OSTREAM_ONLY
658 void MathMatrixInset::Write(string & outf)
660 if (GetType() == LM_OT_MATRIX){
664 if (v_align == 't' || v_align == 'b') {
666 outf += char(v_align);
672 ++number_of_newlines;
674 MathParInset::Write(outf);
675 if (GetType() == LM_OT_MATRIX){
679 ++number_of_newlines;
685 void mathed_write(MathParInset * p, ostream & os, int * newlines,
686 char fragile, char const * label)
688 #ifdef USE_OSTREAM_ONLY
689 number_of_newlines = 0;
690 short mathed_env = p->GetType();
692 if (mathed_env == LM_EN_INTEXT) {
693 if (fragile) os << "\\protect";
694 os << "\\( "; // changed from " \\( " (Albrecht Dress)
698 // Is this '\n' really needed, what can go wrong
699 //if it is not there?
702 if (!suffixIs(outf, '\n')) {
703 // in batchmode we need to make sure
704 // a space before an equation doesn't
705 // make the LaTeX output different
706 // compared to "Exported LaTeX" ARRae
707 // Modified to work in a cleaner and hopefully more general way
710 ++number_of_newlines;
713 if (mathed_env == LM_EN_DISPLAY){
717 << latex_mathenv[mathed_env]
720 ++number_of_newlines;
723 if (label && label[0] > ' ' && mathed_env == LM_EN_EQUATION){
727 ++number_of_newlines;
732 if (mathed_env == LM_EN_INTEXT){
733 if (fragile) os << "\\protect";
736 else if (mathed_env == LM_EN_DISPLAY) {
738 ++number_of_newlines;
742 << latex_mathenv[mathed_env]
744 number_of_newlines += 2;
746 *newlines = number_of_newlines;
749 mathed_write(p, output, newlines, fragile, label);
755 #ifndef USE_OSTREAM_ONLY
756 void mathed_write(MathParInset * p, string & outf, int * newlines,
757 char fragile, char const * label)
759 number_of_newlines = 0;
760 short mathed_env = p->GetType();
762 if (mathed_env == LM_EN_INTEXT) {
763 if (fragile) outf += "\\protect";
764 outf += "\\( "; // changed from " \\( " (Albrecht Dress)
767 if (!suffixIs(outf, '\n')) {
768 // in batchmode we need to make sure
769 // a space before an equation doesn't
770 // make the LaTeX output different
771 // compared to "Exported LaTeX" ARRae
772 // Modified to work in a cleaner and hopefully more general way
775 ++number_of_newlines;
777 if (mathed_env == LM_EN_DISPLAY){
782 outf += latex_mathenv[mathed_env];
785 ++number_of_newlines;
788 if (label && label[0]>' ' && mathed_env == LM_EN_EQUATION){
792 ++number_of_newlines;
797 if (mathed_env == LM_EN_INTEXT){
798 if (fragile) outf += "\\protect";
801 else if (mathed_env == LM_EN_DISPLAY){
803 ++number_of_newlines;
807 outf += latex_mathenv[mathed_env];
809 number_of_newlines += 2;
811 *newlines = number_of_newlines;