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