]> git.lyx.org Git - features.git/blob - src/mathed/math_write.C
233635402657db86006010b3bf9fd78a14ced960
[features.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         if (fragile &&
103             (strcmp(l->name, "overbrace") == 0 ||
104              strcmp(l->name, "underbrace") == 0 ||
105              strcmp(l->name, "overleftarrow") == 0 ||
106              strcmp(l->name, "overrightarrow") == 0))
107                 os << "\\protect";
108         os << '\\' << l->name << '{';
109         MathParInset::Write(os, fragile);  
110         os << '}';
111 }
112
113
114 void MathAccentInset::Write(ostream & os, bool fragile)
115 {
116         latexkeys * l = lm_get_key_by_id(code, LM_TK_ACCENT);
117         os << '\\' << l->name;
118         if (code!= LM_not)
119                 os << '{';
120         else
121                 os << ' ';
122         
123         if (inset) {
124                 inset->Write(os, fragile);
125         } else {
126                 if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM) {
127                         os << '\\'
128                            << math_font_name[fn-LM_TC_RM]
129                            << '{';
130                 }
131                 if (MathIsSymbol(fn)) {
132                         latexkeys * l = lm_get_key_by_id(c, LM_TK_SYM);
133                         if (l) {
134                                 os << '\\' << l->name << ' ';
135                         }
136                 } else
137                         os << char(c);
138                 
139                 if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM)
140                         os << '}';
141         }
142         
143         if (code!= LM_not)
144                 os << '}';
145 }
146
147
148 void MathBigopInset::Write(ostream & os, bool /* fragile */)
149 {
150     bool limp = GetLimits();
151     
152     os << '\\' << name;
153     
154     if (limp && !(sym != LM_int && sym != LM_oint
155                   && (GetStyle() == LM_ST_DISPLAY)))
156             os << "\\limits ";
157     else 
158     if (!limp && (sym != LM_int && sym != LM_oint
159                   && (GetStyle() == LM_ST_DISPLAY)))
160             os << "\\nolimits ";
161     else 
162             os << ' ';
163 }
164
165
166 void MathFracInset::Write(ostream & os, bool fragile)
167 {
168         os << '\\' << name << '{';
169         MathParInset::Write(os, fragile);
170         os << "}{";
171         den->Write(os, fragile);
172         os << '}';
173 }
174
175
176 void MathParInset::Write(ostream & os, bool fragile)
177 {
178         if (!array) return;
179         int brace = 0;
180         latexkeys * l;
181         MathedIter data(array);
182         // hack
183         MathedRowSt const * crow = getRowSt();   
184         data.Reset();
185         
186         if (!Permit(LMPF_FIXED_SIZE)) { 
187                 l = lm_get_key_by_id(size, LM_TK_STY);
188                 if (l) {
189                         os << '\\' << l->name << ' ';
190                 }
191         }
192         while (data.OK()) {
193                 byte cx = data.GetChar();
194                 if (cx >= ' ') {
195                         string str = data.GetString();
196                         
197                         if (data.FCode() >= LM_TC_RM && data.FCode() <= LM_TC_TEXTRM) {
198                                 os << '\\' << math_font_name[data.FCode()-LM_TC_RM] << '{';
199                         }
200                         for (string::const_iterator s = str.begin();
201                              s != str.end(); ++s) {
202                                 byte c = *s;
203                                 if (MathIsSymbol(data.FCode())) {
204                                         l = lm_get_key_by_id(c, (data.FCode() == LM_TC_BSYM) ?
205                                                              LM_TK_BIGSYM : LM_TK_SYM);
206                                         if (l) {
207                                                 os << '\\' << l->name << ' ';
208                                         } else {
209 #warning this does not compile on gcc 2.97
210                                                 //lyxerr << "Illegal symbol code[" << c
211                                                 //   << " " << str.end() - s << " " << data.FCode() << "]";
212                                         }
213                                 } else {
214                                         // Is there a standard logical XOR?
215                                         if ((data.FCode() == LM_TC_TEX && c != '{' && c != '}') ||
216                                             (data.FCode() == LM_TC_SPECIAL))
217                                                 os << '\\';
218                                         else {
219                                                 if (c == '{') ++brace;
220                                                 if (c == '}') --brace;
221                                         }
222                                         if (c == '}' && data.FCode() == LM_TC_TEX && brace < 0) 
223                                                 lyxerr <<"Math warning: Unexpected closing brace."
224                                                        << endl;
225                                         else           
226                                                 os << char(c);
227                                 }
228                         }
229                         if (data.FCode()>= LM_TC_RM && data.FCode()<= LM_TC_TEXTRM)
230                                 os << '}';
231                 } else     
232                         if (MathIsInset(cx)) {
233                                 MathedInset * p = data.GetInset();
234                                 if (cx == LM_TC_UP)
235                                         os << "^{";
236                                 if (cx == LM_TC_DOWN)
237                                         os << "_{";
238                                 p->Write(os, fragile);
239                                 if (cx == LM_TC_UP || cx == LM_TC_DOWN)
240                                         os << '}';
241                                 data.Next();
242                         } else
243                                 switch (cx) {
244                                 case LM_TC_TAB:
245                                 {
246                                         os << " & ";
247                                         data.Next();
248                                         break;
249                                 }
250                                 case LM_TC_CR:
251                                 {
252                                         if (crow) {
253                                                 if (!crow->isNumbered()) {  
254                                                         os << "\\nonumber ";
255                                                 }
256                                                 if (!crow->getLabel().empty()) {
257                                                         os << "\\label{"
258                                                            << crow->getLabel()
259                                                            << "} ";
260                                                 }
261                                                 crow = crow->getNext();
262                                         }
263                                         if (fragile)
264                                                 os << "\\protect";
265                                         os << "\\\\\n";
266                                         ++number_of_newlines;
267                                         data.Next();
268                                         break;
269                                 }
270                                 default:
271                                         lyxerr << "WMath Error: unrecognized code[" << cx << "]";
272                                         return;
273                                 }     
274         }
275         
276         if (crow) {
277                 if (!crow->isNumbered()) {
278                         os << "\\nonumber ";
279                 }
280                 if (!crow->getLabel().empty()) {
281                         os << "\\label{"
282                            << crow->getLabel()
283                            << "} ";
284                 }
285         }
286
287         if (brace > 0)
288                 os << string(brace, '}');
289 }
290
291
292 void MathMatrixInset::Write(ostream & os, bool fragile)
293 {
294     if (GetType() == LM_OT_MATRIX){
295             if (fragile)
296                     os << "\\protect";
297             os << "\\begin{"
298                << name
299                << '}';
300         if (v_align == 't' || v_align == 'b') {
301                 os << '['
302                    << char(v_align)
303                    << ']';
304         }
305         os << '{'
306            << h_align
307            << "}\n";
308         ++number_of_newlines;
309     }
310     MathParInset::Write(os, fragile);
311     if (GetType() == LM_OT_MATRIX){
312             os << "\n";
313             if (fragile)
314                     os << "\\protect";
315             os << "\\end{"
316                << name
317                << '}';
318         ++number_of_newlines;
319     }
320 }
321
322 void mathed_write(MathParInset * p, ostream & os, int * newlines,
323                   bool fragile, string const & label)
324 {
325    number_of_newlines = 0;
326    short mathed_env = p->GetType();
327
328    if (mathed_env == LM_OT_MIN) {
329            if (fragile) os << "\\protect";
330            os << "\\( "; // changed from " \\( " (Albrecht Dress)
331    } 
332    else {
333      if (mathed_env == LM_OT_PAR){
334              os << "\\[\n";
335      } else {
336              os << "\\begin{"
337                 << latex_mathenv[mathed_env]
338                 << "}";
339              if (is_multicolumn(mathed_env)) {
340                      if (mathed_env != LM_OT_ALIGNAT
341                          && mathed_env != LM_OT_ALIGNATN)
342                              os << "%";
343                      os << "{" << p->GetColumns()/2 << "}";
344              }
345              os << "\n";
346      }
347      ++number_of_newlines;
348    }
349    
350    if (!label.empty() && label[0] > ' ' && is_singlely_numbered(mathed_env)) {
351            os << "\\label{"
352               << label
353               << "}\n";
354      ++number_of_newlines;
355    }
356
357    p->Write(os, fragile);
358    
359    if (mathed_env == LM_OT_MIN){
360            if (fragile) os << "\\protect";
361            os << " \\)";
362    }
363    else if (mathed_env == LM_OT_PAR) {
364            os << "\\]\n";
365      ++number_of_newlines;
366    }
367    else {
368            os << "\n\\end{"
369               << latex_mathenv[mathed_env]
370               << "}\n";
371      number_of_newlines += 2;
372    }
373    *newlines = number_of_newlines;
374 }