]> git.lyx.org Git - lyx.git/blob - src/mathed/math_write.C
Hopefully fix the problem with stateText() in lyxfont.C
[lyx.git] / src / mathed / math_write.C
1 /*
2  *  File:        math_write.h
3  *  Purpose:     Write math paragraphs in LaTeX
4  *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx> 
5  *  Created:     January 1996
6  *  Description: 
7  *
8  *  Dependencies: Xlib, XForms
9  *
10  *  Copyright: 1996, 1997 Alejandro Aguilar Sierra
11  *
12  *   Version: 0.8beta, Mathed & Lyx project.
13  *
14  *   You are free to use and modify this code under the terms of
15  *   the GNU General Public Licence version 2 or later.
16  */
17
18 #include <config.h>
19
20 #include "LString.h"
21 #include "math_inset.h"
22 #include "math_iter.h"
23 #include "math_parser.h"
24 #include "support/lstrings.h"
25 #include "debug.h"
26
27 using std::ostream;
28 using std::endl;
29
30 extern char const * latex_mathenv[];
31 extern char * latex_mathspace[];
32
33 // quite a hack i know. Should be done with return values...
34 static int number_of_newlines;
35
36 char const * math_font_name[] = {
37    "mathrm",
38    "mathcal",
39    "mathbf",
40    "mathsf",
41    "mathtt",
42    "mathit",
43    "textrm"
44 };
45
46
47 void
48 MathSpaceInset::Write(ostream & os, bool /* fragile */)
49 {
50    if (space >= 0 && space < 6) {
51            os << '\\' << latex_mathspace[space] << ' ';
52    }
53 }
54
55
56 void
57 MathDotsInset::Write(ostream & os, bool /* fragile */)
58 {
59         os << '\\' << name << ' ';
60 }
61
62
63 void MathSqrtInset::Write(ostream & os, bool fragile)
64 {
65         os << '\\' << name << '{';
66         MathParInset::Write(os, fragile); 
67         os << '}';
68 }
69
70
71 void MathDelimInset::Write(ostream & os, bool fragile)
72 {
73     latexkeys * l = (left != '|') ? lm_get_key_by_id(left, LM_TK_SYM): 0;
74     latexkeys * r = (right != '|') ? lm_get_key_by_id(right, LM_TK_SYM): 0;
75     os << "\\left";
76     if (l) {
77             os << '\\' << l->name << ' ';
78     } else {
79         if (left == '{' || left == '}') {
80                 os << '\\' << char(left) << ' ';
81         } else {
82                 os << char(left) << ' ';
83         }
84     }
85    MathParInset::Write(os, fragile);
86    os << "\\right";
87    if (r) {
88            os << '\\' << r->name << ' ';
89    } else {
90        if (right == '{' || right == '}') {
91                os << '\\' << char(right) << ' ';
92       } else {
93               os << char(right) << ' ';
94       }
95    }
96 }
97
98
99 void MathDecorationInset::Write(ostream & os, bool fragile)
100 {
101         latexkeys * l = lm_get_key_by_id(deco, LM_TK_WIDE);
102         os << '\\' << l->name << '{';
103         MathParInset::Write(os, fragile);  
104         os << '}';
105 }
106
107
108 void MathAccentInset::Write(ostream & os, bool fragile)
109 {
110         latexkeys * l = lm_get_key_by_id(code, LM_TK_ACCENT);
111         os << '\\' << l->name;
112         if (code!= LM_not)
113                 os << '{';
114         else
115                 os << ' ';
116         
117         if (inset) {
118                 inset->Write(os, fragile);
119         } else {
120                 if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM) {
121                         os << '\\'
122                            << math_font_name[fn-LM_TC_RM]
123                            << '{';
124                 }
125                 if (MathIsSymbol(fn)) {
126                         latexkeys * l = lm_get_key_by_id(c, LM_TK_SYM);
127                         if (l) {
128                                 os << '\\' << l->name << ' ';
129                         }
130                 } else
131                         os << char(c);
132                 
133                 if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM)
134                         os << '}';
135         }
136         
137         if (code!= LM_not)
138                 os << '}';
139 }
140
141
142 void MathBigopInset::Write(ostream & os, bool /* fragile */)
143 {
144     bool limp = GetLimits();
145     
146     os << '\\' << name;
147     
148     if (limp && !(sym != LM_int && sym != LM_oint
149                   && (GetStyle() == LM_ST_DISPLAY)))
150             os << "\\limits ";
151     else 
152     if (!limp && (sym != LM_int && sym != LM_oint
153                   && (GetStyle() == LM_ST_DISPLAY)))
154             os << "\\nolimits ";
155     else 
156             os << ' ';
157 }
158
159
160 void MathFracInset::Write(ostream & os, bool fragile)
161 {
162         os << '\\' << name << '{';
163         MathParInset::Write(os, fragile);
164         os << "}{";
165         den->Write(os, fragile);
166         os << '}';
167 }
168
169
170 void MathParInset::Write(ostream & os, bool fragile)
171 {
172         if (!array) return;
173         int brace = 0;
174         latexkeys * l;
175         MathedIter data(array);
176         // hack
177         MathedRowSt const * crow = getRowSt();   
178         data.Reset();
179         
180         if (!Permit(LMPF_FIXED_SIZE)) { 
181                 l = lm_get_key_by_id(size, LM_TK_STY);
182                 if (l) {
183                         os << '\\' << l->name << ' ';
184                 }
185         }
186         while (data.OK()) {
187                 byte cx = data.GetChar();
188                 if (cx >= ' ') {
189                         int ls;
190                         byte * s = data.GetString(ls);
191                         
192                         if (data.FCode() >= LM_TC_RM && data.FCode() <= LM_TC_TEXTRM) {
193                                 os << '\\' << math_font_name[data.FCode()-LM_TC_RM] << '{';
194                         }
195                         while (ls > 0) {
196                                 if (MathIsSymbol(data.FCode())) {
197                                         l = lm_get_key_by_id(*s, (data.FCode() == LM_TC_BSYM) ?
198                                                              LM_TK_BIGSYM : LM_TK_SYM);
199                                         if (l) {
200                                                 os << '\\' << l->name << ' ';
201                                         } else { 
202                                                 lyxerr << "Illegal symbol code[" << *s
203                                                        << " " << ls << " " << data.FCode() << "]";
204                                         }
205                                 } else {
206                                         // Is there a standard logical XOR?
207                                         if ((data.FCode() == LM_TC_TEX && *s != '{' && *s != '}') ||
208                                             (data.FCode() == LM_TC_SPECIAL))
209                                                 os << '\\';
210                                         else {
211                                                 if (*s == '{') ++brace;
212                                                 if (*s == '}') --brace;
213                                         }
214                                         if (*s == '}' && data.FCode() == LM_TC_TEX && brace < 0) 
215                                                 lyxerr <<"Math warning: Unexpected closing brace."
216                                                        << endl;
217                                         else           
218                                                 os << char(*s);
219                                 }
220                                 ++s; --ls;
221                         }
222                         if (data.FCode()>= LM_TC_RM && data.FCode()<= LM_TC_TEXTRM)
223                                 os << '}';
224                 } else     
225                         if (MathIsInset(cx)) {
226                                 MathedInset * p = data.GetInset();
227                                 if (cx == LM_TC_UP)
228                                         os << "^{";
229                                 if (cx == LM_TC_DOWN)
230                                         os << "_{";
231                                 p->Write(os, fragile);
232                                 if (cx == LM_TC_UP || cx == LM_TC_DOWN)
233                                         os << '}';
234                                 data.Next();
235                         } else
236                                 switch(cx) {
237                                 case LM_TC_TAB:
238                                 {
239                                         os << " & ";
240                                         data.Next();
241                                         break;
242                                 }
243                                 case LM_TC_CR:
244                                 {
245                                         if (crow) {
246                                                 if (!crow->isNumbered()) {  
247                                                         os << "\\nonumber ";
248                                                 }
249                                                 if (crow->getLabel()) {
250                                                         os << "\\label{"
251                                                            << crow->getLabel()
252                                                            << "} ";
253                                                 }
254                                                 crow = crow->getNext();
255                                         }
256                                         if (fragile)
257                                                 os << "\\protect";
258                                         os << "\\\\\n";
259                                         ++number_of_newlines;
260                                         data.Next();
261                                         break;
262                                 }
263                                 default:
264                                         lyxerr << "WMath Error: unrecognized code[" << cx << "]";
265                                         return;
266                                 }     
267         }
268         
269         if (crow) {
270                 if (!crow->isNumbered()) {
271                         os << "\\nonumber ";
272                 }
273                 if (crow->getLabel()) {
274                         os << "\\label{"
275                            << crow->getLabel()
276                            << "} ";
277                 }
278         }
279
280         // CHECK
281         // Just make sure that the correct number of braces are output.
282         // (Lgb)
283 #if 0
284         while (brace > 0) {
285                 os << '}';
286                 --brace;
287         }
288 #else
289         // Something like this should work too:
290         os << string(brace, '}'); // not one-off error I hope.
291 #endif
292 }
293
294
295 void MathMatrixInset::Write(ostream & os, bool fragile)
296 {
297     if (GetType() == LM_OT_MATRIX){
298             if (fragile)
299                     os << "\\protect";
300             os << "\\begin{"
301                << name
302                << '}';
303         if (v_align == 't' || v_align == 'b') {
304                 os << '['
305                    << char(v_align)
306                    << ']';
307         }
308         os << '{'
309            << h_align
310            << "}\n";
311         ++number_of_newlines;
312     }
313     MathParInset::Write(os, fragile);
314     if (GetType() == LM_OT_MATRIX){
315             os << "\n";
316             if (fragile)
317                     os << "\\protect";
318             os << "\\end{"
319                << name
320                << '}';
321         ++number_of_newlines;
322     }
323 }
324
325
326 void mathed_write(MathParInset * p, ostream & os, int * newlines,
327                   bool fragile, char const * label)
328 {
329    number_of_newlines = 0;
330    short mathed_env = p->GetType();
331
332    if (mathed_env == LM_EN_INTEXT) {
333            if (fragile) os << "\\protect";
334            os << "\\( "; // changed from " \\( " (Albrecht Dress)
335    } 
336    else {
337            // CHECK
338            // Is this '\n' really needed, what can go wrong
339            //if it is not there? The reason why I want to avoid this is
340            // because of the "backlook" into the output stream.
341            // Lgb.
342 #if 0
343      if (!suffixIs(outf, '\n')) {
344        // in batchmode we need to make sure
345        // a space before an equation doesn't
346        // make the LaTeX output different 
347        // compared to "Exported LaTeX"  ARRae
348        // Modified to work in a cleaner and hopefully more general way
349        // (JMarc)
350        outf += "\n";
351        ++number_of_newlines;
352      }
353 #endif
354      if (mathed_env == LM_EN_DISPLAY){
355              os << "\\[\n";
356      } else {
357              os << "\\begin{"
358                 << latex_mathenv[mathed_env]
359                 << "}\n";
360      }
361      ++number_of_newlines;
362    }
363    
364    if (label && label[0] > ' ' && mathed_env == LM_EN_EQUATION){
365            os << "\\label{"
366               << label
367               << "}\n";
368      ++number_of_newlines;
369    }
370
371    p->Write(os, fragile);
372    
373    if (mathed_env == LM_EN_INTEXT){
374            if (fragile) os << "\\protect";
375            os << " \\)";
376    }
377    else if (mathed_env == LM_EN_DISPLAY) {
378            os << "\\]\n";
379      ++number_of_newlines;
380    }
381    else {
382            os << "\n\\end{"
383               << latex_mathenv[mathed_env]
384               << "}\n";
385      number_of_newlines += 2;
386    }
387    *newlines = number_of_newlines;
388 }