]> git.lyx.org Git - lyx.git/blob - src/mathed/math_write.C
my changes during the holidyas...i expect some compilers to have some problems, but...
[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: (c) 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 extern char const * latex_mathenv[];
28 extern char * latex_mathspace[];
29
30 // quite a hack i know. Should be done with return values...
31 static int number_of_newlines;
32
33 char const * math_font_name[] = {
34    "mathrm",
35    "mathcal",
36    "mathbf",
37    "mathsf",
38    "mathtt",
39    "mathit",
40    "textrm"
41 };
42
43
44 void
45 MathSpaceInset::Write(ostream & os)
46
47    if (space >= 0 && space < 6) {
48        string output;
49        MathSpaceInset::Write(output);
50        os << output;
51    }
52 }
53
54
55 void
56 MathSpaceInset::Write(string & outf)
57
58    if (space >= 0 && space < 6) {
59        outf += '\\';
60        outf += latex_mathspace[space];
61        outf += ' ';
62    }
63 }
64
65
66 void
67 MathDotsInset::Write(ostream & os)
68 {
69    string output;
70    MathDotsInset::Write(output);
71    os << output;
72 }
73
74
75 void
76 MathDotsInset::Write(string & outf)
77 {
78    outf += '\\';
79    outf += name;
80    outf += ' ';
81 }   
82
83
84 void MathSqrtInset::Write(ostream & os)
85
86    string output;
87    MathSqrtInset::Write(output);
88    os << output;
89 }
90
91
92 void MathSqrtInset::Write(string & outf)
93
94    outf += '\\';
95    outf += name;
96    outf += '{';
97    MathParInset::Write(outf);  
98    outf += '}';
99 }
100
101
102 void MathDelimInset::Write(ostream & os)
103
104     string output;
105     MathDelimInset::Write(output);
106     os << output;
107 }
108
109
110 void MathDelimInset::Write(string & outf)
111
112     latexkeys * l = (left != '|') ? lm_get_key_by_id(left, LM_TK_SYM): 0;
113     latexkeys * r = (right != '|') ? lm_get_key_by_id(right, LM_TK_SYM): 0;
114     outf += "\\left";
115     if (l) {
116         outf += '\\';
117         outf += l->name;
118         outf += ' ';
119     } else {
120         if (left == '{' || left == '}') {
121             outf += '\\';
122             outf += char(left);
123             outf += ' ';
124         } else {
125             outf += char(left);
126             outf += ' ';
127         }
128     }
129    MathParInset::Write(outf);  
130    outf += "\\right";
131    if (r) {
132        outf += '\\';
133        outf += r->name;
134        outf += ' ';
135    } else {
136        if (right == '{' || right == '}') {
137            outf += '\\';
138            outf += char(right);
139            outf += ' ';
140       } else {
141            outf += char(right);
142            outf += ' ';
143       }
144    }        
145 }
146
147
148 void MathDecorationInset::Write(ostream & os)
149 {
150    string output;
151    MathDecorationInset::Write(output);
152    os << output;
153 }
154
155
156 void MathDecorationInset::Write(string & outf)
157
158    latexkeys * l = lm_get_key_by_id(deco, LM_TK_WIDE);
159    outf += '\\';
160    outf += l->name;
161    outf += '{';
162    MathParInset::Write(outf);  
163    outf += '}';
164 }
165
166
167 void MathAccentInset::Write(ostream & os)
168
169     string output;
170     MathAccentInset::Write(output);
171     os << output;
172 }
173
174
175 void MathAccentInset::Write(string & outf)
176
177     latexkeys * l = lm_get_key_by_id(code, LM_TK_ACCENT);
178     outf += '\\';
179     outf += l->name;
180     if (code!= LM_not)
181       outf += '{';
182     else
183       outf += ' ';
184
185     if (inset) {
186       inset->Write(outf);
187     } else {
188       if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM) {
189         outf += '\\';
190         outf += math_font_name[fn-LM_TC_RM];
191         outf += '{';
192       }
193       if (MathIsSymbol(fn)) {
194           latexkeys *l = lm_get_key_by_id(c, LM_TK_SYM);
195           if (l) {
196             outf += '\\';
197             outf += l->name;
198             outf += ' ';
199           }
200       } else
201         outf += char(c);
202
203       if (fn>= LM_TC_RM && fn<= LM_TC_TEXTRM)
204         outf += '}';
205     }
206
207     if (code!= LM_not)
208       outf += '}';
209 }
210
211
212 void MathBigopInset::Write(ostream & os)
213
214    string output;
215    MathBigopInset::Write(output);
216    os << output;
217 }
218
219
220 void MathBigopInset::Write(string & outf)
221
222     bool limp = GetLimits();
223     
224     outf += '\\';
225     outf += name;
226     
227     if (limp && !(sym!= LM_int && sym!= LM_oint && (GetStyle() == LM_ST_DISPLAY)))
228       outf += "\\limits ";
229     else 
230     if (!limp && (sym!= LM_int && sym!= LM_oint && (GetStyle() == LM_ST_DISPLAY)))
231         outf += "\\nolimits ";
232     else 
233       outf += ' ';
234 }
235
236
237 void MathFracInset::Write(ostream & os)
238
239    string output;
240    MathFracInset::Write(output);
241    os << output;
242 }
243
244
245 void MathFracInset::Write(string & outf)
246
247    outf += '\\';
248    outf += name;
249    outf += '{';
250    MathParInset::Write(outf);  
251    outf += "}{";
252    den->Write(outf);  
253    outf += '}';
254 }
255
256
257 void MathParInset::Write(ostream & os)
258 {
259    if (!array) return;
260    string output;
261    MathParInset::Write(output);
262    os << output;
263 }
264
265
266 void MathParInset::Write(string & outf)
267 {
268    if (!array) return;
269    int brace = 0;
270    latexkeys * l;
271    MathedIter data(array);
272    // hack
273    MathedRowSt const * crow = getRowSt();   
274    data.Reset();
275     
276    if (!Permit(LMPF_FIXED_SIZE)) { 
277        l = lm_get_key_by_id(size, LM_TK_STY);
278        if (l) {
279            outf += '\\';
280            outf += l->name;
281            outf += ' ';
282        }
283    }
284    while (data.OK()) {
285       byte cx = data.GetChar();
286       if (cx>= ' ') {
287          int ls;
288          byte * s = data.GetString(ls);
289        
290          if (data.FCode()>= LM_TC_RM && data.FCode()<= LM_TC_TEXTRM) {
291              outf += '\\';
292              outf += math_font_name[data.FCode()-LM_TC_RM];
293              outf += '{';
294          }
295          while (ls>0) {
296             if (MathIsSymbol(data.FCode())) {
297                 l = lm_get_key_by_id(*s,(data.FCode() == LM_TC_BSYM)?LM_TK_BIGSYM:LM_TK_SYM);
298                if (l) {
299                  outf += '\\';
300                  outf += l->name;
301                  outf += ' ';
302                } else { 
303                        lyxerr << "Illegal symbol code[" << *s
304                               << " " << ls << " " << data.FCode() << "]";
305                }
306             } else {
307                // Is there a standard logical XOR?
308                if ((data.FCode() == LM_TC_TEX && *s!= '{' && *s!= '}') ||
309                    (data.FCode() == LM_TC_SPECIAL))
310                  outf += '\\';
311                else {
312                   if (*s == '{') brace++;
313                   if (*s == '}') brace--;
314                }
315                if (*s == '}' && data.FCode() == LM_TC_TEX && brace<0) 
316                        lyxerr <<"Math warning: Unexpected closing brace."
317                               << endl;
318                else            
319                  outf += char(*s);
320             }
321             s++; ls--;
322          }
323          if (data.FCode()>= LM_TC_RM && data.FCode()<= LM_TC_TEXTRM)
324            outf += '}';
325       } else     
326       if (MathIsInset(cx)) {
327          MathedInset *p = data.GetInset();
328          if (cx == LM_TC_UP)
329            outf += "^{";
330          if (cx == LM_TC_DOWN)
331            outf += "_{";
332          p->Write(outf);
333          if (cx == LM_TC_UP || cx == LM_TC_DOWN)
334            outf += '}';
335          data.Next();
336       } else
337         switch(cx) {
338          case LM_TC_TAB:
339             {
340                outf += " & ";
341                data.Next();
342                break;
343             }
344          case LM_TC_CR:
345             {
346                 if (crow) {
347                     if (!crow->isNumbered()) {  
348                         outf += "\\nonumber ";
349                     }
350                     if (crow->getLabel()) {
351                         outf += "\\label{";
352                         outf += crow->getLabel();
353                         outf += "} ";
354                     }
355                     crow = crow->getNext();
356                 }
357                outf += "\\\\\n";
358                number_of_newlines++;
359                data.Next();
360                break;
361             }
362          default:
363                  lyxerr << "WMath Error: unrecognized code[" << cx << "]";
364            return;
365         }     
366    }
367     
368     if (crow) {
369         if (!crow->isNumbered()) {
370             outf += "\\nonumber ";
371         }
372         if (crow->getLabel()) {
373             outf += "\\label{";
374             outf += crow->getLabel();
375             outf += "} ";
376         }
377     }
378    while (brace>0) {
379       outf += '}';
380       brace--;
381    }
382 }
383
384
385 void MathMatrixInset::Write(ostream & os)
386 {
387     string output;
388     MathMatrixInset::Write(output);
389     os << output;
390 }
391
392
393 void MathMatrixInset::Write(string & outf)
394 {
395     if (GetType() == LM_OT_MATRIX){
396         outf += "\\begin{";
397         outf += name;
398         outf += '}';
399         if (v_align == 't' || v_align == 'b') {
400             outf += '[';
401             outf += char(v_align);
402             outf += ']';
403         }
404         outf += '{';
405         outf += h_align;
406         outf += "}\n";
407         number_of_newlines++;
408     }
409     MathParInset::Write(outf);
410     if (GetType() == LM_OT_MATRIX){
411         outf += "\n\\end{";
412         outf += name;
413         outf += '}';
414         number_of_newlines++;
415     }
416 }
417
418
419 void mathed_write(MathParInset * p, ostream & os, int * newlines,
420                   char fragile, char const * label)
421 {
422    string output;
423    mathed_write(p, output, newlines, fragile, label);
424    os << output;
425 }
426
427
428 extern int tex_code_break_column;
429
430 void mathed_write(MathParInset * p, string & outf, int * newlines,
431                   char fragile, char const * label)
432 {  
433    number_of_newlines = 0;
434    short mathed_env = p->GetType();
435
436    if (mathed_env == LM_EN_INTEXT) {
437      if (fragile) outf += "\\protect";
438      outf += "\\( "; // changed from " \\( " (Albrecht Dress)
439    } 
440    else {
441      if (!suffixIs(outf, '\n')) {
442        // in batchmode we need to make sure
443        // a space before an equation doesn't
444        // make the LaTeX output different 
445        // compared to "Exported LaTeX"  ARRae
446        // Modified to work in a cleaner and hopefully more general way
447        // (JMarc)
448        outf += "\n";
449        number_of_newlines++;
450      }
451      if (mathed_env == LM_EN_DISPLAY){
452        outf += "\\[\n";
453      }
454      else {
455        outf += "\\begin{";
456        outf += latex_mathenv[mathed_env];
457        outf += "}\n";
458      }
459      number_of_newlines++;
460    }
461    
462    if (label && label[0]>' ' && mathed_env == LM_EN_EQUATION){
463      outf += "\\label{";
464      outf += label;
465      outf += "}\n";
466      number_of_newlines++;
467    }
468
469    p->Write(outf);
470    
471    if (mathed_env == LM_EN_INTEXT){
472      if (fragile) outf += "\\protect";
473      outf += " \\)";
474    }
475    else if (mathed_env == LM_EN_DISPLAY){
476      outf += "\\]\n";
477      number_of_newlines++;
478    }
479    else {
480      outf += "\n\\end{";
481      outf += latex_mathenv[mathed_env];
482      outf += "}\n";
483      number_of_newlines+= 2;
484    }
485    *newlines = number_of_newlines;
486 }