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