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