]> git.lyx.org Git - lyx.git/blob - src/paragraph.C
changes from sprintf to string stream. see comments at top of text.C. read the ChangeLog
[lyx.git] / src / paragraph.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2000 The LyX Team. 
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation "lyxparagraph.h"
15 #endif
16
17 #include <fstream>
18 using std::fstream;
19 using std::ios;
20
21 #include "lyxparagraph.h"
22 #include "support/textutils.h"
23 #include "lyxrc.h"
24 #include "layout.h"
25 #include "tex-strings.h"
26 #include "bufferparams.h"
27 #include "support/FileInfo.h"
28 #include "support/LAssert.h"
29 #include "debug.h"
30 #include "LaTeXFeatures.h"
31 #include "insets/insetinclude.h"
32 #include "insets/insetbib.h"
33 #include "support/filetools.h"
34 #include "lyx_gui_misc.h"
35 #include "texrow.h"
36
37
38 #ifdef USE_OSTREAM_ONLY
39 #include "support/lyxmanip.h"
40 #else
41 extern void addNewlineAndDepth(string & file, int depth); // Jug 990923
42 #endif
43 int tex_code_break_column = 72;  // needs non-zero initialization. set later.
44 // this is a bad idea, but how can LyXParagraph find its buffer to get
45 // parameters? (JMarc)
46 extern BufferView * current_view;
47 extern LyXRC * lyxrc;
48
49
50 // ale970405
51 extern string bibitemWidthest(Painter &);
52
53 // this is a minibuffer
54 static char minibuffer_char;
55 static LyXFont minibuffer_font;
56 static Inset * minibuffer_inset;
57
58
59 // Initialization of the counter for the paragraph id's,
60 // declared in lyxparagraph.h
61 unsigned int LyXParagraph::paragraph_id = 0;
62
63
64 LyXParagraph::LyXParagraph()
65 {
66         text.reserve(500); // is this number too big?
67
68         for (int i = 0; i < 10; ++i) setCounter(i , 0);
69         appendix = false;
70         enumdepth = 0;
71         itemdepth = 0;
72         next = 0;
73         previous = 0;
74         footnoteflag = LyXParagraph::NO_FOOTNOTE;
75         footnotekind = LyXParagraph::FOOTNOTE; // should not be needed
76         
77         align = LYX_ALIGN_BLOCK;
78
79         /* table stuff -- begin*/ 
80         table = 0;
81         /* table stuff -- end*/ 
82         id_ = paragraph_id++;
83         bibkey = 0; // ale970302
84         Clear();
85 }
86
87
88 // This konstruktor inserts the new paragraph in a list.
89 LyXParagraph::LyXParagraph(LyXParagraph * par)
90 {
91         text.reserve(500);
92         par->text.resize(par->text.size());
93
94         for (int i = 0; i < 10; ++i) setCounter(i, 0);
95         appendix = false;
96         enumdepth = 0;
97         itemdepth = 0;
98         // double linked list begin
99         next = par->next;
100         if (next)
101                 next->previous = this;
102         previous = par;
103         previous->next = this;
104         // end
105         footnoteflag = LyXParagraph::NO_FOOTNOTE;
106         footnotekind = LyXParagraph::FOOTNOTE;
107         
108         /* table stuff -- begin*/ 
109         table = 0;
110         /* table stuff -- end*/ 
111         id_ = paragraph_id++;
112
113         bibkey = 0; // ale970302        
114     
115         Clear();
116 }
117
118
119 void LyXParagraph::writeFile(ostream & os, BufferParams const & params,
120                              char footflag, char dth) const
121 {
122         LyXFont font1, font2;
123         int column = 0;
124         int h = 0;
125         char c = 0;
126
127         if (footnoteflag != LyXParagraph::NO_FOOTNOTE
128             || !previous
129             || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
130                 
131                 // The beginning or the end of a footnote environment?
132                 if (footflag != footnoteflag) {
133                         footflag = footnoteflag;
134                         if (footflag) {
135                                 os << "\n\\begin_float "
136                                    << string_footnotekinds[footnotekind]
137                                    << " ";
138                         } else {
139                                 os << "\n\\end_float ";
140                         }
141                 }
142
143                 // The beginning or end of a deeper (i.e. nested) area?
144                 if (dth != depth) {
145                         if (depth > dth) {
146                                 while (depth > dth) {
147                                         os << "\n\\begin_deeper ";
148                                         ++dth;
149                                 }
150                         } else {
151                                 while (depth < dth) {
152                                         os << "\n\\end_deeper ";
153                                         --dth;
154                                 }
155                         }
156                 }
157
158                 // First write the layout
159                 os << "\n\\layout "
160                    << textclasslist.NameOfLayout(params.textclass, layout)
161                    << "\n";
162
163                 // Maybe some vertical spaces.
164                 if (added_space_top.kind() != VSpace::NONE)
165                         os << "\\added_space_top "
166                            << added_space_top.asLyXCommand() << " ";
167                 if (added_space_bottom.kind() != VSpace::NONE)
168                         os << "\\added_space_bottom "
169                            << added_space_bottom.asLyXCommand() << " ";
170                         
171                 // The labelwidth string used in lists.
172                 if (!labelwidthstring.empty())
173                         os << "\\labelwidthstring "
174                            << labelwidthstring << '\n';
175
176                 // Lines above or below?
177                 if (line_top)
178                         os << "\\line_top ";
179                 if (line_bottom)
180                         os << "\\line_bottom ";
181
182                 // Pagebreaks above or below?
183                 if (pagebreak_top)
184                         os << "\\pagebreak_top ";
185                 if (pagebreak_bottom)
186                         os << "\\pagebreak_bottom ";
187                         
188                 // Start of appendix?
189                 if (start_of_appendix)
190                         os << "\\start_of_appendix ";
191
192                 // Noindent?
193                 if (noindent)
194                         os << "\\noindent ";
195                         
196                 // Alignment?
197                 if (align != LYX_ALIGN_LAYOUT) {
198                         switch (align) {
199                         case LYX_ALIGN_LEFT: h = 1; break;
200                         case LYX_ALIGN_RIGHT: h = 2; break;
201                         case LYX_ALIGN_CENTER: h = 3; break;
202                         default: h = 0; break;
203                         }
204                         os << "\\align " << string_align[h] << " ";
205                 }
206                 if (pextra_type != PEXTRA_NONE) {
207                         os << "\\pextra_type " << pextra_type;
208                         if (pextra_type == PEXTRA_MINIPAGE) {
209                                 os << " \\pextra_alignment "
210                                    << pextra_alignment;
211                                 if (pextra_hfill)
212                                         os << " \\pextra_hfill "
213                                            << pextra_hfill;
214                                 if (pextra_start_minipage)
215                                         os << " \\pextra_start_minipage "
216                                            << pextra_start_minipage;
217                         }
218                         if (!pextra_width.empty()) {
219                                 os << " \\pextra_width "
220                                    << VSpace(pextra_width).asLyXCommand();
221                         } else if (!pextra_widthp.empty()) {
222                                 os << " \\pextra_widthp "
223                                    << pextra_widthp;
224                         }
225                         os << '\n';
226                 }
227         } else {
228                 // Dummy layout. This means that a footnote ended.
229                 os << "\n\\end_float ";
230                 footflag = LyXParagraph::NO_FOOTNOTE;
231         }
232                 
233         // It might be a table.
234         if (table){
235                 os << "\\LyXTable\n";
236                 table->Write(os);
237         }
238
239         // bibitem  ale970302
240         if (bibkey)
241                 bibkey->Write(os);
242
243         font1 = LyXFont(LyXFont::ALL_INHERIT);
244
245         column = 0;
246         for (size_type i = 0; i < size(); ++i) {
247                 if (!i) {
248                         os << "\n";
249                         column = 0;
250                 }
251                 
252                 // Write font changes
253                 font2 = GetFontSettings(i);
254                 if (font2 != font1) {
255                         font2.lyxWriteChanges(font1, os);
256                         column = 0;
257                         font1 = font2;
258                 }
259
260                 c = GetChar(i);
261                 switch (c) {
262                 case META_INSET:
263                 {
264                         Inset const * inset = GetInset(i);
265                         if (inset)
266                                 if (inset->DirectWrite()) {
267                                         // international char, let it write
268                                         // code directly so it's shorter in
269                                         // the file
270                                         inset->Write(os);
271                                 } else {
272                                         os << "\n\\begin_inset ";
273                                         inset->Write(os);
274                                         os << "\n\\end_inset \n\n";
275                                         column = 0;
276                                 }
277                 }
278                 break;
279                 case META_NEWLINE: 
280                         os << "\n\\newline \n";
281                         column = 0;
282                         break;
283                 case META_HFILL: 
284                         os << "\n\\hfill \n";
285                         column = 0;
286                         break;
287 #if 0
288                 case META_PROTECTED_SEPARATOR: 
289                         os << "\n\\protected_separator \n";
290                         column = 0;
291                         break;
292 #endif
293                 case '\\':
294                         os << "\n\\backslash \n";
295                         column = 0;
296                         break;
297                 case '.':
298                         if (i + 1 < size() && GetChar(i + 1) == ' ') {
299                                 os << ".\n";
300                                 column = 0;
301                         } else
302                                 os << ".";
303                         break;
304                 default:
305                         if ((column > 70 && c == ' ')
306                             || column > 79) {
307                                 os << "\n";
308                                 column = 0;
309                         }
310                         // this check is to amend a bug. LyX sometimes
311                         // inserts '\0' this could cause problems.
312                         if (c != '\0')
313                                 os << c;
314                         else
315                                 lyxerr << "ERROR (LyXParagraph::writeFile):"
316                                         " NULL char in structure." << endl;
317                         ++column;
318                         break;
319                 }
320         }
321
322         // now write the next paragraph
323         if (next)
324                 next->writeFile(os, params, footflag, dth);
325 }
326
327
328 void LyXParagraph::validate(LaTeXFeatures & features) const
329 {
330         // this will be useful later
331         LyXLayout const & layout =
332                 textclasslist.Style(current_view->buffer()->params.textclass, 
333                                     GetLayout());
334         
335         // check the params.
336         if (line_top || line_bottom)
337                 features.lyxline = true;
338         
339         // then the layouts
340         features.layout[GetLayout()] = true;
341
342         // then the fonts
343         for (FontList::const_iterator cit = fontlist.begin();
344              cit != fontlist.end(); ++cit) {
345                 if ((*cit).font.noun() == LyXFont::ON) {
346                         lyxerr[Debug::LATEX] << "font.noun: "
347                                              << (*cit).font.noun()
348                                              << endl;
349                         features.noun = true;
350                         lyxerr[Debug::LATEX] << "Noun enabled. Font: "
351                                              << (*cit).font.stateText()
352                                              << endl;
353                 }
354                 switch ((*cit).font.color()) {
355                 case LColor::none:
356                 case LColor::inherit:
357                 case LColor::ignore:
358                         break;
359                 default:
360                         features.color = true;
361                         lyxerr[Debug::LATEX] << "Color enabled. Font: "
362                                              << (*cit).font.stateText()
363                                              << endl;
364                 }
365         }
366
367         // then the insets
368         for (InsetList::const_iterator cit = insetlist.begin();
369              cit != insetlist.end(); ++cit) {
370                 if ((*cit).inset)
371                         (*cit).inset->Validate(features);
372         }
373
374         if (table && table->IsLongTable())
375                 features.longtable = true;
376         if (pextra_type == PEXTRA_INDENT)
377                 features.LyXParagraphIndent = true;
378         if (pextra_type == PEXTRA_FLOATFLT)
379                 features.floatflt = true;
380         if (layout.needprotect 
381             && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
382                 features.NeedLyXFootnoteCode = true;
383         if ((current_view->buffer()->params.paragraph_separation == BufferParams::PARSEP_INDENT) &&
384             (pextra_type == LyXParagraph::PEXTRA_MINIPAGE))
385                 features.NeedLyXMinipageIndent = true;
386         if (table && table->NeedRotating())
387                 features.rotating = true;
388         if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
389                 features.algorithm = true;
390 }
391
392
393 // First few functions needed for cut and paste and paragraph breaking.
394 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos) const
395 {
396         minibuffer_char = GetChar(pos);
397         minibuffer_font = GetFontSettings(pos);
398         minibuffer_inset = 0;
399         if (minibuffer_char == LyXParagraph::META_INSET) {
400                 if (GetInset(pos)) {
401                         minibuffer_inset = GetInset(pos)->Clone();
402                 } else {
403                         minibuffer_inset = 0;
404                         minibuffer_char = ' ';
405                         // This reflects what GetInset() does (ARRae)
406                 }
407         }
408 }
409
410
411 void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos)
412 {
413         minibuffer_char = GetChar(pos);
414         minibuffer_font = GetFontSettings(pos);
415         minibuffer_inset = 0;
416         if (minibuffer_char == LyXParagraph::META_INSET) {
417                 if (GetInset(pos)) {
418                         minibuffer_inset = GetInset(pos);
419                         // This is a little hack since I want exactly
420                         // the inset, not just a clone. Otherwise
421                         // the inset would be deleted when calling Erase(pos)
422                         // find the entry
423                         for (InsetList::iterator it = insetlist.begin();
424                              it != insetlist.end(); ++it) {
425                                 if ((*it).pos == pos) {
426                                         (*it).inset = 0;
427                                         break;
428                                 }
429                                         
430                         }
431                 } else {
432                         minibuffer_inset = 0;
433                         minibuffer_char = ' ';
434                         // This reflects what GetInset() does (ARRae)
435                 }
436
437         }
438
439         // Erase(pos); now the caller is responsible for that.
440 }
441
442
443 void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
444 {
445         InsertChar(pos, minibuffer_char);
446         SetFont(pos, minibuffer_font);
447         if (minibuffer_char == LyXParagraph::META_INSET)
448                 InsertInset(pos, minibuffer_inset);
449 }
450
451 // end of minibuffer
452
453
454
455 void LyXParagraph::Clear()
456 {
457         line_top = false;
458         line_bottom = false;
459    
460         pagebreak_top = false;
461         pagebreak_bottom = false;
462
463         added_space_top = VSpace(VSpace::NONE);
464         added_space_bottom = VSpace(VSpace::NONE);
465
466         align = LYX_ALIGN_LAYOUT;
467         depth = 0;
468         noindent = false;
469
470         pextra_type = PEXTRA_NONE;
471         pextra_width.clear();
472         pextra_widthp.clear();
473         pextra_alignment = MINIPAGE_ALIGN_TOP;
474         pextra_hfill = false;
475         pextra_start_minipage = false;
476
477         labelstring.clear();
478         labelwidthstring.clear();
479         layout = 0;
480         bibkey = 0;
481         
482         start_of_appendix = false;
483 }
484
485
486 // the destructor removes the new paragraph from the list
487 LyXParagraph::~LyXParagraph()
488 {
489         if (previous)
490                 previous->next = next;
491         if (next)
492                 next->previous = previous;
493
494         for (InsetList::iterator it = insetlist.begin();
495              it != insetlist.end(); ++it) {
496                 delete (*it).inset;
497         }
498
499         /* table stuff -- begin*/ 
500         delete table;
501         /* table stuff -- end*/ 
502
503         // ale970302
504         delete bibkey;
505 }
506
507
508 void LyXParagraph::Erase(LyXParagraph::size_type pos)
509 {
510         // > because last is the next unused position, and you can 
511         // use it if you want
512         if (pos > size()) {
513                 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
514                         NextAfterFootnote()->Erase(pos - text.size() - 1);
515                 else 
516                         lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
517                                 "position does not exist." << endl;
518                 return;
519         }
520         if (pos < size()) { // last is free for insertation, but should be empty
521                 // if it is an inset, delete the inset entry 
522                 if (text[pos] == LyXParagraph::META_INSET) {
523                         // find the entry
524                         for (InsetList::iterator it = insetlist.begin();
525                              it != insetlist.end(); ++it) {
526                                 if ((*it).pos == pos) {
527                                         delete (*it).inset;
528                                         insetlist.erase(it);
529                                         break;
530                                 }
531                         }
532                 }
533                 text.erase(text.begin() + pos);
534                 // Erase entries in the tables.
535                 for (FontList::iterator it = fontlist.begin();
536                      it != fontlist.end(); ++it) {
537                         if (pos >= (*it).pos && pos <= (*it).pos_end) {
538                                 if ((*it).pos == (*it).pos_end) {
539                                         // If it is a multi-character font
540                                         // entry, we just make it smaller
541                                         // (see update below), otherwise we
542                                         // should delete it.
543                                         fontlist.erase(it);
544                                         break;
545                                 }
546                         }
547                 }
548                 // Update all other entries.
549                 for (FontList::iterator it = fontlist.begin();
550                      it != fontlist.end(); ++it) {
551                         if ((*it).pos > pos)
552                                 (*it).pos--;
553                         if ((*it).pos_end >= pos)
554                                 (*it).pos_end--;
555                 }
556
557                 // Update the inset table.
558                 for (InsetList::iterator it = insetlist.begin();
559                      it != insetlist.end(); ++it) {
560                         if ((*it).pos > pos)
561                                 (*it).pos--;
562                 }
563         } else {
564                 lyxerr << "ERROR (LyXParagraph::Erase): "
565                         "can't erase non-existant char." << endl;
566         }
567 }
568
569
570 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
571 {
572         // > because last is the next unused position, and you can 
573         // use it if you want
574         if (pos > size()) {
575                 if (next
576                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
577                         NextAfterFootnote()->InsertChar(pos - text.size() - 1,
578                                                         c);
579                 else 
580                         lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
581                                 "position does not exist." << endl;
582                 return;
583         }
584         text.insert(text.begin() + pos, c);
585         // Update the font table.
586         for (FontList::iterator it = fontlist.begin();
587              it != fontlist.end(); ++it) {
588                 if ((*it).pos >= pos)
589                         (*it).pos++;
590                 if ((*it).pos_end >= pos)
591                         (*it).pos_end++;
592         }
593    
594         // Update the inset table.
595         for (InsetList::iterator it = insetlist.begin();
596              it != insetlist.end(); ++it) {
597                 if ((*it).pos >= pos)
598                         (*it).pos++;
599         }
600 }
601
602
603 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
604                                Inset * inset)
605 {
606         // > because last is the next unused position, and you can 
607         // use it if you want
608         if (pos > size()) {
609                 if (next
610                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
611                         NextAfterFootnote()
612                                 ->InsertInset(pos - text.size() - 1, inset);
613                 else 
614                         lyxerr << "ERROR (LyXParagraph::InsertInset): " 
615                                 "position does not exist: " << pos << endl;
616                 return;
617         }
618         if (text[pos] != LyXParagraph::META_INSET) {
619                 lyxerr << "ERROR (LyXParagraph::InsertInset): "
620                         "there is no LyXParagraph::META_INSET" << endl;
621                 return;
622         }
623
624         if (inset) {
625                 // Add a new entry in the inset table.
626                 InsetList::iterator it =
627                         insetlist.insert(insetlist.begin(), InsetTable());
628                 (*it).inset = inset;
629                 (*it).pos = pos;
630         }
631 }
632
633
634 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
635 {
636         if (pos >= size()) {
637                 if (next
638                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
639                         return NextAfterFootnote()
640                                 ->GetInset(pos - text.size() - 1);
641                 else { 
642                         lyxerr << "ERROR (LyXParagraph::GetInset): "
643                                 "position does not exist: "
644                                << pos << endl;
645                 }
646                 return 0;
647         }
648         // Find the inset.
649         for (InsetList::iterator it = insetlist.begin();
650              it != insetlist.end(); ++it) {
651                 if ((*it).pos == pos) {
652                         return (*it).inset;
653                 }
654         }
655         lyxerr << "ERROR (LyXParagraph::GetInset): "
656                 "Inset does not exist: " << pos << endl;
657         text[pos] = ' '; // WHY!!! does this set the pos to ' '????
658         // Did this commenting out introduce a bug? So far I have not
659         // see any, please enlighten me. (Lgb)
660         // My guess is that since the inset does not exist, we might
661         // as well replace it with a space to prevent craches. (Asger)
662         return 0;
663 }
664
665
666 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
667 {
668         if (pos >= size()) {
669                 if (next
670                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
671                         return NextAfterFootnote()
672                                 ->GetInset(pos - text.size() - 1);
673                 else { 
674                         lyxerr << "ERROR (LyXParagraph::GetInset): "
675                                 "position does not exist: "
676                                << pos << endl;
677                 }
678                 return 0;
679         }
680         // Find the inset.
681         for (InsetList::const_iterator cit = insetlist.begin();
682              cit != insetlist.end(); ++cit) {
683                 if ((*cit).pos == pos) {
684                         return (*cit).inset;
685                 }
686         }
687         lyxerr << "ERROR (LyXParagraph::GetInset): "
688                 "Inset does not exist: " << pos << endl;
689         //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
690         // Did this commenting out introduce a bug? So far I have not
691         // see any, please enlighten me. (Lgb)
692         // My guess is that since the inset does not exist, we might
693         // as well replace it with a space to prevent craches. (Asger)
694         return 0;
695 }
696
697
698 // Gets uninstantiated font setting at position.
699 // Optimized after profiling. (Asger)
700 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos) const
701 {
702         if (pos < size()) {
703                 for (FontList::const_iterator cit = fontlist.begin();
704                      cit != fontlist.end(); ++cit) {
705                         if (pos >= (*cit).pos && pos <= (*cit).pos_end)
706                                 return (*cit).font;
707                 }
708         }
709         // > because last is the next unused position, and you can 
710         // use it if you want
711         else if (pos > size()) {
712                 if (next
713                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
714                         return NextAfterFootnote()
715                                 ->GetFontSettings(pos - text.size() - 1);
716                 else {
717                         // Why is it an error to ask for the font of a
718                         // position that does not exist? Would it be
719                         // enough for this to be enabled on debug?
720                         // We want strict error checking, but it's ok to only
721                         // have it when debugging. (Asger)
722                         lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
723                                 "position does not exist. "
724                                << pos << " (" << static_cast<int>(pos)
725                                << ")" << endl;
726                 }
727         } else if (pos) {
728                 return GetFontSettings(pos - 1);
729         }
730         return LyXFont(LyXFont::ALL_INHERIT);
731 }
732
733
734 // Gets the fully instantiated font at a given position in a paragraph
735 // This is basically the same function as LyXText::GetFont() in text2.C.
736 // The difference is that this one is used for generating the LaTeX file,
737 // and thus cosmetic "improvements" are disallowed: This has to deliver
738 // the true picture of the buffer. (Asger)
739 // If position is -1, we get the layout font of the paragraph.
740 // If position is -2, we get the font of the manual label of the paragraph.
741 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos) const
742 {
743         LyXFont tmpfont;
744         LyXLayout const & layout =
745                 textclasslist.Style(current_view->buffer()->params.textclass, 
746                                     GetLayout());
747         LyXParagraph::size_type main_body = 0;
748         if (layout.labeltype == LABEL_MANUAL)
749                 main_body = BeginningOfMainBody();
750
751         if (pos >= 0){
752                 LyXFont layoutfont;
753                 if (pos < main_body)
754                         layoutfont = layout.labelfont;
755                 else
756                         layoutfont = layout.font;
757                 tmpfont = GetFontSettings(pos);
758                 tmpfont.realize(layoutfont);
759         } else {
760                 // process layoutfont for pos == -1 and labelfont for pos < -1
761                 if (pos == -1)
762                         tmpfont = layout.font;
763                 else
764                         tmpfont = layout.labelfont;
765                 if (getParDirection() == LYX_DIR_RIGHT_TO_LEFT)
766                         tmpfont.setDirection(LyXFont::RTL_DIR);
767         }
768
769         // check for environment font information
770         char par_depth = GetDepth();
771         LyXParagraph const * par = this;
772         while (par && par_depth && !tmpfont.resolved()) {
773                 par = par->DepthHook(par_depth - 1);
774                 if (par) {
775                         tmpfont.realize(textclasslist.
776                                         Style(current_view->buffer()->params.textclass,
777                                               par->GetLayout()).font);
778                         par_depth = par->GetDepth();
779                 }
780         }
781
782         tmpfont.realize(textclasslist
783                         .TextClass(current_view->buffer()->params.textclass)
784                         .defaultfont());
785         return tmpfont;
786 }
787
788
789 /// Returns the height of the highest font in range
790 LyXFont::FONT_SIZE
791 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
792                                  LyXParagraph::size_type endpos) const
793 {
794         LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
795         for (FontList::const_iterator cit = fontlist.begin();
796              cit != fontlist.end(); ++cit) {
797                 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
798                         LyXFont::FONT_SIZE size = (*cit).font.size();
799                         if (size > maxsize && size <= LyXFont::SIZE_HUGER)
800                                 maxsize = size;
801                 }
802         }
803         return maxsize;
804 }
805
806
807 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
808 {
809         Assert(pos >= 0);
810
811         if (pos < size()) {
812                 return text[pos];
813         }
814         // > because last is the next unused position, and you can 
815         // use it if you want
816         else if (pos > size()) {
817                 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) 
818                         return NextAfterFootnote()
819                                 ->GetChar(pos - text.size() - 1);
820                 else {
821                         lyxerr << "ERROR (LyXParagraph::GetChar): "
822                                 "position does not exist."
823                                << pos << " (" << static_cast<int>(pos)
824                                << ")\n";
825                         // Assert(false); // This triggers sometimes...
826                         // Why?
827                 }
828                 return '\0';
829         } else {
830                 // We should have a footnote environment.
831                 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
832                         // Notice that LyX does request the
833                         // last char from time to time. (Asger)
834                         //lyxerr << "ERROR (LyXParagraph::GetChar): "
835                         //      "expected footnote." << endl;
836                         return '\0';
837                 }
838                 switch (next->footnotekind) {
839                 case LyXParagraph::FOOTNOTE:
840                         return LyXParagraph::META_FOOTNOTE;
841                 case LyXParagraph::MARGIN:
842                         return LyXParagraph::META_MARGIN;
843                 case LyXParagraph::FIG:
844                 case LyXParagraph::WIDE_FIG:
845                         return LyXParagraph::META_FIG;
846                 case LyXParagraph::TAB:
847                 case LyXParagraph::WIDE_TAB:
848                         return LyXParagraph::META_TAB;
849                 case LyXParagraph::ALGORITHM:
850                         return LyXParagraph::META_ALGORITHM;
851                 }
852                 return '\0'; // to shut up gcc
853         }
854 }
855
856
857 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
858 {
859         Assert(pos >= 0);
860
861         if (pos < size()) {
862                 return text[pos];
863         }
864         // > because last is the next unused position, and you can 
865         // use it if you want
866         else if (pos > size()) {
867                 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) 
868                         return NextAfterFootnote()
869                                 ->GetChar(pos - text.size() - 1);
870                 else {
871                         lyxerr << "ERROR (LyXParagraph::GetChar const): "
872                                 "position does not exist."
873                                << pos << " (" << static_cast<int>(pos)
874                                << ")\n";
875                         Assert(false);
876                 }
877                 return '\0';
878         } else {
879                 // We should have a footnote environment.
880                 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
881                         // Notice that LyX does request the
882                         // last char from time to time. (Asger)
883                         //lyxerr << "ERROR (LyXParagraph::GetChar): "
884                         //      "expected footnote." << endl;
885                         return '\0';
886                 }
887                 switch (next->footnotekind) {
888                 case LyXParagraph::FOOTNOTE:
889                         return LyXParagraph::META_FOOTNOTE;
890                 case LyXParagraph::MARGIN:
891                         return LyXParagraph::META_MARGIN;
892                 case LyXParagraph::FIG:
893                 case LyXParagraph::WIDE_FIG:
894                         return LyXParagraph::META_FIG;
895                 case LyXParagraph::TAB:
896                 case LyXParagraph::WIDE_TAB:
897                         return LyXParagraph::META_TAB;
898                 case LyXParagraph::ALGORITHM:
899                         return LyXParagraph::META_ALGORITHM;
900                 }
901                 return '\0'; // to shut up gcc
902         }
903 }
904
905
906 // return an string of the current word, and the end of the word in lastpos.
907 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
908 {
909         Assert(lastpos>=0);
910
911         // the current word is defined as starting at the first character
912         // from the immediate left of lastpospos which meets the definition
913         // of IsLetter(), continuing to the last character to the right
914         // of this meeting IsLetter.
915
916         string theword;
917
918         // grab a word
919                 
920         // move back until we have a letter
921
922         //there's no real reason to have firstpos & lastpos as
923         //separate variables as this is written, but maybe someon
924         // will want to return firstpos in the future.
925
926         //since someone might have typed a punctuation first
927         int firstpos = lastpos;
928         
929         while ((firstpos >= 0) && !IsLetter(firstpos))
930                 --firstpos;
931
932         // now find the beginning by looking for a nonletter
933         
934         while ((firstpos>= 0) && IsLetter(firstpos))
935                 --firstpos;
936
937         // the above is now pointing to the preceeding non-letter
938         ++firstpos;
939         lastpos = firstpos;
940
941         // so copy characters into theword  until we get a nonletter
942         // note that this can easily exceed lastpos, wich means
943         // that if used in the middle of a word, the whole word
944         // is included
945
946         while (IsLetter(lastpos)) theword += GetChar(lastpos++);
947         
948         return theword;
949
950 }
951
952  
953 LyXParagraph::size_type LyXParagraph::Last() const
954 {
955         if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
956                 return text.size() + NextAfterFootnote()->Last() + 1;
957         // the 1 is the symbol
958         // for the footnote
959         else
960                 return text.size();
961 }
962
963
964 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
965 {
966         // > because last is the next unused position, and you can 
967         // use it if you want
968         if (pos > size()) {
969                 if (next
970                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
971                         return NextAfterFootnote()
972                                 ->ParFromPos(pos - text.size() - 1);
973                 else 
974                         lyxerr << "ERROR (LyXParagraph::ParFromPos): "
975                                 "position does not exist." << endl;
976                 return this;
977         } else
978                 return this;
979 }
980
981
982 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
983 {
984         // > because last is the next unused position, and you can 
985         // use it if you want
986         if (pos > size()) {
987                 if (next
988                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
989                         return NextAfterFootnote()
990                                 ->PositionInParFromPos(pos - text.size() - 1);
991                 else 
992                         lyxerr <<
993                                 "ERROR (LyXParagraph::PositionInParFromPos): "
994                                 "position does not exist." << endl;
995                 return pos;
996         }
997         else
998                 return pos;
999 }
1000
1001
1002 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1003                            LyXFont const & font)
1004 {
1005         // > because last is the next unused position, and you can 
1006         // use it if you want
1007         if (pos > size()) {
1008                 if (next &&
1009                     next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1010                         NextAfterFootnote()->SetFont(pos - text.size() - 1,
1011                                                      font);
1012                 } else {
1013                         lyxerr << "ERROR (LyXParagraph::SetFont): "
1014                                 "position does not exist." << endl;
1015                 }
1016                 return;
1017         }
1018         LyXFont patternfont(LyXFont::ALL_INHERIT);
1019
1020         // First, reduce font against layout/label font
1021         // Update: The SetCharFont() routine in text2.C already
1022         // reduces font, so we don't need to do that here. (Asger)
1023         // No need to simplify this because it will disappear
1024         // in a new kernel. (Asger)
1025         // Next search font table
1026         FontList::iterator tmp = fontlist.begin();
1027         for (; tmp != fontlist.end(); ++tmp) {
1028                 if (pos >= (*tmp).pos && pos <= (*tmp).pos_end) {
1029                         break;
1030                 }
1031         }
1032         if (tmp == fontlist.end()) { // !found
1033                 // if we did not find a font entry, but if the font at hand
1034                 // is the same as default, we just forget it
1035                 if (font == patternfont) return;
1036
1037                 // ok, we did not find a font entry. But maybe there is exactly
1038                 // the needed font ientry one position left
1039                 FontList::iterator tmp2 = fontlist.begin();
1040                 for (; tmp2 != fontlist.end(); ++tmp2) {
1041                         if (pos - 1 >= (*tmp2).pos
1042                             && pos - 1 <= (*tmp2).pos_end)
1043                                 break;
1044                 }
1045                 if (tmp2 != fontlist.end()) {
1046                         // ok there is one, maybe it is exactly
1047                         // the needed font
1048                         if ((*tmp2).font == font) {
1049                                 // put the position under the font
1050                                 (*tmp2).pos_end++;
1051                                 return;
1052                         }
1053                 }
1054                 // Add a new entry in the
1055                 // fontlist for the position
1056                 FontTable ft;
1057                 ft.pos = pos;
1058                 ft.pos_end = pos;
1059                 ft.font = font; // or patternfont
1060                 // It seems that using font instead of patternfont here
1061                 // fixes all the problems. This also surfaces a "bug" in
1062                 // the old code.
1063                 fontlist.insert(fontlist.begin(), ft);
1064         } else if ((*tmp).pos != (*tmp).pos_end) { // we found a font entry. maybe we have to split it and create a new one.
1065
1066 // more than one character
1067                 if (pos == (*tmp).pos) {
1068                         // maybe we should enlarge the left fonttable
1069                         FontList::iterator tmp2 = fontlist.begin();
1070                         for (; tmp2 != fontlist.end(); ++tmp2) {
1071                                 if (pos - 1 >= (*tmp2).pos
1072                                     && pos - 1 <= (*tmp2).pos_end)
1073                                         break;
1074                         }
1075                         // Is there is one, and is it exactly
1076                         // the needed font?
1077                         if (tmp2 != fontlist.end() &&
1078                             (*tmp2).font == font) {
1079                                 // Put the position under the font
1080                                 (*tmp2).pos_end++;
1081                                 (*tmp).pos++;
1082                                 return;
1083                         }
1084
1085                         // Add a new entry in the
1086                         // fontlist for the position
1087                         FontTable ft;
1088                         ft.pos = pos + 1;
1089                         ft.pos_end = (*tmp).pos_end;
1090                         ft.font = (*tmp).font;
1091                         (*tmp).pos_end = pos;
1092                         (*tmp).font = font;
1093                         fontlist.insert(fontlist.begin(), ft);
1094                 } else if (pos == (*tmp).pos_end) {
1095                         // Add a new entry in the
1096                         // fontlist for the position
1097                         FontTable ft;
1098                         ft.pos = (*tmp).pos;
1099                         ft.pos_end = (*tmp).pos_end - 1;
1100                         ft.font = (*tmp).font;
1101                         (*tmp).pos = (*tmp).pos_end;
1102                         (*tmp).font = font;
1103                         fontlist.insert(fontlist.begin(), ft);
1104                 } else {
1105                         // Add a new entry in the
1106                         // fontlist for the position
1107                         FontTable ft;
1108                         ft.pos = (*tmp).pos;
1109                         ft.pos_end = pos - 1;
1110                         ft.font = (*tmp).font;
1111                         
1112                         FontTable ft2;
1113                         ft2.pos = pos + 1;
1114                         ft2.pos_end = (*tmp).pos_end;
1115                         ft2.font = (*tmp).font;
1116                         
1117                         (*tmp).pos = pos;
1118                         (*tmp).pos_end = pos;
1119                         (*tmp).font = font;
1120                         
1121                         fontlist.insert(fontlist.begin(), ft);
1122                         fontlist.insert(fontlist.begin(), ft2);
1123                 }
1124         } else {
1125                 (*tmp).font = font;
1126         }
1127 }
1128
1129    
1130 // This function is able to hide closed footnotes.
1131 LyXParagraph * LyXParagraph::Next()
1132 {
1133         if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1134                 LyXParagraph * tmp = next;
1135                 while (tmp
1136                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1137                         tmp = tmp->next;
1138                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1139                         return tmp->Next(); /* there can be more than one
1140                                                footnote in a logical
1141                                                paragraph */
1142                 else
1143                         return next;  // This should never happen!
1144         } else
1145                 return next;
1146 }
1147
1148
1149 LyXParagraph * LyXParagraph::NextAfterFootnote()
1150 {
1151         if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1152                 LyXParagraph * tmp = next;
1153                 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1154                         tmp = tmp->next;
1155                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1156                         return tmp;   /* there can be more than one footnote
1157                                          in a logical paragraph */
1158                 else
1159                         return next;  // This should never happen!
1160         } else
1161                 return next;
1162 }
1163
1164
1165 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1166 {
1167         if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1168                 LyXParagraph * tmp = next;
1169                 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1170                         tmp = tmp->next;
1171                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1172                         return tmp;   /* there can be more than one footnote
1173                                          in a logical paragraph */
1174                 else
1175                         return next;  // This should never happen!
1176         } else
1177                 return next;
1178 }
1179
1180
1181 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1182 {
1183         LyXParagraph * tmp;
1184         if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1185                 tmp = next;
1186                 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1187                         tmp = tmp->previous;
1188                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1189                         return tmp;    /* there can be more than one footnote
1190                                           in a logical paragraph */
1191                 else
1192                         return previous;  // This should never happen!
1193         } else
1194                 return previous;
1195 }
1196
1197
1198 LyXParagraph * LyXParagraph::LastPhysicalPar()
1199 {
1200         if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1201                 return this;
1202    
1203         LyXParagraph * tmp = this;
1204         while (tmp->next
1205                && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1206                 tmp = tmp->NextAfterFootnote();
1207    
1208         return tmp;
1209    
1210 }
1211
1212
1213 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1214 {
1215         if (!IsDummy())
1216                 return this;
1217         LyXParagraph * tmppar = this;
1218
1219         while (tmppar &&
1220                (tmppar->IsDummy()
1221                 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1222                 tmppar = tmppar->previous;
1223    
1224         if (!tmppar) {
1225                 return this;
1226         } else
1227                 return tmppar;
1228 }
1229
1230
1231 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1232 {
1233         if (!IsDummy())
1234                 return this;
1235         LyXParagraph const * tmppar = this;
1236
1237         while (tmppar &&
1238                (tmppar->IsDummy()
1239                 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1240                 tmppar = tmppar->previous;
1241    
1242         if (!tmppar) {
1243                 return this;
1244         } else
1245                 return tmppar;
1246 }
1247
1248
1249 // This function is able to hide closed footnotes.
1250 LyXParagraph * LyXParagraph::Previous()
1251 {
1252         LyXParagraph * tmp = previous;
1253         if (!tmp)
1254                 return tmp;
1255    
1256         if (tmp->previous
1257             && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1258                 tmp = tmp->previous;
1259                 while (tmp
1260                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1261                         tmp = tmp->previous;
1262                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1263                         return tmp->next->Previous();   
1264
1265                 else
1266                         return previous; 
1267         } else
1268                 return previous;
1269 }
1270
1271
1272 // This function is able to hide closed footnotes.
1273 LyXParagraph const * LyXParagraph::Previous() const
1274 {
1275         LyXParagraph * tmp = previous;
1276         if (!tmp)
1277                 return tmp;
1278    
1279         if (tmp->previous
1280             && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1281                 tmp = tmp->previous;
1282                 while (tmp
1283                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1284                         tmp = tmp->previous;
1285                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1286                         return tmp->next->Previous();   
1287
1288                 else
1289                         return previous; 
1290         } else
1291                 return previous;
1292 }
1293
1294
1295 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1296                                   int flag)
1297 {
1298         size_type i, pos_end, pos_first;
1299         // create a new paragraph
1300         LyXParagraph * par = ParFromPos(pos);
1301         LyXParagraph * firstpar = FirstPhysicalPar();
1302    
1303         LyXParagraph * tmp = new LyXParagraph(par);
1304         
1305         tmp->footnoteflag = footnoteflag;
1306         tmp->footnotekind = footnotekind;
1307    
1308         // this is an idea for a more userfriendly layout handling, I will
1309         // see what the users say
1310    
1311         // layout stays the same with latex-environments
1312         if (flag) {
1313                 tmp->SetOnlyLayout(firstpar->layout);
1314                 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1315         }
1316
1317         if (Last() > pos || !Last() || flag == 2) {
1318                 tmp->SetOnlyLayout(firstpar->layout);
1319                 tmp->align = firstpar->align;
1320                 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1321       
1322                 tmp->line_bottom = firstpar->line_bottom;
1323                 firstpar->line_bottom = false;
1324                 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1325                 firstpar->pagebreak_bottom = false;
1326                 tmp->added_space_bottom = firstpar->added_space_bottom;
1327                 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1328       
1329                 tmp->depth = firstpar->depth;
1330                 tmp->noindent = firstpar->noindent;
1331    
1332                 // copy everything behind the break-position
1333                 // to the new paragraph
1334                 pos_first = 0;
1335                 while (ParFromPos(pos_first) != par)
1336                         ++pos_first;
1337
1338                 pos_end = pos_first + par->text.size() - 1;
1339                 // The constructor has already reserved 500 elements
1340                 //if (pos_end > pos)
1341                 //      tmp->text.reserve(pos_end - pos);
1342
1343                 for (i = pos; i <= pos_end; ++i) {
1344                         par->CutIntoMinibuffer(i - pos_first);
1345                         tmp->InsertFromMinibuffer(i - pos);
1346                 }
1347                 tmp->text.resize(tmp->text.size());
1348                 for (i = pos_end; i >= pos; --i)
1349                         par->Erase(i - pos_first);
1350
1351                 par->text.resize(par->text.size());
1352         }
1353
1354         // just an idea of me
1355         if (!pos) {
1356                 tmp->line_top = firstpar->line_top;
1357                 tmp->pagebreak_top = firstpar->pagebreak_top;
1358                 tmp->added_space_top = firstpar->added_space_top;
1359                 tmp->bibkey = firstpar->bibkey;
1360                 firstpar->Clear();
1361                 // layout stays the same with latex-environments
1362                 if (flag) {
1363                         firstpar->SetOnlyLayout(tmp->layout);
1364                         firstpar->SetLabelWidthString(tmp->labelwidthstring);
1365                         firstpar->depth = tmp->depth;
1366                 }
1367         }
1368 }
1369
1370
1371 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1372 {
1373         par = par->FirstPhysicalPar();
1374         footnoteflag = par->footnoteflag;
1375         footnotekind = par->footnotekind;
1376
1377         layout = par->layout;
1378         align = par-> align;
1379         SetLabelWidthString(par->labelwidthstring);
1380
1381         line_bottom = par->line_bottom;
1382         pagebreak_bottom = par->pagebreak_bottom;
1383         added_space_bottom = par->added_space_bottom;
1384
1385         line_top = par->line_top;
1386         pagebreak_top = par->pagebreak_top;
1387         added_space_top = par->added_space_top;
1388
1389         pextra_type = par->pextra_type;
1390         pextra_width = par->pextra_width;
1391         pextra_widthp = par->pextra_widthp;
1392         pextra_alignment = par->pextra_alignment;
1393         pextra_hfill = par->pextra_hfill;
1394         pextra_start_minipage = par->pextra_start_minipage;
1395
1396         noindent = par->noindent;
1397         depth = par->depth;
1398 }
1399
1400
1401 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1402 {
1403         LyXParagraph * tmppar = this;
1404         while (tmppar && (
1405                 (tmppar->IsDummy()
1406                  && tmppar->previous->footnoteflag == 
1407                  LyXParagraph::CLOSED_FOOTNOTE)
1408                 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1409                 tmppar = tmppar->previous;
1410    
1411         if (!tmppar)
1412                 return this;  // This should never happen!
1413         else
1414                 return tmppar;
1415 }
1416
1417
1418 LyXParagraph * LyXParagraph::Clone() const
1419 {
1420         // create a new paragraph
1421         LyXParagraph * result = new LyXParagraph;
1422    
1423         result->MakeSameLayout(this);
1424
1425         // this is because of the dummy layout of the paragraphs that
1426         // follow footnotes
1427         result->layout = layout;
1428    
1429         /* table stuff -- begin*/ 
1430         if (table)
1431                 result->table = table->Clone();
1432         else
1433                 result->table = 0;
1434         /* table stuff -- end*/ 
1435    
1436         // ale970302
1437         result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1438                
1439     
1440         // copy everything behind the break-position to the new paragraph
1441    
1442         for (size_type i = 0; i < size(); ++i) {
1443                 CopyIntoMinibuffer(i);
1444                 result->InsertFromMinibuffer(i);
1445         }
1446         result->text.resize(result->text.size());
1447         return result;
1448 }
1449
1450
1451 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1452 {
1453         par = par->FirstPhysicalPar();
1454
1455         return (
1456                 par->footnoteflag == footnoteflag &&
1457                 par->footnotekind == footnotekind &&
1458
1459                 par->layout == layout &&
1460
1461                 par->align == align &&
1462
1463                 par->line_bottom == line_bottom &&
1464                 par->pagebreak_bottom == pagebreak_bottom &&
1465                 par->added_space_bottom == added_space_bottom &&
1466
1467                 par->line_top == line_top &&
1468                 par->pagebreak_top == pagebreak_top &&
1469                 par->added_space_top == added_space_top &&
1470
1471                 par->pextra_type == pextra_type &&
1472                 par->pextra_width == pextra_width && 
1473                 par->pextra_widthp == pextra_widthp && 
1474                 par->pextra_alignment == pextra_alignment && 
1475                 par->pextra_hfill == pextra_hfill && 
1476                 par->pextra_start_minipage == pextra_start_minipage && 
1477
1478                 par->table == table && // what means: NO TABLE AT ALL 
1479
1480                 par->noindent == noindent &&
1481                 par->depth == depth);
1482 }
1483
1484
1485 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
1486 {
1487         // create a new paragraph
1488         LyXParagraph * par = ParFromPos(pos);
1489
1490         LyXParagraph * tmp = new LyXParagraph(par);
1491    
1492         tmp->MakeSameLayout(par);
1493
1494         // When can pos < Last()?
1495         // I guess pos == Last() is possible.
1496         if (Last() > pos) {
1497                 // copy everything behind the break-position to the new
1498                 // paragraph
1499                 size_type pos_first = 0;
1500                 while (ParFromPos(pos_first) != par)
1501                         ++pos_first;
1502                 size_type pos_end = pos_first + par->text.size() - 1;
1503                 // make sure there is enough memory for the now larger
1504                 // paragraph. This is not neccessary, because
1505                 // InsertFromMinibuffer will enlarge the memory (it uses
1506                 // InsertChar of course). But doing it by hand
1507                 // is MUCH faster! (only one time, not thousend times!!)
1508                 // Not needed since the constructor aleady have
1509                 // reserved 500 elements in text.
1510                 //if (pos_end > pos)
1511                 //      tmp->text.reserve(pos_end - pos);
1512
1513                 for (size_type i = pos; i <= pos_end; ++i) {
1514                         par->CutIntoMinibuffer(i - pos_first);
1515                         tmp->InsertFromMinibuffer(i - pos);
1516                 }
1517                 tmp->text.resize(tmp->text.size());
1518                 for (size_type i = pos_end; i >= pos; --i)
1519                         par->Erase(i - pos_first);
1520
1521                 par->text.resize(par->text.size());
1522         }
1523 }
1524    
1525
1526 // Be carefull, this does not make any check at all.
1527 void LyXParagraph::PasteParagraph()
1528 {
1529         // copy the next paragraph to this one
1530         LyXParagraph * the_next = Next();
1531    
1532         LyXParagraph * firstpar = FirstPhysicalPar();
1533    
1534         // first the DTP-stuff
1535         firstpar->line_bottom = the_next->line_bottom;
1536         firstpar->added_space_bottom = the_next->added_space_bottom;
1537         firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1538
1539         size_type pos_end = the_next->text.size() - 1;
1540         size_type pos_insert = Last();
1541
1542         // ok, now copy the paragraph
1543         for (size_type i = 0; i <= pos_end; ++i) {
1544                 the_next->CutIntoMinibuffer(i);
1545                 InsertFromMinibuffer(pos_insert + i);
1546         }
1547    
1548         // delete the next paragraph
1549         delete the_next;
1550 }
1551
1552
1553 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1554 {
1555         LyXParagraph * par = ParFromPos(pos);
1556         par = par->next;
1557         while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1558                 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1559                 par = par->next;
1560         }
1561 }
1562
1563
1564 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1565 {
1566         LyXParagraph * par = ParFromPos(pos);
1567         par = par->next;
1568         while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1569                 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1570                 par = par->next;
1571         }
1572 }
1573
1574
1575 LyXTextClass::size_type LyXParagraph::GetLayout() const
1576 {
1577         return FirstPhysicalPar()->layout;
1578 }
1579
1580
1581 char LyXParagraph::GetDepth() const
1582 {
1583         return FirstPhysicalPar()->depth;
1584 }
1585
1586
1587 char LyXParagraph::GetAlign() const
1588 {
1589         return FirstPhysicalPar()->align;
1590 }
1591
1592
1593 string LyXParagraph::GetLabestring() const
1594 {
1595         return FirstPhysicalPar()->labelstring;
1596 }
1597
1598
1599 int LyXParagraph::GetFirstCounter(int i) const
1600 {
1601         return FirstPhysicalPar()->counter_[i];
1602 }
1603
1604
1605 // the next two functions are for the manual labels
1606 string LyXParagraph::GetLabelWidthString() const
1607 {
1608         if (!FirstPhysicalPar()->labelwidthstring.empty())
1609                 return FirstPhysicalPar()->labelwidthstring;
1610         else
1611                 return _("Senseless with this layout!");
1612 }
1613
1614
1615 void LyXParagraph::SetLabelWidthString(string const & s)
1616 {
1617         LyXParagraph * par = FirstPhysicalPar();
1618
1619         par->labelwidthstring = s;
1620 }
1621
1622
1623 void LyXParagraph::SetOnlyLayout(LyXTextClass::size_type new_layout)
1624 {
1625         LyXParagraph * par = FirstPhysicalPar();
1626         LyXParagraph * ppar = 0;
1627         LyXParagraph * npar = 0;
1628
1629         par->layout = new_layout;
1630         /* table stuff -- begin*/ 
1631         if (table) 
1632                 par->layout = 0;
1633         /* table stuff -- end*/ 
1634         if (par->pextra_type == PEXTRA_NONE) {
1635                 if (par->Previous()) {
1636                         ppar = par->Previous()->FirstPhysicalPar();
1637                         while(ppar
1638                               && ppar->Previous()
1639                               && (ppar->depth > par->depth))
1640                                 ppar = ppar->Previous()->FirstPhysicalPar();
1641                 }
1642                 if (par->Next()) {
1643                         npar = par->Next()->NextAfterFootnote();
1644                         while(npar
1645                               && npar->Next()
1646                               && (npar->depth > par->depth))
1647                                 npar = npar->Next()->NextAfterFootnote();
1648                 }
1649                 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1650                         string
1651                                 p1 = ppar->pextra_width,
1652                                 p2 = ppar->pextra_widthp;
1653                         ppar->SetPExtraType(ppar->pextra_type,
1654                                             p1.c_str(), p2.c_str());
1655                 }
1656                 if ((par->pextra_type == PEXTRA_NONE) &&
1657                     npar && (npar->pextra_type != PEXTRA_NONE)) {
1658                         string
1659                                 p1 = npar->pextra_width,
1660                                 p2 = npar->pextra_widthp;
1661                         npar->SetPExtraType(npar->pextra_type,
1662                                             p1.c_str(), p2.c_str());
1663                 }
1664         }
1665 }
1666
1667
1668 void LyXParagraph::SetLayout(LyXTextClass::size_type new_layout)
1669 {
1670         LyXParagraph
1671                 * par = FirstPhysicalPar(),
1672                 * ppar = 0,
1673                 * npar = 0;
1674
1675         par->layout = new_layout;
1676         par->labelwidthstring.clear();
1677         par->align = LYX_ALIGN_LAYOUT;
1678         par->added_space_top = VSpace(VSpace::NONE);
1679         par->added_space_bottom = VSpace(VSpace::NONE);
1680         /* table stuff -- begin*/ 
1681         if (table) 
1682                 par->layout = 0;
1683         /* table stuff -- end*/
1684         if (par->pextra_type == PEXTRA_NONE) {
1685                 if (par->Previous()) {
1686                         ppar = par->Previous()->FirstPhysicalPar();
1687                         while(ppar
1688                               && ppar->Previous()
1689                               && (ppar->depth > par->depth))
1690                                 ppar = ppar->Previous()->FirstPhysicalPar();
1691                 }
1692                 if (par->Next()) {
1693                         npar = par->Next()->NextAfterFootnote();
1694                         while(npar
1695                               && npar->Next()
1696                               && (npar->depth > par->depth))
1697                                 npar = npar->Next()->NextAfterFootnote();
1698                 }
1699                 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1700                         string
1701                                 p1 = ppar->pextra_width,
1702                                 p2 = ppar->pextra_widthp;
1703                         ppar->SetPExtraType(ppar->pextra_type,
1704                                             p1.c_str(), p2.c_str());
1705                 }
1706                 if ((par->pextra_type == PEXTRA_NONE) &&
1707                     npar && (npar->pextra_type != PEXTRA_NONE)) {
1708                         string
1709                                 p1 = npar->pextra_width,
1710                                 p2 = npar->pextra_widthp;
1711                         npar->SetPExtraType(npar->pextra_type,
1712                                             p1.c_str(), p2.c_str());
1713                 }
1714         }
1715 }
1716
1717
1718 // if the layout of a paragraph contains a manual label, the beginning of the 
1719 // main body is the beginning of the second word. This is what the par-
1720 // function returns. If the layout does not contain a label, the main
1721 // body always starts with position 0. This differentiation is necessary,
1722 // because there cannot be a newline or a blank <= the beginning of the 
1723 // main body in TeX.
1724
1725 int LyXParagraph::BeginningOfMainBody() const
1726 {
1727         if (FirstPhysicalPar() != this)
1728                 return -1;
1729    
1730         // Unroll the first two cycles of the loop
1731         // and remember the previous character to
1732         // remove unnecessary GetChar() calls
1733         size_type i = 0;
1734         if (i < size()
1735             && GetChar(i) != LyXParagraph::META_NEWLINE
1736                 ) {
1737                 ++i;
1738                 char previous_char = 0, temp = 0; 
1739                 if (i < size()
1740                     && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1741                         // Yes, this  ^ is supposed to be "= " not "=="
1742                         ++i;
1743                         while (i < size()
1744                                && previous_char != ' '
1745                                && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1746                                 ++i;
1747                                 previous_char = temp;
1748                         }
1749                 }
1750         }
1751
1752         if (i == 0 && i == size() &&
1753             !(footnoteflag == LyXParagraph::NO_FOOTNOTE
1754               && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1755                 ++i;                           /* the cursor should not jump  
1756                                                 * to the main body if there
1757                                                 * is nothing in! */
1758         return i;
1759 }
1760
1761
1762 LyXParagraph * LyXParagraph::DepthHook(int deth)
1763 {
1764         LyXParagraph * newpar = this;
1765         if (deth < 0)
1766                 return 0;
1767    
1768         do {
1769                 newpar = newpar->FirstPhysicalPar()->Previous();
1770         } while (newpar && newpar->GetDepth() > deth
1771                  && newpar->footnoteflag == footnoteflag);
1772    
1773         if (!newpar) {
1774                 if (Previous() || GetDepth())
1775                         lyxerr << "ERROR (LyXParagraph::DepthHook): "
1776                                 "no hook." << endl;
1777                 newpar = this;
1778         }
1779         return newpar->FirstPhysicalPar();
1780 }
1781
1782
1783 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
1784 {
1785         LyXParagraph const * newpar = this;
1786         if (deth < 0)
1787                 return 0;
1788    
1789         do {
1790                 newpar = newpar->FirstPhysicalPar()->Previous();
1791         } while (newpar && newpar->GetDepth() > deth
1792                  && newpar->footnoteflag == footnoteflag);
1793    
1794         if (!newpar) {
1795                 if (Previous() || GetDepth())
1796                         lyxerr << "ERROR (LyXParagraph::DepthHook): "
1797                                 "no hook." << endl;
1798                 newpar = this;
1799         }
1800         return newpar->FirstPhysicalPar();
1801 }
1802
1803
1804 int LyXParagraph::AutoDeleteInsets()
1805 {
1806         vector<size_type> tmpvec;
1807         int i = 0;
1808         for (InsetList::iterator it = insetlist.begin();
1809              it != insetlist.end(); ++it) {
1810                 if ((*it).inset && (*it).inset->AutoDelete()) {
1811                         tmpvec.push_back((*it).pos);
1812                         ++i;
1813                 }
1814         }
1815         for (vector<size_type>::const_iterator cit = tmpvec.begin();
1816              cit != tmpvec.end(); ++cit) {
1817                 Erase((*cit));
1818         }
1819         return i;
1820 }
1821
1822
1823 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
1824 {
1825         InsetList::iterator it2 = insetlist.end();
1826         for (InsetList::iterator it = insetlist.begin();
1827              it != insetlist.end(); ++it) {
1828                 if ((*it).pos >= pos) {
1829                         if (it2 == insetlist.end() || (*it).pos < (*it2).pos)
1830                                 it2 = it;
1831                 }
1832         }
1833         if (it2 != insetlist.end()) {
1834                 pos = (*it2).pos;
1835                 return (*it2).inset;
1836         }
1837         return 0;
1838 }
1839
1840
1841 // returns -1 if inset not found
1842 int LyXParagraph::GetPositionOfInset(Inset * inset) const
1843 {
1844         // Find the entry.
1845         for (InsetList::const_iterator cit = insetlist.begin();
1846              cit != insetlist.end(); ++cit) {
1847                 if ((*cit).inset == inset) {
1848                         return (*cit).pos;
1849                 }
1850         }
1851         // Think about footnotes.
1852         if (footnoteflag == LyXParagraph::NO_FOOTNOTE 
1853             && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1854                 int further = 
1855                         NextAfterFootnote()->GetPositionOfInset(inset);
1856                 if (further != -1)
1857                         return text.size() + 1 + further;
1858         }
1859         return -1;
1860 }
1861
1862
1863 void LyXParagraph::readSimpleWholeFile(istream & is)
1864 {
1865         is.seekg(0);
1866         char c = 0;
1867         while(!is.eof()) {
1868                 is.get(c);
1869                 InsertChar(text.size(), c);
1870         };
1871 }
1872
1873
1874 #ifdef USE_OSTREAM_ONLY
1875 LyXParagraph * LyXParagraph::TeXOnePar(ostream & os, TexRow & texrow,
1876                                        ostream & foot, TexRow & foot_texrow,
1877                                        int & foot_count)
1878 {
1879         lyxerr[Debug::LATEX] << "TeXOnePar...     " << this << endl;
1880         LyXParagraph * par = next;
1881         LyXLayout const & style =
1882                 textclasslist.Style(current_view->buffer()->params.textclass,
1883                                     layout);
1884
1885         bool further_blank_line = false;
1886         if (IsDummy())
1887                 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1888
1889         if (start_of_appendix) {
1890                 os << "\\appendix\n";
1891                 texrow.newline();
1892         }
1893
1894         if (tex_code_break_column && style.isCommand()){
1895                 os << '\n';
1896                 texrow.newline();
1897         }
1898
1899         if (pagebreak_top) {
1900                 os << "\\newpage";
1901                 further_blank_line = true;
1902         }
1903         if (added_space_top.kind() != VSpace::NONE) {
1904                 os << added_space_top.asLatexCommand(current_view->buffer()->params);
1905                 further_blank_line = true;
1906         }
1907       
1908         if (line_top) {
1909                 os << "\\lyxline{\\" << getFont(0).latexSize() << '}'
1910                    << "\\vspace{-1\\parskip}";
1911                 further_blank_line = true;
1912         }
1913
1914         if (further_blank_line){
1915                 os << '\n';
1916                 texrow.newline();
1917         }
1918
1919         LyXDirection direction = getParDirection();
1920         LyXDirection global_direction =
1921                 current_view->buffer()->params.getDocumentDirection();
1922         if (direction != global_direction) {
1923                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
1924                         os << "\\unsethebrew\n";
1925                 else
1926                         os << "\\sethebrew\n";
1927                 texrow.newline();
1928         }
1929         
1930
1931         switch (style.latextype) {
1932         case LATEX_COMMAND:
1933                 os << '\\'
1934                    << style.latexname()
1935                    << style.latexparam();
1936                 break;
1937         case LATEX_ITEM_ENVIRONMENT:
1938                 if (bibkey) {
1939                         bibkey->Latex(os, false);
1940                 } else
1941                         os << "\\item ";
1942                 break;
1943         case LATEX_LIST_ENVIRONMENT:
1944                 os << "\\item ";
1945                 break;
1946         default:
1947                 break;
1948         }
1949
1950         bool need_par = SimpleTeXOnePar(os, texrow);
1951  
1952         // Spit out footnotes
1953         while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
1954                && par->footnoteflag != footnoteflag) {
1955                 par = par->TeXFootnote(os, texrow,
1956                                        foot, foot_texrow, foot_count,
1957                                        direction);
1958                 par->SimpleTeXOnePar(os, texrow);
1959                 par = par->next;
1960         }
1961
1962         // Make sure that \\par is done with the font of the last
1963         // character if this has another size as the default.
1964         // This is necessary because LaTeX (and LyX on the screen)
1965         // calculates the space between the baselines according
1966         // to this font. (Matthias)
1967         LyXFont font = getFont(Last() - 1);
1968         if (need_par) {
1969                 if (style.resfont.size() != font.size()) {
1970                         os << '\\'
1971                            << font.latexSize()
1972                            << ' ';
1973                 }
1974                 os << "\\par}";
1975         } else if (textclasslist.Style(current_view->buffer()->params.textclass,
1976                                        GetLayout()).isCommand()){
1977                 if (style.resfont.size() != font.size()) {
1978                         os << '\\'
1979                            << font.latexSize()
1980                            << ' ';
1981                 }
1982                 os << '}';
1983         } else if (style.resfont.size() != font.size()){
1984                 os << "{\\" << font.latexSize() << " \\par}";
1985         }
1986
1987         if (direction != global_direction)
1988                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
1989                         os << "\\sethebrew";
1990                 else
1991                         os << "\\unsethebrew";
1992         
1993         switch (style.latextype) {
1994         case LATEX_ITEM_ENVIRONMENT:
1995         case LATEX_LIST_ENVIRONMENT:
1996                 if (par && (depth < par->depth)) {
1997                         os << '\n';
1998                         texrow.newline();
1999                 }
2000                 break;
2001         case LATEX_ENVIRONMENT:
2002                 // if its the last paragraph of the current environment
2003                 // skip it otherwise fall through
2004                 if (par
2005                     && (par->layout != layout
2006                         || par->depth != depth
2007                         || par->pextra_type != pextra_type))
2008                         break;
2009         default:
2010                 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2011                       && footnotekind != LyXParagraph::FOOTNOTE
2012                       && footnotekind != LyXParagraph::MARGIN
2013                       && (table
2014                           || (par
2015                               && par->table)))) {
2016                         // don't insert this if we would be adding it
2017                         // before or after a table in a float.  This 
2018                         // little trick is needed in order to allow
2019                         // use of tables in \subfigures or \subtables.
2020                         os << '\n';
2021                         texrow.newline();
2022                 }
2023         }
2024         
2025         further_blank_line = false;
2026         if (line_bottom) {
2027                 os << "\\lyxline{\\" << getFont(Last() - 1).latexSize() << '}';
2028                 further_blank_line = true;
2029         }
2030
2031         if (added_space_bottom.kind() != VSpace::NONE) {
2032                 os << added_space_bottom.asLatexCommand(current_view->buffer()->params);
2033                 further_blank_line = true;
2034         }
2035       
2036         if (pagebreak_bottom) {
2037                 os << "\\newpage";
2038                 further_blank_line = true;
2039         }
2040
2041         if (further_blank_line){
2042                 os << '\n';
2043                 texrow.newline();
2044         }
2045
2046         if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2047               par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2048                 os << '\n';
2049                 texrow.newline();
2050         }
2051
2052         lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2053         return par;
2054 }
2055 #else
2056 LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow,
2057                                        string & foot, TexRow & foot_texrow,
2058                                        int & foot_count)
2059 {
2060         lyxerr[Debug::LATEX] << "TeXOnePar...     " << this << endl;
2061         LyXParagraph * par = next;
2062         LyXLayout const & style =
2063                 textclasslist.Style(current_view->buffer()->params.textclass,
2064                                     layout);
2065
2066         bool further_blank_line = false;
2067         if (IsDummy())
2068                 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
2069
2070         if (start_of_appendix) {
2071                 file += "\\appendix\n";
2072                 texrow.newline();
2073         }
2074
2075         if (tex_code_break_column && style.isCommand()){
2076                 file += '\n';
2077                 texrow.newline();
2078         }
2079
2080         if (pagebreak_top) {
2081                 file += "\\newpage";
2082                 further_blank_line = true;
2083         }
2084         if (added_space_top.kind() != VSpace::NONE) {
2085                 file += added_space_top.asLatexCommand(current_view->buffer()->params);
2086                 further_blank_line = true;
2087         }
2088       
2089         if (line_top) {
2090                 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
2091                 file += "\\vspace{-1\\parskip}";
2092                 further_blank_line = true;
2093         }
2094
2095         if (further_blank_line){
2096                 file += '\n';
2097                 texrow.newline();
2098         }
2099
2100         LyXDirection direction = getParDirection();
2101         LyXDirection global_direction =
2102                 current_view->buffer()->params.getDocumentDirection();
2103         if (direction != global_direction) {
2104                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
2105                         file += "\\unsethebrew\n";
2106                 else
2107                         file += "\\sethebrew\n";
2108                 texrow.newline();
2109         }
2110         
2111
2112         switch (style.latextype) {
2113         case LATEX_COMMAND:
2114                 file += '\\';
2115                 file += style.latexname();
2116                 file += style.latexparam();
2117                 break;
2118         case LATEX_ITEM_ENVIRONMENT:
2119                 if (bibkey) {
2120 #ifdef USE_OSTREAM_ONLY
2121 #ifdef HAVE_SSTREAM
2122                         ostringstream ost;
2123                         bibkey->Latex(ost, false);
2124                         file += ost.str().c_str();
2125 #else
2126                         ostrstream ost;
2127                         bibkey->Latex(ost, false);
2128                         ost << '\0';
2129                         char * tmp = ost.str();
2130                         file += tmp;
2131                         delete [] tmp;
2132 #endif
2133 #else
2134                         bibkey->Latex(file, false);
2135 #endif
2136                 } else
2137                         file += "\\item ";
2138                 break;
2139         case LATEX_LIST_ENVIRONMENT:
2140                 file += "\\item ";
2141                 break;
2142         default:
2143                 break;
2144         }
2145
2146         bool need_par = SimpleTeXOnePar(file, texrow);
2147  
2148         // Spit out footnotes
2149         while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2150                && par->footnoteflag != footnoteflag) {
2151                 par = par->TeXFootnote(file, texrow,
2152                                        foot, foot_texrow, foot_count,
2153                                        direction);
2154                 par->SimpleTeXOnePar(file, texrow);
2155                 par = par->next;
2156         }
2157
2158         // Make sure that \\par is done with the font of the last
2159         // character if this has another size as the default.
2160         // This is necessary because LaTeX (and LyX on the screen)
2161         // calculates the space between the baselines according
2162         // to this font. (Matthias)
2163         LyXFont font = getFont(Last()-1);
2164         if (need_par) {
2165                 if (style.resfont.size() != font.size()) {
2166                         file += '\\';
2167                         file += font.latexSize();
2168                         file += ' ';
2169                 }
2170                 file += "\\par}";
2171         } else if (textclasslist.Style(current_view->buffer()->params.textclass,
2172                                        GetLayout()).isCommand()){
2173                 if (style.resfont.size() != font.size()) {
2174                         file += '\\';
2175                         file += font.latexSize();
2176                         file += ' ';
2177                 }
2178                 file += '}';
2179         } else if (style.resfont.size() != font.size()){
2180                 file += "{\\" + font.latexSize() + " \\par}";
2181         }
2182
2183         if (direction != global_direction)
2184                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
2185                         file += "\\sethebrew";
2186                 else
2187                         file += "\\unsethebrew";
2188         
2189         switch (style.latextype) {
2190         case LATEX_ITEM_ENVIRONMENT:
2191         case LATEX_LIST_ENVIRONMENT:
2192                 if (par && (depth < par->depth)) {
2193                         file += '\n';
2194                         texrow.newline();
2195                 }
2196                 break;
2197         case LATEX_ENVIRONMENT:
2198                 // if its the last paragraph of the current environment
2199                 // skip it otherwise fall through
2200                 if (par
2201                     && (par->layout != layout
2202                         || par->depth != depth
2203                         || par->pextra_type != pextra_type))
2204                         break;
2205         default:
2206                 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2207                       && footnotekind != LyXParagraph::FOOTNOTE
2208                       && footnotekind != LyXParagraph::MARGIN
2209                       && (table
2210                           || (par
2211                               && par->table)))) {
2212                         // don't insert this if we would be adding it
2213                         // before or after a table in a float.  This 
2214                         // little trick is needed in order to allow
2215                         // use of tables in \subfigures or \subtables.
2216                         file += '\n';
2217                         texrow.newline();
2218                 }
2219         }
2220         
2221         further_blank_line = false;
2222         if (line_bottom) {
2223                 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2224                 further_blank_line = true;
2225         }
2226
2227         if (added_space_bottom.kind() != VSpace::NONE) {
2228                 file += added_space_bottom.asLatexCommand(current_view->buffer()->params);
2229                 further_blank_line = true;
2230         }
2231       
2232         if (pagebreak_bottom) {
2233                 file += "\\newpage";
2234                 further_blank_line = true;
2235         }
2236
2237         if (further_blank_line){
2238                 file += '\n';
2239                 texrow.newline();
2240         }
2241
2242         if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2243               par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2244                 file += '\n';
2245                 texrow.newline();
2246         }
2247
2248         lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2249         return par;
2250 }
2251 #endif
2252
2253
2254 // This one spits out the text of the paragraph
2255 #ifdef USE_OSTREAM_ONLY
2256 bool LyXParagraph::SimpleTeXOnePar(ostream & os, TexRow & texrow)
2257 {
2258         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...     " << this << endl;
2259
2260         if (table)
2261                 return SimpleTeXOneTablePar(os, texrow);
2262
2263         bool return_value = false;
2264
2265         LyXLayout const & style =
2266                 textclasslist.Style(current_view->buffer()->params.textclass,
2267                                     GetLayout());
2268         LyXFont basefont, last_font;
2269
2270         // Maybe we have to create a optional argument.
2271         size_type main_body;
2272         if (style.labeltype != LABEL_MANUAL)
2273                 main_body = 0;
2274         else
2275                 main_body = BeginningOfMainBody();
2276
2277         if (main_body > 0) {
2278                 os << '[';
2279                 basefont = getFont(-2); // Get label font
2280         } else {
2281                 basefont = getFont(-1); // Get layout font
2282         }
2283
2284         int column = 0;
2285
2286         if (main_body >= 0
2287             && !text.size()
2288             && !IsDummy()) {
2289                 if (style.isCommand()) {
2290                         os << '{';
2291                         ++column;
2292                 } else if (align != LYX_ALIGN_LAYOUT) {
2293                         os << '{';
2294                         ++column;
2295                         return_value = true;
2296                 }
2297         }
2298  
2299         // Which font is currently active?
2300         LyXFont running_font(basefont);
2301         // Do we have an open font change?
2302         bool open_font = false;
2303
2304         texrow.start(this, 0);
2305
2306         for (size_type i = 0; i < size(); ++i) {
2307                 ++column;
2308                 // First char in paragraph or after label?
2309                 if (i == main_body && !IsDummy()) {
2310                         if (main_body > 0) {
2311                                 if (open_font) {
2312                                         column += running_font.latexWriteEndChanges(os, basefont, basefont);
2313                                         open_font = false;
2314                                 }
2315                                 basefont = getFont(-1); // Now use the layout font
2316                                 running_font = basefont;
2317                                 os << ']';
2318                                 ++column;
2319                         }
2320                         if (style.isCommand()) {
2321                                 os << '{';
2322                                 ++column;
2323                         } else if (align != LYX_ALIGN_LAYOUT) {
2324                                 os << "{\\par";
2325                                 column += 4;
2326                                 return_value = true;
2327                         }
2328
2329                         if (noindent) {
2330                                 os << "\\noindent ";
2331                                 column += 10;
2332                         }
2333                         switch (align) {
2334                         case LYX_ALIGN_NONE:
2335                         case LYX_ALIGN_BLOCK:
2336                         case LYX_ALIGN_LAYOUT:
2337                         case LYX_ALIGN_SPECIAL: break;
2338                         case LYX_ALIGN_LEFT:
2339                                 os << "\\raggedright ";
2340                                 column+= 13;
2341                                 break;
2342                         case LYX_ALIGN_RIGHT:
2343                                 os << "\\raggedleft ";
2344                                 column+= 12;
2345                                 break;
2346                         case LYX_ALIGN_CENTER:
2347                                 os << "\\centering ";
2348                                 column+= 11;
2349                                 break;
2350                         }        
2351                 }
2352
2353                 int c = GetChar(i);
2354
2355                 // Fully instantiated font
2356                 LyXFont font = getFont(i);
2357                 last_font = running_font;
2358
2359                 // Spaces at end of font change are simulated to be
2360                 // outside font change, i.e. we write "\textXX{text} "
2361                 // rather than "\textXX{text }". (Asger)
2362                 if (open_font && c == ' ' && i <= size() - 2 
2363                     && !getFont(i+1).equalExceptLatex(running_font) 
2364                     && !getFont(i+1).equalExceptLatex(font)) {
2365                         font = getFont(i + 1);
2366                 }
2367                 // We end font definition before blanks
2368                 if (!font.equalExceptLatex(running_font) && open_font) {
2369                         column += running_font.latexWriteEndChanges(os,
2370                                                                     basefont,
2371                                                                     (i == main_body-1) ? basefont : font);
2372                         running_font = basefont;
2373                         open_font = false;
2374                 }
2375
2376                 // Blanks are printed before start of fontswitch
2377                 if (c == ' '){
2378                         // Do not print the separation of the optional argument
2379                         if (i != main_body - 1) {
2380                                 SimpleTeXBlanks(os, texrow, i,
2381                                                 column, font, style);
2382                         }
2383                 }
2384
2385                 // Do we need to change font?
2386                 if (!font.equalExceptLatex(running_font)
2387                     && i != main_body-1) {
2388                         column += font.latexWriteStartChanges(os, basefont,
2389                                                               last_font);
2390                         running_font = font;
2391                         open_font = true;
2392                 }
2393
2394                 if (c == LyXParagraph::META_NEWLINE) {
2395                         // newlines are handled differently here than
2396                         // the default in SimpleTeXSpecialChars().
2397                         if (!style.newline_allowed
2398                             || font.latex() == LyXFont::ON) {
2399                                 os << '\n';
2400                         } else {
2401                                 if (open_font) {
2402                                         column += running_font.latexWriteEndChanges(os, basefont, basefont);
2403                                         open_font = false;
2404                                 }
2405                                 basefont = getFont(-1);
2406                                 running_font = basefont;
2407                                 if (font.family() == 
2408                                     LyXFont::TYPEWRITER_FAMILY) {
2409                                         os << "~";
2410                                 }
2411                                 os << "\\\\\n";
2412                         }
2413                         texrow.newline();
2414                         texrow.start(this, i + 1);
2415                         column = 0;
2416                 } else {
2417                         SimpleTeXSpecialChars(os, texrow,
2418                                               font, running_font, basefont,
2419                                               open_font, style, i, column, c);
2420                 }
2421         }
2422
2423         // If we have an open font definition, we have to close it
2424         if (open_font) {
2425                 running_font.latexWriteEndChanges(os, basefont, basefont);
2426         }
2427
2428         // Needed if there is an optional argument but no contents.
2429         if (main_body > 0 && main_body == size()) {
2430                 os << "]~";
2431                 return_value = false;
2432         }
2433
2434         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2435         return return_value;
2436 }
2437 #else
2438 bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow)
2439 {
2440         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...     " << this << endl;
2441
2442         if (table)
2443                 return SimpleTeXOneTablePar(file, texrow);
2444
2445         bool return_value = false;
2446
2447         LyXLayout const & style =
2448                 textclasslist.Style(current_view->buffer()->params.textclass,
2449                                     GetLayout());
2450         LyXFont basefont, last_font;
2451
2452         // Maybe we have to create a optional argument.
2453         size_type main_body;
2454         if (style.labeltype != LABEL_MANUAL)
2455                 main_body = 0;
2456         else
2457                 main_body = BeginningOfMainBody();
2458
2459         if (main_body > 0) {
2460                 file += '[';
2461                 basefont = getFont(-2); // Get label font
2462         } else {
2463                 basefont = getFont(-1); // Get layout font
2464         }
2465
2466         int column = 0;
2467
2468         if (main_body >= 0
2469             && !text.size()
2470             && !IsDummy()) {
2471                 if (style.isCommand()) {
2472                         file += '{';
2473                         ++column;
2474                 } else if (align != LYX_ALIGN_LAYOUT) {
2475                         file += '{';
2476                         ++column;
2477                         return_value = true;
2478                 }
2479         }
2480  
2481         // Which font is currently active?
2482         LyXFont running_font = basefont;
2483         // Do we have an open font change?
2484         bool open_font = false;
2485
2486         texrow.start(this, 0);
2487
2488         for (size_type i = 0; i < size(); ++i) {
2489                 ++column;
2490                 // First char in paragraph or after label?
2491                 if (i == main_body && !IsDummy()) {
2492                         if (main_body > 0) {
2493                                 if (open_font) {
2494                                         column += running_font.latexWriteEndChanges(file, basefont, basefont);
2495                                         open_font = false;
2496                                 }
2497                                 basefont = getFont(-1); // Now use the layout font
2498                                 running_font = basefont;
2499                                 file += ']';
2500                                 ++column;
2501                         }
2502                         if (style.isCommand()) {
2503                                 file += '{';
2504                                 ++column;
2505                         } else if (align != LYX_ALIGN_LAYOUT) {
2506                                 file += "{\\par";
2507                                 column += 4;
2508                                 return_value = true;
2509                         }
2510
2511                         if (noindent) {
2512                                 file += "\\noindent ";
2513                                 column += 10;
2514                         }
2515                         switch (align) {
2516                         case LYX_ALIGN_NONE:
2517                         case LYX_ALIGN_BLOCK:
2518                         case LYX_ALIGN_LAYOUT:
2519                         case LYX_ALIGN_SPECIAL: break;
2520                         case LYX_ALIGN_LEFT:
2521                                 file += "\\raggedright ";
2522                                 column+= 13;
2523                                 break;
2524                         case LYX_ALIGN_RIGHT:
2525                                 file += "\\raggedleft ";
2526                                 column+= 12;
2527                                 break;
2528                         case LYX_ALIGN_CENTER:
2529                                 file += "\\centering ";
2530                                 column+= 11;
2531                                 break;
2532                         }        
2533                 }
2534
2535                 int c = GetChar(i);
2536
2537                 // Fully instantiated font
2538                 LyXFont font = getFont(i);
2539                 last_font = running_font;
2540
2541                 // Spaces at end of font change are simulated to be
2542                 // outside font change, i.e. we write "\textXX{text} "
2543                 // rather than "\textXX{text }". (Asger)
2544                 if (open_font && c == ' ' && i <= size() - 2 
2545                     && !getFont(i+1).equalExceptLatex(running_font) 
2546                     && !getFont(i+1).equalExceptLatex(font)) {
2547                         font = getFont(i + 1);
2548                 }
2549                 // We end font definition before blanks
2550                 if (!font.equalExceptLatex(running_font) && open_font) {
2551                         column += running_font.latexWriteEndChanges(file,
2552                                                                     basefont,
2553                                                                     (i == main_body-1) ? basefont : font);
2554                         running_font = basefont;
2555                         open_font = false;
2556                 }
2557
2558                 // Blanks are printed before start of fontswitch
2559                 if (c == ' '){
2560                         // Do not print the separation of the optional argument
2561                         if (i != main_body - 1) {
2562                                 SimpleTeXBlanks(file, texrow, i,
2563                                                 column, font, style);
2564                         }
2565                 }
2566
2567                 // Do we need to change font?
2568                 if (!font.equalExceptLatex(running_font)
2569                     && i != main_body-1) {
2570                         column += font.latexWriteStartChanges(file, basefont, last_font);
2571                         running_font = font;
2572                         open_font = true;
2573                 }
2574
2575                 if (c == LyXParagraph::META_NEWLINE) {
2576                         // newlines are handled differently here than
2577                         // the default in SimpleTeXSpecialChars().
2578                         if (!style.newline_allowed
2579                             || font.latex() == LyXFont::ON) {
2580                                 file += '\n';
2581                         } else {
2582                                 if (open_font) {
2583                                         column += running_font.latexWriteEndChanges(file, basefont, basefont);
2584                                         open_font = false;
2585                                 }
2586                                 basefont = getFont(-1);
2587                                 running_font = basefont;
2588                                 if (font.family() == 
2589                                     LyXFont::TYPEWRITER_FAMILY) {
2590                                         file += "~";
2591                                 }
2592                                 file += "\\\\\n";
2593                         }
2594                         texrow.newline();
2595                         texrow.start(this, i + 1);
2596                         column = 0;
2597                 } else {
2598                         SimpleTeXSpecialChars(file, texrow,
2599                                               font, running_font, basefont,
2600                                               open_font, style, i, column, c);
2601                 }
2602         }
2603
2604         // If we have an open font definition, we have to close it
2605         if (open_font) {
2606                 running_font.latexWriteEndChanges(file, basefont, basefont);
2607         }
2608
2609         // Needed if there is an optional argument but no contents.
2610         if (main_body > 0 && main_body == size()) {
2611                 file += "]~";
2612                 return_value = false;
2613         }
2614
2615         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2616         return return_value;
2617 }
2618 #endif
2619
2620
2621 #ifdef USE_OSTREAM_ONLY
2622 // This one spits out the text of a table paragraph
2623 bool LyXParagraph::SimpleTeXOneTablePar(ostream & os, TexRow & texrow)
2624 {
2625         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...     " << this << endl;
2626    
2627         bool return_value = false;
2628
2629         LyXLayout const & style = 
2630                 textclasslist.Style(current_view->buffer()->params.textclass,
2631                                     GetLayout());
2632  
2633         int column = 0;
2634         if (!IsDummy()) { // it is dummy if it is in a float!!!
2635                 if (style.isCommand()) {
2636                         os << '{';
2637                         ++column;
2638                 } else if (align != LYX_ALIGN_LAYOUT) {
2639                         os << '{';
2640                         ++column;
2641                         return_value = true;
2642                 }
2643                 if (noindent) {
2644                         os << "\\noindent ";
2645                         column += 10;
2646                 }
2647                 switch (align) {
2648                 case LYX_ALIGN_NONE:
2649                 case LYX_ALIGN_BLOCK:
2650                 case LYX_ALIGN_LAYOUT:
2651                 case LYX_ALIGN_SPECIAL: break;
2652                 case LYX_ALIGN_LEFT:
2653                         os << "\\raggedright ";
2654                         column+= 13;
2655                         break;
2656                 case LYX_ALIGN_RIGHT:
2657                         os << "\\raggedleft ";
2658                         column+= 12;
2659                         break;
2660                 case LYX_ALIGN_CENTER:
2661                         os << "\\centering ";
2662                         column+= 11;
2663                         break;
2664                 }
2665         }
2666
2667         LyXFont basefont = getFont(-1); // Get layout font
2668         // Which font is currently active?
2669         LyXFont running_font = basefont;
2670         LyXFont last_font;
2671         // Do we have an open font change?
2672         bool open_font = false;
2673         int current_cell_number = -1;
2674         int tmp = table->TexEndOfCell(os, current_cell_number);
2675         for (; tmp > 0 ; --tmp)
2676                 texrow.newline();
2677         
2678         texrow.start(this, 0);
2679
2680         for (size_type i = 0; i < size(); ++i) {
2681                 char c = GetChar(i);
2682                 if (table->IsContRow(current_cell_number + 1)) {
2683                         if (c == LyXParagraph::META_NEWLINE)
2684                                 ++current_cell_number;
2685                         continue;
2686                 }
2687                 ++column;
2688                 
2689                 // Fully instantiated font
2690                 LyXFont font = getFont(i);
2691                 last_font = running_font;
2692
2693                 // Spaces at end of font change are simulated to be
2694                 // outside font change.
2695                 // i.e. we write "\textXX{text} " rather than
2696                 // "\textXX{text }". (Asger)
2697                 if (open_font && c == ' ' && i <= size() - 2
2698                     && getFont(i + 1) != running_font
2699                     && getFont(i + 1) != font) {
2700                         font = getFont(i + 1);
2701                 }
2702
2703                 // We end font definition before blanks
2704                 if (font != running_font && open_font) {
2705                         column += running_font.latexWriteEndChanges(os,
2706                                                                     basefont,
2707                                                                     font);
2708                         running_font = basefont;
2709                         open_font = false;
2710                 }
2711                 // Blanks are printed before start of fontswitch
2712                 if (c == ' '){
2713                         SimpleTeXBlanks(os, texrow, i, column, font, style);
2714                 }
2715                 // Do we need to change font?
2716                 if (font != running_font) {
2717                         column += font.latexWriteStartChanges(os, basefont,
2718                                                               last_font);
2719                         running_font = font;
2720                         open_font = true;
2721                 }
2722                 // Do we need to turn on LaTeX mode?
2723                 if (font.latex() != running_font.latex()) {
2724                         if (font.latex() == LyXFont::ON
2725                             && style.needprotect) {
2726                                 os << "\\protect ";
2727                                 column += 9;
2728                         }
2729                 }
2730                 if (c == LyXParagraph::META_NEWLINE) {
2731                         // special case for inside a table
2732                         // different from default case in
2733                         // SimpleTeXSpecialChars()
2734                         if (open_font) {
2735                                 column += running_font
2736                                         .latexWriteEndChanges(os, basefont,
2737                                                               basefont);
2738                                 open_font = false;
2739                         }
2740                         basefont = getFont(-1);
2741                         running_font = basefont;
2742                         ++current_cell_number;
2743                         if (table->CellHasContRow(current_cell_number) >= 0) {
2744                                 TeXContTableRows(os, i + 1,
2745                                                  current_cell_number,
2746                                                  column, texrow);
2747                         }
2748                         // if this cell follow only ContRows till end don't
2749                         // put the EndOfCell because it is put after the
2750                         // for(...)
2751                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2752                                 --current_cell_number;
2753                                 break;
2754                         }
2755                         int tmp = table->TexEndOfCell(os,
2756                                                       current_cell_number);
2757                         if (tmp > 0) {
2758                                 column = 0;
2759                         } else if (tmp < 0) {
2760                                 tmp = -tmp;
2761                         }
2762                         for (; tmp--;) {
2763                                 texrow.newline();
2764                         }
2765                         texrow.start(this, i + 1);
2766                 } else {
2767                         SimpleTeXSpecialChars(os, texrow,
2768                                               font, running_font, basefont,
2769                                               open_font, style, i, column, c);
2770                 }
2771         }
2772
2773         // If we have an open font definition, we have to close it
2774         if (open_font) {
2775                 running_font.latexWriteEndChanges(os, basefont, basefont);
2776         }
2777         ++current_cell_number;
2778         tmp = table->TexEndOfCell(os, current_cell_number);
2779         for (; tmp > 0; --tmp)
2780                 texrow.newline();
2781         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2782         return return_value;
2783 }
2784 #else
2785 // This one spits out the text of a table paragraph
2786 bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow)
2787 {
2788         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...     " << this << endl;
2789    
2790         bool return_value = false;
2791
2792         LyXLayout const & style = 
2793                 textclasslist.Style(current_view->buffer()->params.textclass,
2794                                     GetLayout());
2795  
2796         int column = 0;
2797         if (!IsDummy()) { // it is dummy if it is in a float!!!
2798                 if (style.isCommand()) {
2799                         file += '{';
2800                         ++column;
2801                 } else if (align != LYX_ALIGN_LAYOUT) {
2802                         file += '{';
2803                         ++column;
2804                         return_value = true;
2805                 }
2806                 if (noindent) {
2807                         file += "\\noindent ";
2808                         column += 10;
2809                 }
2810                 switch (align) {
2811                 case LYX_ALIGN_NONE:
2812                 case LYX_ALIGN_BLOCK:
2813                 case LYX_ALIGN_LAYOUT:
2814                 case LYX_ALIGN_SPECIAL: break;
2815                 case LYX_ALIGN_LEFT:
2816                         file += "\\raggedright ";
2817                         column+= 13;
2818                         break;
2819                 case LYX_ALIGN_RIGHT:
2820                         file += "\\raggedleft ";
2821                         column+= 12;
2822                         break;
2823                 case LYX_ALIGN_CENTER:
2824                         file += "\\centering ";
2825                         column+= 11;
2826                         break;
2827                 }
2828         }
2829
2830         LyXFont basefont = getFont(-1); // Get layout font
2831         // Which font is currently active?
2832         LyXFont running_font = basefont;
2833         LyXFont last_font;
2834         // Do we have an open font change?
2835         bool open_font = false;
2836         int current_cell_number = -1;
2837         int tmp = table->TexEndOfCell(file, current_cell_number);
2838         for (; tmp > 0 ; --tmp)
2839                 texrow.newline();
2840         
2841         texrow.start(this, 0);
2842
2843         for (size_type i = 0; i < size(); ++i) {
2844                 char c = GetChar(i);
2845                 if (table->IsContRow(current_cell_number + 1)) {
2846                         if (c == LyXParagraph::META_NEWLINE)
2847                                 ++current_cell_number;
2848                         continue;
2849                 }
2850                 ++column;
2851                 
2852                 // Fully instantiated font
2853                 LyXFont font = getFont(i);
2854                 last_font = running_font;
2855
2856                 // Spaces at end of font change are simulated to be
2857                 // outside font change.
2858                 // i.e. we write "\textXX{text} " rather than
2859                 // "\textXX{text }". (Asger)
2860                 if (open_font && c == ' ' && i <= size() - 2
2861                     && getFont(i+1) != running_font && getFont(i+1) != font) {
2862                         font = getFont(i+1);
2863                 }
2864
2865                 // We end font definition before blanks
2866                 if (font != running_font && open_font) {
2867                         column += running_font.latexWriteEndChanges(file,
2868                                                                     basefont, font);
2869                         running_font = basefont;
2870                         open_font = false;
2871                 }
2872                 // Blanks are printed before start of fontswitch
2873                 if (c == ' '){
2874                         SimpleTeXBlanks(file, texrow, i, column, font, style);
2875                 }
2876                 // Do we need to change font?
2877                 if (font != running_font) {
2878                         column += font.latexWriteStartChanges(file, basefont, last_font);
2879                         running_font = font;
2880                         open_font = true;
2881                 }
2882                 // Do we need to turn on LaTeX mode?
2883                 if (font.latex() != running_font.latex()) {
2884                         if (font.latex() == LyXFont::ON
2885                             && style.needprotect) {
2886                                 file += "\\protect ";
2887                                 column += 9;
2888                         }
2889                 }
2890                 if (c == LyXParagraph::META_NEWLINE) {
2891                         // special case for inside a table
2892                         // different from default case in
2893                         // SimpleTeXSpecialChars()
2894                         if (open_font) {
2895                                 column += running_font
2896                                         .latexWriteEndChanges(file, basefont, basefont);
2897                                 open_font = false;
2898                         }
2899                         basefont = getFont(-1);
2900                         running_font = basefont;
2901                         ++current_cell_number;
2902                         if (table->CellHasContRow(current_cell_number) >= 0) {
2903                                 TeXContTableRows(file, i + 1,
2904                                                  current_cell_number,
2905                                                  column, texrow);
2906                         }
2907                         // if this cell follow only ContRows till end don't
2908                         // put the EndOfCell because it is put after the
2909                         // for(...)
2910                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2911                                 --current_cell_number;
2912                                 break;
2913                         }
2914                         int tmp = table->TexEndOfCell(file,
2915                                                       current_cell_number);
2916                         if (tmp > 0) {
2917                                 column = 0;
2918                         } else if (tmp < 0) {
2919                                 tmp = -tmp;
2920                         }
2921                         for (; tmp--;) {
2922                                 texrow.newline();
2923                         }
2924                         texrow.start(this, i + 1);
2925                 } else {
2926                         SimpleTeXSpecialChars(file, texrow,
2927                                               font, running_font, basefont,
2928                                               open_font, style, i, column, c);
2929                 }
2930         }
2931
2932         // If we have an open font definition, we have to close it
2933         if (open_font) {
2934                 running_font.latexWriteEndChanges(file, basefont, basefont);
2935         }
2936         ++current_cell_number;
2937         tmp = table->TexEndOfCell(file, current_cell_number);
2938         for (; tmp > 0; --tmp)
2939                 texrow.newline();
2940         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2941         return return_value;
2942 }
2943 #endif
2944
2945
2946 #ifdef USE_OSTREAM_ONLY
2947 // This one spits out the text off ContRows in tables
2948 bool LyXParagraph::TeXContTableRows(ostream & os,
2949                                     LyXParagraph::size_type i,
2950                                     int current_cell_number,
2951                                     int & column, TexRow & texrow)
2952 {
2953         lyxerr[Debug::LATEX] << "TeXContTableRows...     " << this << endl;
2954         if (!table)
2955                 return false;
2956     
2957         char c;
2958    
2959         bool return_value = false;
2960         LyXLayout const & style =
2961                 textclasslist.Style(current_view->buffer()->params.textclass,
2962                                     GetLayout());
2963         LyXFont basefont = getFont(-1); // Get layout font
2964         LyXFont last_font;
2965         // Which font is currently active?
2966         LyXFont running_font = basefont;
2967         // Do we have an open font change?
2968         bool open_font = false;
2969
2970         size_type lastpos = i;
2971         int cell = table->CellHasContRow(current_cell_number);
2972         ++current_cell_number;
2973         while(cell >= 0) {
2974                 // first find the right position
2975                 i = lastpos;
2976                 for (; (i < size()) && (current_cell_number<cell); ++i) {
2977                         c = GetChar(i);
2978                         if (c == LyXParagraph::META_NEWLINE)
2979                                 ++current_cell_number;
2980                 }
2981                 lastpos = i;
2982                 c = GetChar(i);
2983                 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2984                         os << " \\\\\n";
2985                         texrow.newline();
2986                         column = 0;
2987                 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2988                         os << ' ';
2989                 }
2990
2991                 for (; i < size()
2992                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2993                      ++i) {
2994                         ++column;
2995
2996                         // Fully instantiated font
2997                         LyXFont font = getFont(i);
2998                         last_font = running_font;
2999
3000                         // Spaces at end of font change are simulated to
3001                         // be outside font change. i.e. we write
3002                         // "\textXX{text} " rather than "\textXX{text }".
3003                         // (Asger)
3004                         if (open_font && c == ' ' && i <= size() - 2 
3005                             && getFont(i + 1) != running_font
3006                             && getFont(i + 1) != font) {
3007                                 font = getFont(i + 1);
3008                         }
3009
3010                         // We end font definition before blanks
3011                         if (font != running_font && open_font) {
3012                                 column += running_font.latexWriteEndChanges(os, basefont, font);
3013                                 running_font = basefont;
3014                                 open_font = false;
3015                         }
3016                         // Blanks are printed before start of fontswitch
3017                         if (c == ' '){
3018                                 SimpleTeXBlanks(os, texrow, i,
3019                                                 column, font, style);
3020                         }
3021                         // Do we need to change font?
3022                         if (font != running_font) {
3023                                 column +=
3024                                         font.latexWriteStartChanges(os,
3025                                                                     basefont,
3026                                                                     last_font);
3027                                 running_font = font;
3028                                 open_font = true;
3029                         }
3030                         // Do we need to turn on LaTeX mode?
3031                         if (font.latex() != running_font.latex()) {
3032                                 if (font.latex() == LyXFont::ON
3033                                     && style.needprotect) {
3034                                         os << "\\protect ";
3035                                         column += 9;
3036                                 }
3037                         }
3038                         SimpleTeXSpecialChars(os, texrow, font,
3039                                               running_font, basefont,
3040                                               open_font, style, i, column, c);
3041                 }
3042                 // If we have an open font definition, we have to close it
3043                 if (open_font) {
3044                         running_font.latexWriteEndChanges(os, basefont,
3045                                                           basefont);
3046                         open_font = false;
3047                 }
3048                 basefont = getFont(-1);
3049                 running_font = basefont;
3050                 cell = table->CellHasContRow(current_cell_number);
3051         }
3052         lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
3053         return return_value;
3054 }
3055 #else
3056 // This one spits out the text off ContRows in tables
3057 bool LyXParagraph::TeXContTableRows(string & file,
3058                                     LyXParagraph::size_type i,
3059                                     int current_cell_number,
3060                                     int & column, TexRow & texrow)
3061 {
3062         lyxerr[Debug::LATEX] << "TeXContTableRows...     " << this << endl;
3063         if (!table)
3064                 return false;
3065     
3066         char c;
3067    
3068         bool return_value = false;
3069         LyXLayout const & style =
3070                 textclasslist.Style(current_view->buffer()->params.textclass,
3071                                     GetLayout());
3072         LyXFont basefont = getFont(-1); // Get layout font
3073         LyXFont last_font;
3074         // Which font is currently active?
3075         LyXFont running_font = basefont;
3076         // Do we have an open font change?
3077         bool open_font = false;
3078
3079         size_type lastpos = i;
3080         int cell = table->CellHasContRow(current_cell_number);
3081         ++current_cell_number;
3082         while(cell >= 0) {
3083                 // first find the right position
3084                 i = lastpos;
3085                 for (; (i < size()) && (current_cell_number<cell); ++i) {
3086                         c = GetChar(i);
3087                         if (c == LyXParagraph::META_NEWLINE)
3088                                 ++current_cell_number;
3089                 }
3090                 lastpos = i;
3091                 c = GetChar(i);
3092                 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3093                         file += " \\\\\n";
3094                         texrow.newline();
3095                         column = 0;
3096                 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
3097                         file += ' ';
3098                 }
3099
3100                 for (; i < size()
3101                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3102                      ++i) {
3103                         ++column;
3104
3105                         // Fully instantiated font
3106                         LyXFont font = getFont(i);
3107                         last_font = running_font;
3108
3109                         // Spaces at end of font change are simulated to
3110                         // be outside font change. i.e. we write
3111                         // "\textXX{text} " rather than "\textXX{text }".
3112                         // (Asger)
3113                         if (open_font && c == ' ' && i <= size() - 2 
3114                             && getFont(i + 1) != running_font
3115                             && getFont(i + 1) != font) {
3116                                 font = getFont(i + 1);
3117                         }
3118
3119                         // We end font definition before blanks
3120                         if (font != running_font && open_font) {
3121                                 column += running_font.latexWriteEndChanges(file, basefont, font);
3122                                 running_font = basefont;
3123                                 open_font = false;
3124                         }
3125                         // Blanks are printed before start of fontswitch
3126                         if (c == ' '){
3127                                 SimpleTeXBlanks(file, texrow, i,
3128                                                 column, font, style);
3129                         }
3130                         // Do we need to change font?
3131                         if (font != running_font) {
3132                                 column +=
3133                                         font.latexWriteStartChanges(file,
3134                                                                     basefont, last_font);
3135                                 running_font = font;
3136                                 open_font = true;
3137                         }
3138                         // Do we need to turn on LaTeX mode?
3139                         if (font.latex() != running_font.latex()) {
3140                                 if (font.latex() == LyXFont::ON
3141                                     && style.needprotect)
3142                                         {
3143                                                 file += "\\protect ";
3144                                                 column += 9;
3145                                         }
3146                         }
3147                         SimpleTeXSpecialChars(file, texrow, font,
3148                                               running_font, basefont,
3149                                               open_font, style, i, column, c);
3150                 }
3151                 // If we have an open font definition, we have to close it
3152                 if (open_font) {
3153                         running_font.latexWriteEndChanges(file, basefont, basefont);
3154                         open_font = false;
3155                 }
3156                 basefont = getFont(-1);
3157                 running_font = basefont;
3158                 cell = table->CellHasContRow(current_cell_number);
3159         }
3160         lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
3161         return return_value;
3162 }
3163 #endif
3164
3165
3166 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
3167 {
3168         bool retval = false;
3169         switch (c) {
3170         case LyXParagraph::META_HFILL:
3171                 sgml_string.clear();
3172                 break;
3173 #if 0
3174         case LyXParagraph::META_PROTECTED_SEPARATOR: 
3175                 sgml_string = ' ';
3176                 break;
3177 #endif
3178         case LyXParagraph::META_NEWLINE:
3179                 sgml_string = '\n';
3180                 break;
3181         case '&': 
3182                 sgml_string = "&amp;";
3183                 break;
3184         case '<': 
3185                 sgml_string = "&lt;"; 
3186                 break;
3187         case '>':
3188                 sgml_string = "&gt;"; 
3189                 break;
3190         case '$': 
3191                 sgml_string = "&dollar;"; 
3192                 break;
3193         case '#': 
3194                 sgml_string = "&num;";
3195                 break;
3196         case '%': 
3197                 sgml_string = "&percnt;";
3198                 break;
3199         case '[': 
3200                 sgml_string = "&lsqb;";
3201                 break;
3202         case ']': 
3203                 sgml_string = "&rsqb;";
3204                 break;
3205         case '{': 
3206                 sgml_string = "&lcub;";
3207                 break;
3208         case '}': 
3209                 sgml_string = "&rcub;";
3210                 break;
3211         case '~': 
3212                 sgml_string = "&tilde;";
3213                 break;
3214         case '"': 
3215                 sgml_string = "&quot;";
3216                 break;
3217         case '\\': 
3218                 sgml_string = "&bsol;";
3219                 break;
3220         case ' ':
3221                 retval = true;
3222                 sgml_string = ' ';
3223                 break;
3224         case '\0': // Ignore :-)
3225                 sgml_string.clear();
3226                 break;
3227         default:
3228                 sgml_string = c;
3229                 break;
3230         }
3231         return retval;
3232 }
3233
3234
3235 #ifdef USE_OSTREAM_ONLY
3236 void LyXParagraph::SimpleDocBookOneTablePar(ostream & os, string & extra,
3237                                             int & desc_on, int depth) 
3238 {
3239         if (!table) return;
3240         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
3241         int column = 0;
3242         LyXFont font1, font2;
3243         char c;
3244         Inset * inset;
3245         size_type main_body;
3246         bool emph_flag = false;
3247         
3248         LyXLayout const & style =
3249                 textclasslist.Style(current_view->buffer()->params.textclass,
3250                                     GetLayout());
3251         
3252         if (style.labeltype != LABEL_MANUAL)
3253                 main_body = 0;
3254         else
3255                 main_body = BeginningOfMainBody();
3256         
3257         // Gets paragraph main font.
3258         if (main_body > 0)
3259                 font1 = style.labelfont;
3260         else
3261                 font1 = style.font;
3262         
3263         int char_line_count = depth;
3264         os << newlineAndDepth(depth);
3265         if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
3266                 os << "<INFORMALTABLE>"
3267                    << newlineAndDepth(++depth);
3268         }
3269         int current_cell_number = -1;
3270         int tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
3271         
3272         // Parsing main loop.
3273         for (size_type i = 0; i < size(); ++i) {
3274                 c = GetChar(i);
3275                 if (table->IsContRow(current_cell_number+1)) {
3276                         if (c == LyXParagraph::META_NEWLINE)
3277                                 ++current_cell_number;
3278                         continue;
3279                 }
3280                 ++column;
3281                 
3282                 // Fully instantiated font
3283                 font2 = getFont(i);
3284                 
3285                 // Handle <emphasis> tag.
3286                 if (font1.emph() != font2.emph() && i) {
3287                         if (font2.emph() == LyXFont::ON) {
3288                                 os << "<emphasis>";
3289                                 emph_flag= true;
3290                         } else if (emph_flag) {
3291                                 os << "</emphasis>";
3292                                 emph_flag= false;
3293                         }
3294                 }
3295                 if (c == LyXParagraph::META_NEWLINE) {
3296                         // We have only to control for emphasis open here!
3297                         if (emph_flag) {
3298                                 os << "</emphasis>";
3299                                 emph_flag= false;
3300                         }
3301                         font1 = font2 = getFont(-1);
3302                         ++current_cell_number;
3303                         if (table->CellHasContRow(current_cell_number) >= 0) {
3304                                 DocBookContTableRows(os, extra, desc_on, i + 1,
3305                                                      current_cell_number,
3306                                                      column);
3307                         }
3308                         // if this cell follow only ContRows till end don't
3309                         // put the EndOfCell because it is put after the
3310                         // for(...)
3311                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
3312                                 --current_cell_number;
3313                                 break;
3314                         }
3315                         tmp = table->DocBookEndOfCell(os,
3316                                                       current_cell_number,
3317                                                       depth);
3318                         
3319                         if (tmp > 0)
3320                                 column = 0;
3321                 } else if (c == LyXParagraph::META_INSET) {
3322                         inset = GetInset(i);
3323 #ifdef HAVE_SSTREAM
3324                         ostringstream ost;
3325                         inset->DocBook(ost);
3326                         string tmp_out = ost.str().c_str();
3327 #else
3328                         ostrstream ost;
3329                         inset->DocBook(ost);
3330                         ost << '\0';
3331                         char * ctmp = ost.str();
3332                         string tmp_out(ctmp);
3333                         delete [] ctmp;
3334 #endif
3335                         //
3336                         // This code needs some explanation:
3337                         // Two insets are treated specially
3338                         //   label if it is the first element in a
3339                         //   command paragraph
3340                         //         desc_on == 3
3341                         //   graphics inside tables or figure floats
3342                         //   can't go on
3343                         //   title (the equivalente in latex for this
3344                         //   case is caption
3345                         //   and title should come first
3346                         //         desc_on == 4
3347                         //
3348                         if(desc_on != 3 || i != 0) {
3349                                 if(tmp_out[0] == '@') {
3350                                         if(desc_on == 4)
3351                                                 extra += frontStrip(tmp_out,
3352                                                                     '@');
3353                                         else
3354                                                 os << frontStrip(tmp_out,
3355                                                                  '@');
3356                                 } else
3357                                         os << tmp_out;
3358                         }
3359                 } else if (font2.latex() == LyXFont::ON) {
3360                         // "TeX"-Mode on == > SGML-Mode on.
3361                         if (c != '\0')
3362                                 os << c;
3363                         ++char_line_count;
3364                 } else {
3365                         string sgml_string;
3366                         if (linuxDocConvertChar(c, sgml_string) 
3367                             && !style.free_spacing) {
3368                                 // in freespacing mode, spaces are
3369                                 // non-breaking characters
3370                                 // char is ' '
3371                                 if (desc_on == 1) {
3372                                         ++char_line_count;
3373                                         os << '\n'
3374                                            << "</term><listitem><para>";
3375                                         desc_on = 2;
3376                                 } else  {
3377                                         os << c;
3378                                 }
3379                         } else {
3380                                 os << sgml_string;
3381                         }
3382                 }
3383                 font1 = font2;
3384         }
3385         
3386         // Needed if there is an optional argument but no contents.
3387         if (main_body > 0 && main_body == size()) {
3388                 font1 = style.font;
3389         }
3390
3391         if (emph_flag) {
3392                 os << "</emphasis>";
3393         }
3394         
3395         ++current_cell_number;
3396         tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
3397         // Resets description flag correctly.
3398         switch(desc_on){
3399         case 1:
3400                 // <term> not closed...
3401                 os << "</term>";
3402                 break;
3403         }
3404         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3405                 os << "</INFORMALTABLE>";
3406         os << '\n';
3407         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
3408                              << this << endl;
3409 }
3410 #else
3411 void LyXParagraph::SimpleDocBookOneTablePar(string & file, string & extra,
3412                                             int & desc_on, int depth) 
3413 {
3414         if (!table) return;
3415         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
3416         int column = 0;
3417         LyXFont font1, font2;
3418         char c;
3419         Inset * inset;
3420         size_type main_body;
3421         bool emph_flag = false;
3422         
3423         LyXLayout const & style =
3424                 textclasslist.Style(current_view->buffer()->params.textclass,
3425                                     GetLayout());
3426         
3427         if (style.labeltype != LABEL_MANUAL)
3428                 main_body = 0;
3429         else
3430                 main_body = BeginningOfMainBody();
3431         
3432         // Gets paragraph main font.
3433         if (main_body > 0)
3434                 font1 = style.labelfont;
3435         else
3436                 font1 = style.font;
3437         
3438         int char_line_count = depth;
3439         addNewlineAndDepth(file, depth);
3440         if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
3441                 file += "<INFORMALTABLE>";
3442                 addNewlineAndDepth(file, ++depth);
3443         }
3444         int current_cell_number = -1;
3445         int tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
3446         
3447         // Parsing main loop.
3448         for (size_type i = 0; i < size(); ++i) {
3449                 c = GetChar(i);
3450                 if (table->IsContRow(current_cell_number+1)) {
3451                         if (c == LyXParagraph::META_NEWLINE)
3452                                 ++current_cell_number;
3453                         continue;
3454                 }
3455                 ++column;
3456                 
3457                 // Fully instantiated font
3458                 font2 = getFont(i);
3459                 
3460                 // Handle <emphasis> tag.
3461                 if (font1.emph() != font2.emph() && i) {
3462                         if (font2.emph() == LyXFont::ON) {
3463                                 file += "<emphasis>";
3464                                 emph_flag= true;
3465                         } else if (emph_flag) {
3466                                 file += "</emphasis>";
3467                                 emph_flag= false;
3468                         }
3469                 }
3470                 if (c == LyXParagraph::META_NEWLINE) {
3471                         // We have only to control for emphasis open here!
3472                         if (emph_flag) {
3473                                 file += "</emphasis>";
3474                                 emph_flag= false;
3475                         }
3476                         font1 = font2 = getFont(-1);
3477                         ++current_cell_number;
3478                         if (table->CellHasContRow(current_cell_number) >= 0) {
3479                                 DocBookContTableRows(file, extra, desc_on, i+1,
3480                                                      current_cell_number,
3481                                                      column);
3482                         }
3483                         // if this cell follow only ContRows till end don't
3484                         // put the EndOfCell because it is put after the
3485                         // for(...)
3486                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
3487                                 --current_cell_number;
3488                                 break;
3489                         }
3490                         tmp = table->DocBookEndOfCell(file,
3491                                                       current_cell_number,
3492                                                       depth);
3493                         
3494                         if (tmp > 0)
3495                                 column = 0;
3496                 } else if (c == LyXParagraph::META_INSET) {
3497                         inset = GetInset(i);
3498 #ifdef USE_OSTREAM_ONLY
3499 #ifdef HAVE_SSTREAM
3500                         ostringstream ost;
3501                         inset->DocBook(ost);
3502                         string tmp_out = ost.str().c_str();
3503 #else
3504                         ostrstream ost;
3505                         inset->DocBook(ost);
3506                         ost << '\0';
3507                         char * ctmp = ost.str();
3508                         string tmp_out(ctmp);
3509                         delete [] ctmp;
3510 #endif
3511 #else
3512                         string tmp_out;
3513                         inset->DocBook(tmp_out);
3514 #endif
3515                         //
3516                         // This code needs some explanation:
3517                         // Two insets are treated specially
3518                         //   label if it is the first element in a
3519                         //   command paragraph
3520                         //         desc_on == 3
3521                         //   graphics inside tables or figure floats
3522                         //   can't go on
3523                         //   title (the equivalente in latex for this
3524                         //   case is caption
3525                         //   and title should come first
3526                         //         desc_on == 4
3527                         //
3528                         if(desc_on != 3 || i != 0) {
3529                                 if(tmp_out[0] == '@') {
3530                                         if(desc_on == 4)
3531                                                 extra += frontStrip(tmp_out,
3532                                                                     '@');
3533                                         else
3534                                                 file += frontStrip(tmp_out,
3535                                                                    '@');
3536                                 } else
3537                                         file += tmp_out;
3538                         }
3539                 } else if (font2.latex() == LyXFont::ON) {
3540                         // "TeX"-Mode on == > SGML-Mode on.
3541                         if (c != '\0')
3542                                 file += c;
3543                         ++char_line_count;
3544                 } else {
3545                         string sgml_string;
3546                         if (linuxDocConvertChar(c, sgml_string) 
3547                             && !style.free_spacing) {
3548                                 // in freespacing mode, spaces are
3549                                 // non-breaking characters
3550                                 // char is ' '
3551                                 if (desc_on == 1) {
3552                                         ++char_line_count;
3553                                         file += '\n';
3554                                         file += "</term><listitem><para>";
3555                                         desc_on = 2;
3556                                 } else  {
3557                                         file += c;
3558                                 }
3559                         } else {
3560                                 file += sgml_string;
3561                         }
3562                 }
3563                 font1 = font2;
3564         }
3565         
3566         // Needed if there is an optional argument but no contents.
3567         if (main_body > 0 && main_body == size()) {
3568                 font1 = style.font;
3569         }
3570
3571         if (emph_flag) {
3572                 file += "</emphasis>";
3573         }
3574         
3575         ++current_cell_number;
3576         tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
3577         // Resets description flag correctly.
3578         switch(desc_on){
3579         case 1:
3580                 // <term> not closed...
3581                 file += "</term>";
3582                 break;
3583         }
3584         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3585                 file += "</INFORMALTABLE>";
3586         file += '\n';
3587         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
3588                              << this << endl;
3589 }
3590 #endif
3591
3592
3593 #ifdef USE_OSTREAM_ONLY
3594 void LyXParagraph::DocBookContTableRows(ostream & os, string & extra,
3595                                         int & desc_on,
3596                                         LyXParagraph::size_type i,
3597                                         int current_cell_number, int &column) 
3598
3599 {
3600         if (!table) return;
3601         
3602         lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
3603
3604         LyXFont font2;
3605         char c;
3606         Inset * inset;
3607         //string emph = "emphasis";
3608         bool emph_flag = false;
3609         int char_line_count = 0;
3610         
3611         LyXLayout const & style =
3612                 textclasslist.Style(current_view->buffer()->params.textclass,
3613                                     GetLayout());
3614         
3615         size_type main_body;
3616         if (style.labeltype != LABEL_MANUAL)
3617                 main_body = 0;
3618         else
3619                 main_body = BeginningOfMainBody();
3620         
3621         // Gets paragraph main font.
3622         LyXFont font1;
3623         if (main_body > 0)
3624                 font1 = style.labelfont;
3625         else
3626                 font1 = style.font;
3627         
3628         size_type lastpos = i;
3629         int cell = table->CellHasContRow(current_cell_number);
3630         ++current_cell_number;
3631         while(cell >= 0) {
3632                 // first find the right position
3633                 i = lastpos;
3634                 for (; i < size() && current_cell_number < cell; ++i) {
3635                         c = GetChar(i);
3636                         if (c == LyXParagraph::META_NEWLINE)
3637                                 ++current_cell_number;
3638                 }
3639                 lastpos = i;
3640                 c = GetChar(i);
3641                 // I don't know how to handle this so I comment it
3642                 // for the moment (Jug)
3643 //             if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3644 //                     file += " \\\\\n";
3645 //                     column = 0;
3646 //             } else
3647                 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
3648                         os << ' ';
3649                 }
3650
3651                 for (; i < size()
3652                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3653                      ++i) {
3654                         ++column;
3655                         
3656                         // Fully instantiated font
3657                         font2 = getFont(i);
3658                         
3659                         // Handle <emphasis> tag.
3660                         if (font1.emph() != font2.emph() && i) {
3661                                 if (font2.emph() == LyXFont::ON) {
3662                                         os << "<emphasis>";
3663                                         emph_flag= true;
3664                                 } else if (emph_flag) {
3665                                         os << "</emphasis>";
3666                                         emph_flag= false;
3667                                 }
3668                         }
3669                         if (c == LyXParagraph::META_INSET) {
3670                                 inset = GetInset(i);
3671 #ifdef HAVE_SSTREAM
3672                                 ostringstream ost;
3673                                 inset->DocBook(ost);
3674                                 string tmp_out = ost.str().c_str();
3675 #else
3676                                 ostrstream ost;
3677                                 inset->DocBook(ost);
3678                                 ost << '\0';
3679                                 char * ctmp = ost.str();
3680                                 string tmp_out(ctmp);
3681                                 delete [] ctmp;
3682 #endif
3683                                 //
3684                                 // This code needs some explanation:
3685                                 // Two insets are treated specially
3686                                 //   label if it is the first element in a
3687                                 //   command paragraph
3688                                 //       desc_on == 3
3689                                 //   graphics inside tables or figure floats
3690                                 //   can't go on title (the equivalente in
3691                                 //   latex for this case is caption and title
3692                                 //   should come first
3693                                 //       desc_on == 4
3694                                 //
3695                                 if(desc_on != 3 || i != 0) {
3696                                         if(tmp_out[0] == '@') {
3697                                                 if(desc_on == 4)
3698                                                         extra += frontStrip(tmp_out, '@');
3699                                                 else
3700                                                         os << frontStrip(tmp_out, '@');
3701                                         } else
3702                                                 os << tmp_out;
3703                                 }
3704                         } else if (font2.latex() == LyXFont::ON) {
3705                                 // "TeX"-Mode on == > SGML-Mode on.
3706                                 if (c!= '\0')
3707                                         os << c;
3708                                 ++char_line_count;
3709                         } else {
3710                                 string sgml_string;
3711                                 if (linuxDocConvertChar(c, sgml_string) 
3712                                     && !style.free_spacing) {
3713                                         // in freespacing mode, spaces are
3714                                         // non-breaking characters
3715                                         // char is ' '
3716                                         if (desc_on == 1) {
3717                                                 ++char_line_count;
3718                                                 os << '\n'
3719                                                    << "</term><listitem><para>";
3720                                                 desc_on = 2;
3721                                         } else  {
3722                                                 os << c;
3723                                         }
3724                                 } else {
3725                                         os << sgml_string;
3726                                 }
3727                         }
3728                 }
3729                 // we have only to control for emphasis open here!
3730                 if (emph_flag) {
3731                         os << "</emphasis>";
3732                         emph_flag= false;
3733                 }
3734                 font1 = font2 = getFont(-1);
3735                 cell = table->CellHasContRow(current_cell_number);
3736         }
3737         lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3738 }
3739 #else
3740 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
3741                                         int & desc_on,
3742                                         LyXParagraph::size_type i,
3743                                         int current_cell_number, int &column) 
3744
3745 {
3746         if (!table) return;
3747         
3748         lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
3749
3750         LyXFont font2;
3751         char c;
3752         Inset * inset;
3753         //string emph = "emphasis";
3754         bool emph_flag= false;
3755         int char_line_count= 0;
3756         
3757         LyXLayout const & style =
3758                 textclasslist.Style(current_view->buffer()->params.textclass,
3759                                     GetLayout());
3760         
3761         size_type main_body;
3762         if (style.labeltype != LABEL_MANUAL)
3763                 main_body = 0;
3764         else
3765                 main_body = BeginningOfMainBody();
3766         
3767         // Gets paragraph main font.
3768         LyXFont font1;
3769         if (main_body > 0)
3770                 font1 = style.labelfont;
3771         else
3772                 font1 = style.font;
3773         
3774         size_type lastpos = i;
3775         int cell = table->CellHasContRow(current_cell_number);
3776         ++current_cell_number;
3777         while(cell >= 0) {
3778                 // first find the right position
3779                 i = lastpos;
3780                 for (; i < size() && current_cell_number < cell; ++i) {
3781                         c = GetChar(i);
3782                         if (c == LyXParagraph::META_NEWLINE)
3783                                 ++current_cell_number;
3784                 }
3785                 lastpos = i;
3786                 c = GetChar(i);
3787                 // I don't know how to handle this so I comment it
3788                 // for the moment (Jug)
3789 //             if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3790 //                     file += " \\\\\n";
3791 //                     column = 0;
3792 //             } else
3793                 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
3794                         file += ' ';
3795                 }
3796
3797                 for (; i < size()
3798                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3799                      ++i) {
3800                         ++column;
3801                         
3802                         // Fully instantiated font
3803                         font2 = getFont(i);
3804                         
3805                         // Handle <emphasis> tag.
3806                         if (font1.emph() != font2.emph() && i) {
3807                                 if (font2.emph() == LyXFont::ON) {
3808                                         file += "<emphasis>";
3809                                         emph_flag= true;
3810                                 } else if (emph_flag) {
3811                                         file += "</emphasis>";
3812                                         emph_flag= false;
3813                                 }
3814                         }
3815                         if (c == LyXParagraph::META_INSET) {
3816                                 inset = GetInset(i);
3817 #ifdef USE_OSTREAM_ONLY
3818 #ifdef HAVE_SSTREAM
3819                                 ostringstream ost;
3820                                 inset->DocBook(ost);
3821                                 string tmp_out = ost.str().c_str();
3822 #else
3823                                 ostrstream ost;
3824                                 inset->DocBook(ost);
3825                                 ost << '\0';
3826                                 char * ctmp = ost.str();
3827                                 string tmp_out(ctmp);
3828                                 delete [] ctmp;
3829 #endif
3830 #else
3831                                 string tmp_out;
3832                                 inset->DocBook(tmp_out);
3833 #endif
3834                                 //
3835                                 // This code needs some explanation:
3836                                 // Two insets are treated specially
3837                                 //   label if it is the first element in a
3838                                 //   command paragraph
3839                                 //       desc_on == 3
3840                                 //   graphics inside tables or figure floats
3841                                 //   can't go on title (the equivalente in
3842                                 //   latex for this case is caption and title
3843                                 //   should come first
3844                                 //       desc_on == 4
3845                                 //
3846                                 if(desc_on != 3 || i != 0) {
3847                                         if(tmp_out[0] == '@') {
3848                                                 if(desc_on == 4)
3849                                                         extra += frontStrip(tmp_out, '@');
3850                                                 else
3851                                                         file += frontStrip(tmp_out, '@');
3852                                         } else
3853                                                 file += tmp_out;
3854                                 }
3855                         } else if (font2.latex() == LyXFont::ON) {
3856                                 // "TeX"-Mode on == > SGML-Mode on.
3857                                 if (c!= '\0')
3858                                         file += c;
3859                                 ++char_line_count;
3860                         } else {
3861                                 string sgml_string;
3862                                 if (linuxDocConvertChar(c, sgml_string) 
3863                                     && !style.free_spacing) {
3864                                         // in freespacing mode, spaces are
3865                                         // non-breaking characters
3866                                         // char is ' '
3867                                         if (desc_on == 1) {
3868                                                 ++char_line_count;
3869                                                 file += '\n';
3870                                                 file += "</term><listitem><para>";
3871                                                 desc_on = 2;
3872                                         } else  {
3873                                                 file += c;
3874                                         }
3875                                 } else {
3876                                         file += sgml_string;
3877                                 }
3878                         }
3879                 }
3880                 // we have only to control for emphasis open here!
3881                 if (emph_flag) {
3882                         file += "</emphasis>";
3883                         emph_flag= false;
3884                 }
3885                 font1 = font2 = getFont(-1);
3886                 cell = table->CellHasContRow(current_cell_number);
3887         }
3888         lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3889 }
3890 #endif
3891
3892
3893 #ifdef USE_OSTREAM_ONLY
3894 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
3895                                    LyXParagraph::size_type const i,
3896                                    int & column, LyXFont const & font,
3897                                    LyXLayout const & style)
3898 {
3899         if (column > tex_code_break_column
3900             && i 
3901             && GetChar(i - 1) != ' '
3902             && (i < size() - 1)
3903             // In LaTeX mode, we don't want to
3904             // break lines since some commands
3905             // do not like this
3906             && ! (font.latex() == LyXFont::ON)
3907             // same in FreeSpacing mode
3908             && !style.free_spacing
3909             // In typewriter mode, we want to avoid 
3910             // ! . ? : at the end of a line
3911             && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3912                  && (GetChar(i-1) == '.'
3913                      || GetChar(i-1) == '?' 
3914                      || GetChar(i-1) == ':'
3915                      || GetChar(i-1) == '!'))) {
3916                 if (tex_code_break_column == 0) {
3917                         // in batchmode we need LaTeX to still
3918                         // see it as a space not as an extra '\n'
3919                         os << " %\n";
3920                 } else {
3921                         os << '\n';
3922                 }
3923                 texrow.newline();
3924                 texrow.start(this, i + 1);
3925                 column = 0;
3926         } else if (font.latex() == LyXFont::OFF) {
3927                 if (style.free_spacing) {
3928                         os << '~';
3929                 } else {
3930                         os << ' ';
3931                 }
3932         }
3933 }
3934 #else
3935 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
3936                                    LyXParagraph::size_type const i,
3937                                    int & column, LyXFont const & font,
3938                                    LyXLayout const & style)
3939 {
3940         if (column > tex_code_break_column
3941             && i 
3942             && GetChar(i - 1) != ' '
3943             && (i < size() - 1)
3944             // In LaTeX mode, we don't want to
3945             // break lines since some commands
3946             // do not like this
3947             && ! (font.latex() == LyXFont::ON)
3948             // same in FreeSpacing mode
3949             && !style.free_spacing
3950             // In typewriter mode, we want to avoid 
3951             // ! . ? : at the end of a line
3952             && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3953                  && (GetChar(i-1) == '.'
3954                      || GetChar(i-1) == '?' 
3955                      || GetChar(i-1) == ':'
3956                      || GetChar(i-1) == '!'))) {
3957                 if (tex_code_break_column == 0) {
3958                         // in batchmode we need LaTeX to still
3959                         // see it as a space not as an extra '\n'
3960                         file += " %\n";
3961                 } else {
3962                         file += '\n';
3963                 }
3964                 texrow.newline();
3965                 texrow.start(this, i+1);
3966                 column = 0;
3967         } else if (font.latex() == LyXFont::OFF) {
3968                 if (style.free_spacing) {
3969                         file += '~';
3970                 } else {
3971                         file += ' ';
3972                 }
3973         }
3974 }
3975 #endif
3976
3977
3978 #ifdef USE_OSTREAM_ONLY
3979 void LyXParagraph::SimpleTeXSpecialChars(ostream & os, TexRow & texrow,
3980                                          LyXFont & font,
3981                                          LyXFont & running_font,
3982                                          LyXFont & basefont,
3983                                          bool & open_font,
3984                                          LyXLayout const & style,
3985                                          LyXParagraph::size_type & i,
3986                                          int & column, char const c)
3987 {
3988         // Two major modes:  LaTeX or plain
3989         // Handle here those cases common to both modes
3990         // and then split to handle the two modes separately.
3991         switch (c) {
3992         case LyXParagraph::META_INSET: {
3993                 Inset * inset = GetInset(i);
3994                 if (inset) {
3995                         bool close = false;
3996                         int len = os.tellp();
3997                         if ((inset->LyxCode() == Inset::GRAPHICS_CODE
3998                              || inset->LyxCode() == Inset::MATH_CODE
3999                              || inset->LyxCode() == Inset::URL_CODE)
4000                             && running_font.getFontDirection()
4001                             == LYX_DIR_RIGHT_TO_LEFT) {
4002                                 os << "\\L{";
4003                                 close = true;
4004                         }
4005
4006                         int tmp = inset->Latex(os, style.isCommand());
4007
4008                         if (close)
4009                                 os << "}";
4010                         
4011                         if (tmp) {
4012                                 column = 0;
4013                         } else {
4014                                 column += os.tellp() - len;
4015                         }
4016                         for (; tmp--;) {
4017                                 texrow.newline();
4018                         }
4019                 }
4020         }
4021         break;
4022
4023         case LyXParagraph::META_NEWLINE:
4024                 if (open_font) {
4025                         column += running_font.latexWriteEndChanges(os,
4026                                                                     basefont,
4027                                                                     basefont);
4028                         open_font = false;
4029                 }
4030                 basefont = getFont(-1);
4031                 running_font = basefont;
4032                 break;
4033
4034         case LyXParagraph::META_HFILL: 
4035                 os << "\\hfill{}";
4036                 column += 7;
4037                 break;
4038
4039         default:
4040                 // And now for the special cases within each mode
4041                 // Are we in LaTeX mode?
4042                 if (font.latex() == LyXFont::ON) {
4043                         // at present we only have one option
4044                         // but I'll leave it as a switch statement
4045                         // so its simpler to extend. (ARRae)
4046                         switch (c) {
4047 #if 0
4048                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
4049                                 os << ' ';
4050                                 break;
4051 #endif
4052                         default:
4053                                 // make sure that we will not print
4054                                 // error generating chars to the tex
4055                                 // file. This test would not be needed
4056                                 // if it were done in the buffer
4057                                 // itself.
4058                                 if (c != '\0') {
4059                                         os << c;
4060                                 }
4061                                 break;
4062                         }
4063                 } else {
4064                         // Plain mode (i.e. not LaTeX)
4065                         switch (c) {
4066 #if 0
4067                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
4068                                 os << '~';
4069                                 break;
4070 #endif
4071                         case '\\': 
4072                                 os << "\\textbackslash{}";
4073                                 column += 15;
4074                                 break;
4075                 
4076                         case '°': case '±': case '²': case '³':  
4077                         case '×': case '÷': case '¹': case 'ª':
4078                         case 'º': case '¬': case 'µ':
4079                                 if (current_view->buffer()->params.inputenc == "latin1") {
4080                                         os << "\\ensuremath{"
4081                                            << c
4082                                            << '}';
4083                                         column += 13;
4084                                 } else {
4085                                         os << c;
4086                                 }
4087                                 break;
4088
4089                         case '|': case '<': case '>':
4090                                 // In T1 encoding, these characters exist
4091                                 if (lyxrc->fontenc == "T1") {
4092                                         os << c;
4093                                         //... but we should avoid ligatures
4094                                         if ((c == '>' || c == '<')
4095                                             && i <= size() - 2
4096                                             && GetChar(i + 1) == c){
4097                                                 os << "\\textcompwordmark{}";
4098                                                 column += 19;
4099                                         }
4100                                         break;
4101                                 }
4102                                 // Typewriter font also has them
4103                                 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
4104                                         os << c;
4105                                         break;
4106                                 } 
4107                                 // Otherwise, we use what LaTeX
4108                                 // provides us.
4109                                 switch(c) {
4110                                 case '<':
4111                                         os << "\\textless{}";
4112                                         column += 10;
4113                                         break;
4114                                 case '>':
4115                                         os << "\\textgreater{}";
4116                                         column += 13;
4117                                         break;
4118                                 case '|':
4119                                         os << "\\textbar{}";
4120                                         column += 9;
4121                                         break;
4122                                 }
4123                                 break;
4124
4125                         case '-': // "--" in Typewriter mode -> "-{}-"
4126                                 if (i <= size() - 2
4127                                     && GetChar(i + 1) == '-'
4128                                     && font.family() == LyXFont::TYPEWRITER_FAMILY) {
4129                                         os << "-{}";
4130                                         column += 2;
4131                                 } else {
4132                                         os << '-';
4133                                 }
4134                                 break;
4135
4136                         case '\"': 
4137                                 os << "\\char`\\\"{}";
4138                                 column += 9;
4139                                 break;
4140
4141                         case '£':
4142                                 if (current_view->buffer()->params.inputenc == "default") {
4143                                         os << "\\pounds{}";
4144                                         column += 8;
4145                                 } else {
4146                                         os << c;
4147                                 }
4148                                 break;
4149
4150                         case '$': case '&':
4151                         case '%': case '#': case '{':
4152                         case '}': case '_':
4153                                 os << '\\' << c;
4154                                 column += 1;
4155                                 break;
4156
4157                         case '~':
4158                                 os << "\\textasciitilde{}";
4159                                 column += 16;
4160                                 break;
4161
4162                         case '^':
4163                                 os << "\\textasciicircum{}";
4164                                 column += 17;
4165                                 break;
4166
4167                         case '*': case '[': case ']':
4168                                 // avoid being mistaken for optional arguments
4169                                 os << '{' << c << '}';
4170                                 column += 2;
4171                                 break;
4172
4173                         case ' ':
4174                                 // Blanks are printed before font switching.
4175                                 // Sure? I am not! (try nice-latex)
4176                                 // I am sure it's correct. LyX might be smarter
4177                                 // in the future, but for now, nothing wrong is
4178                                 // written. (Asger)
4179                                 break;
4180
4181                         default:
4182                                 /* idea for labels --- begin*/
4183                                 // Check for "LyX"
4184                                 if (c ==  'L'
4185                                     && i <= size() - 3
4186                                     && font.family() != LyXFont::TYPEWRITER_FAMILY
4187                                     && GetChar(i + 1) == 'y'
4188                                     && GetChar(i + 2) == 'X') {
4189                                         os << "\\LyX{}";
4190                                         i += 2;
4191                                         column += 5;
4192                                 }
4193                                 // Check for "TeX"
4194                                 else if (c == 'T'
4195                                          && i <= size() - 3
4196                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4197                                          && GetChar(i + 1) == 'e'
4198                                          && GetChar(i + 2) == 'X') {
4199                                         os << "\\TeX{}";
4200                                         i += 2;
4201                                         column += 5;
4202                                 }
4203                                 // Check for "LaTeX2e"
4204                                 else if (c == 'L'
4205                                          && i <= size() - 7
4206                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4207                                          && GetChar(i + 1) == 'a'
4208                                          && GetChar(i + 2) == 'T'
4209                                          && GetChar(i + 3) == 'e'
4210                                          && GetChar(i + 4) == 'X'
4211                                          && GetChar(i + 5) == '2'
4212                                          && GetChar(i + 6) == 'e') {
4213                                         os << "\\LaTeXe{}";
4214                                         i += 6;
4215                                         column += 8;
4216                                 }
4217                                 // Check for "LaTeX"
4218                                 else if (c == 'L'
4219                                          && i <= size() - 5
4220                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4221                                          && GetChar(i + 1) == 'a'
4222                                          && GetChar(i + 2) == 'T'
4223                                          && GetChar(i + 3) == 'e'
4224                                          && GetChar(i + 4) == 'X') {
4225                                         os << "\\LaTeX{}";
4226                                         i += 4;
4227                                         column += 7;
4228                                         /* idea for labels --- end*/ 
4229                                 } else if (c != '\0') {
4230                                         os << c;
4231                                 }
4232                                 break;
4233                         }
4234                 }
4235         }
4236 }
4237 #else
4238 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
4239                                          LyXFont & font,
4240                                          LyXFont & running_font,
4241                                          LyXFont & basefont,
4242                                          bool & open_font,
4243                                          LyXLayout const & style,
4244                                          LyXParagraph::size_type & i,
4245                                          int & column, char const c)
4246 {
4247         // Two major modes:  LaTeX or plain
4248         // Handle here those cases common to both modes
4249         // and then split to handle the two modes separately.
4250         switch (c) {
4251         case LyXParagraph::META_INSET: {
4252                 Inset * inset = GetInset(i);
4253                 if (inset) {
4254                         bool close = false;
4255                         int len = file.length();
4256                         if ((inset->LyxCode() == Inset::GRAPHICS_CODE
4257                              || inset->LyxCode() == Inset::MATH_CODE
4258                              || inset->LyxCode() == Inset::URL_CODE)
4259                             && running_font.getFontDirection()
4260                             == LYX_DIR_RIGHT_TO_LEFT) {
4261                                 file += "\\L{";
4262                                 close = true;
4263                         }
4264 #ifdef USE_OSTREAM_ONLY
4265 #ifdef HAVE_SSTREAM
4266                         ostringstream ost;
4267                         int tmp = inset->Latex(ost, style.isCommand());
4268                         file += ost.str().c_str();
4269 #else
4270                         ostrstream ost;
4271                         int tmp = inset->Latex(ost, style.isCommand());
4272                         ost << '\0';
4273                         char * chtmp = ost.str();
4274                         file += chtmp;
4275                         delete [] chtmp;
4276 #endif          
4277 #else
4278                         int tmp = inset->Latex(file, style.isCommand());
4279 #endif
4280                         if (close)
4281                                 file += "}";
4282                         
4283                         if (tmp) {
4284                                 column = 0;
4285                         } else {
4286                                 column += file.length() - len;
4287                         }
4288                         for (; tmp--;) {
4289                                 texrow.newline();
4290                         }
4291                 }
4292         }
4293         break;
4294
4295         case LyXParagraph::META_NEWLINE:
4296                 if (open_font) {
4297                         column += running_font.latexWriteEndChanges(file,
4298                                                                     basefont, basefont);
4299                         open_font = false;
4300                 }
4301                 basefont = getFont(-1);
4302                 running_font = basefont;
4303                 break;
4304
4305         case LyXParagraph::META_HFILL: 
4306                 file += "\\hfill{}";
4307                 column += 7;
4308                 break;
4309
4310         default:
4311                 // And now for the special cases within each mode
4312                 // Are we in LaTeX mode?
4313                 if (font.latex() == LyXFont::ON) {
4314                         // at present we only have one option
4315                         // but I'll leave it as a switch statement
4316                         // so its simpler to extend. (ARRae)
4317                         switch (c) {
4318 #if 0
4319                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
4320                                 file += ' ';
4321                                 break;
4322 #endif
4323                         default:
4324                                 // make sure that we will not print
4325                                 // error generating chars to the tex
4326                                 // file. This test would not be needed
4327                                 // if it were done in the buffer
4328                                 // itself.
4329                                 if (c != '\0') {
4330                                         file += c;
4331                                 }
4332                                 break;
4333                         }
4334                 } else {
4335                         // Plain mode (i.e. not LaTeX)
4336                         switch (c) {
4337 #if 0
4338                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
4339                                 file += '~';
4340                                 break;
4341 #endif
4342                         case '\\': 
4343                                 file += "\\textbackslash{}";
4344                                 column += 15;
4345                                 break;
4346                 
4347                         case '°': case '±': case '²': case '³':  
4348                         case '×': case '÷': case '¹': case 'ª':
4349                         case 'º': case '¬': case 'µ':
4350                                 if (current_view->buffer()->params.inputenc == "latin1") {
4351                                         file += "\\ensuremath{";
4352                                         file += c;
4353                                         file += '}';
4354                                         column += 13;
4355                                 } else {
4356                                         file += c;
4357                                 }
4358                                 break;
4359
4360                         case '|': case '<': case '>':
4361                                 // In T1 encoding, these characters exist
4362                                 if (lyxrc->fontenc == "T1") {
4363                                         file += c;
4364                                         //... but we should avoid ligatures
4365                                         if ((c == '>' || c == '<')
4366                                             && i <= size() - 2
4367                                             && GetChar(i+1) == c){
4368                                                 file += "\\textcompwordmark{}";
4369                                                 column += 19;
4370                                         }
4371                                         break;
4372                                 }
4373                                 // Typewriter font also has them
4374                                 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
4375                                         file += c;
4376                                         break;
4377                                 } 
4378                                 // Otherwise, we use what LaTeX
4379                                 // provides us.
4380                                 switch(c) {
4381                                 case '<':
4382                                         file += "\\textless{}";
4383                                         column += 10;
4384                                         break;
4385                                 case '>':
4386                                         file += "\\textgreater{}";
4387                                         column += 13;
4388                                         break;
4389                                 case '|':
4390                                         file += "\\textbar{}";
4391                                         column += 9;
4392                                         break;
4393                                 }
4394                                 break;
4395
4396                         case '-': // "--" in Typewriter mode -> "-{}-"
4397                                 if (i <= size() - 2
4398                                     && GetChar(i + 1) == '-'
4399                                     && font.family() == LyXFont::TYPEWRITER_FAMILY) {
4400                                         file += "-{}";
4401                                         column += 2;
4402                                 } else {
4403                                         file += '-';
4404                                 }
4405                                 break;
4406
4407                         case '\"': 
4408                                 file += "\\char`\\\"{}";
4409                                 column += 9;
4410                                 break;
4411
4412                         case '£':
4413                                 if (current_view->buffer()->params.inputenc == "default") {
4414                                         file += "\\pounds{}";
4415                                         column += 8;
4416                                 } else {
4417                                         file += c;
4418                                 }
4419                                 break;
4420
4421                         case '$': case '&':
4422                         case '%': case '#': case '{':
4423                         case '}': case '_':
4424                                 file += '\\';
4425                                 file += c;
4426                                 column += 1;
4427                                 break;
4428
4429                         case '~':
4430                                 file += "\\textasciitilde{}";
4431                                 column += 16;
4432                                 break;
4433
4434                         case '^':
4435                                 file += "\\textasciicircum{}";
4436                                 column += 17;
4437                                 break;
4438
4439                         case '*': case '[': case ']':
4440                                 // avoid being mistaken for optional arguments
4441                                 file += '{';
4442                                 file += c;
4443                                 file += '}';
4444                                 column += 2;
4445                                 break;
4446
4447                         case ' ':
4448                                 // Blanks are printed before font switching.
4449                                 // Sure? I am not! (try nice-latex)
4450                                 // I am sure it's correct. LyX might be smarter
4451                                 // in the future, but for now, nothing wrong is
4452                                 // written. (Asger)
4453                                 break;
4454
4455                         default:
4456                                 /* idea for labels --- begin*/
4457                                 // Check for "LyX"
4458                                 if (c ==  'L'
4459                                     && i <= size() - 3
4460                                     && font.family() != LyXFont::TYPEWRITER_FAMILY
4461                                     && GetChar(i + 1) == 'y'
4462                                     && GetChar(i + 2) == 'X') {
4463                                         file += "\\LyX{}";
4464                                         i += 2;
4465                                         column += 5;
4466                                 }
4467                                 // Check for "TeX"
4468                                 else if (c == 'T'
4469                                          && i <= size() - 3
4470                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4471                                          && GetChar(i + 1) == 'e'
4472                                          && GetChar(i + 2) == 'X') {
4473                                         file += "\\TeX{}";
4474                                         i += 2;
4475                                         column += 5;
4476                                 }
4477                                 // Check for "LaTeX2e"
4478                                 else if (c == 'L'
4479                                          && i <= size() - 7
4480                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4481                                          && GetChar(i + 1) == 'a'
4482                                          && GetChar(i + 2) == 'T'
4483                                          && GetChar(i + 3) == 'e'
4484                                          && GetChar(i + 4) == 'X'
4485                                          && GetChar(i + 5) == '2'
4486                                          && GetChar(i + 6) == 'e') {
4487                                         file += "\\LaTeXe{}";
4488                                         i += 6;
4489                                         column += 8;
4490                                 }
4491                                 // Check for "LaTeX"
4492                                 else if (c == 'L'
4493                                          && i <= size() - 5
4494                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4495                                          && GetChar(i + 1) == 'a'
4496                                          && GetChar(i + 2) == 'T'
4497                                          && GetChar(i + 3) == 'e'
4498                                          && GetChar(i + 4) == 'X') {
4499                                         file += "\\LaTeX{}";
4500                                         i += 4;
4501                                         column += 7;
4502                                         /* idea for labels --- end*/ 
4503                                 } else if (c != '\0') {
4504                                         file += c;
4505                                 }
4506                                 break;
4507                         }
4508                 }
4509         }
4510 }
4511 #endif
4512
4513
4514 #if 0
4515 bool LyXParagraph::RoffContTableRows(ostream & os,
4516                                      LyXParagraph::size_type i,
4517                                      int actcell)
4518 {
4519         if (!table)
4520                 return false;
4521
4522         LyXFont font1(LyXFont::ALL_INHERIT);
4523         LyXFont font2;
4524         Inset * inset;
4525         char c;
4526
4527         string fname2 = TmpFileName(string(), "RAT2");
4528         int lastpos = i;
4529         int cell = table->CellHasContRow(actcell);
4530         ++actcell;
4531         while(cell >= 0) {
4532                 // first find the right position
4533                 i = lastpos;
4534                 for (; i < size() && actcell < cell; ++i) {
4535                         c = GetChar(i);
4536                         if (c == LyXParagraph::META_NEWLINE)
4537                                 ++actcell;
4538                 }
4539                 lastpos = i;
4540                 c = GetChar(i);
4541                 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
4542                         os << " ";
4543                 for (; i < size()
4544                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
4545                      ++i) {
4546                         font2 = GetFontSettings(i);
4547                         if (font1.latex() != font2.latex()) {
4548                                 if (font2.latex() != LyXFont::OFF)
4549                                         continue;
4550                         }
4551                         c = GetChar(i);
4552                         switch (c) {
4553                         case LyXParagraph::META_INSET:
4554                                 if ((inset = GetInset(i))) {
4555 #if 1
4556 #ifdef HAVE_SSTREAM
4557                                         stringstream ss(ios::in | ios::out);
4558                                         inset->Latex(ss, -1);
4559                                         ss.seekp(0);
4560                                         ss.get(c);
4561                                         while (!ss) {
4562                                                 if (c == '\\')
4563                                                         os << "\\\\";
4564                                                 else
4565                                                         os << c;
4566                                                 ss.get(c);
4567                                         }
4568 #else
4569                                         strstream ss;
4570                                         inset->Latex(ss, -1);
4571                                         ss.seekp(0);
4572                                         ss.get(c);
4573                                         while (!ss) {
4574                                                 if (c == '\\')
4575                                                         os << "\\\\";
4576                                                 else
4577                                                         os << c;
4578                                                 ss.get(c);
4579                                         }
4580                                         delete [] ss.str();
4581 #endif
4582 #else
4583                                         fstream fs(fname2.c_str(),
4584                                                    ios::in|ios::out);
4585                                         if (!fs) {
4586                                                 WriteAlert(_("LYX_ERROR:"),
4587                                                            _("Cannot open temporary file:"),
4588                                                            fname2);
4589                                                 return false;
4590                                         }
4591                                         inset->Latex(fs, -1);
4592                                         fs.seekp(0);
4593                                         fs.get(c);
4594                                         while (!fs) {
4595                                                 if (c == '\\')
4596                                                         os << "\\\\";
4597                                                 else
4598                                                         os << c;
4599                                                 fs.get(c);
4600                                         }
4601                                         fs.close();
4602 #endif
4603                                 }
4604                                 break;
4605                         case LyXParagraph::META_NEWLINE:
4606                                 break;
4607                         case LyXParagraph::META_HFILL: 
4608                                 break;
4609 #if 0
4610                         case LyXParagraph::META_PROTECTED_SEPARATOR:
4611                                 break;
4612 #endif
4613                         case '\\': 
4614                                 os << "\\\\";
4615                                 break;
4616                         default:
4617                                 if (c != '\0')
4618                                         os << c;
4619                                 else
4620                                         lyxerr.debug() << "RoffAsciiTable: "
4621                                                 "NULL char in structure."
4622                                                        << endl;
4623                                 break;
4624                         }
4625                 }
4626                 cell = table->CellHasContRow(actcell);
4627         }
4628         return true;
4629 }
4630 #endif
4631
4632
4633 #ifdef USE_OSTREAM_ONLY
4634 LyXParagraph * LyXParagraph::TeXDeeper(ostream & os, TexRow & texrow,
4635                                        ostream & foot, TexRow & foot_texrow,
4636                                        int & foot_count)
4637 {
4638         lyxerr[Debug::LATEX] << "TeXDeeper...     " << this << endl;
4639         LyXParagraph * par = this;
4640
4641         while (par && par->depth == depth) {
4642                 if (par->IsDummy())
4643                         lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
4644                 if (textclasslist.Style(current_view->buffer()->params.textclass, 
4645                                         par->layout).isEnvironment()
4646                     || par->pextra_type != PEXTRA_NONE) {
4647                         par = par->TeXEnvironment(os, texrow,
4648                                                   foot, foot_texrow,
4649                                                   foot_count);
4650                 } else {
4651                         par = par->TeXOnePar(os, texrow,
4652                                              foot, foot_texrow,
4653                                              foot_count);
4654                 }
4655         }
4656         lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
4657
4658         return par;
4659 }
4660 #else
4661 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
4662                                        string & foot, TexRow & foot_texrow,
4663                                        int & foot_count)
4664 {
4665         lyxerr[Debug::LATEX] << "TeXDeeper...     " << this << endl;
4666         LyXParagraph * par = this;
4667
4668         while (par && par->depth == depth) {
4669                 if (par->IsDummy())
4670                         lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
4671                 if (textclasslist.Style(current_view->buffer()->params.textclass, 
4672                                         par->layout).isEnvironment()
4673                     || par->pextra_type != PEXTRA_NONE) 
4674                         {
4675                                 par = par->TeXEnvironment(file, texrow,
4676                                                           foot, foot_texrow,
4677                                                           foot_count);
4678                         } else {
4679                                 par = par->TeXOnePar(file, texrow,
4680                                                      foot, foot_texrow,
4681                                                      foot_count);
4682                         }
4683         }
4684         lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
4685
4686         return par;
4687 }
4688 #endif
4689
4690
4691 #ifdef USE_OSTREAM_ONLY
4692 LyXParagraph * LyXParagraph::TeXEnvironment(ostream & os, TexRow & texrow,
4693                                             ostream & foot,
4694                                             TexRow & foot_texrow,
4695                                             int & foot_count)
4696 {
4697         bool eindent_open = false;
4698         bool foot_this_level = false;
4699         // flags when footnotetext should be appended to file.
4700         static bool minipage_open = false;
4701         static int minipage_open_depth = 0;
4702         char par_sep = current_view->buffer()->params.paragraph_separation;
4703     
4704         lyxerr[Debug::LATEX] << "TeXEnvironment...     " << this << endl;
4705         if (IsDummy())
4706                 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
4707
4708         LyXLayout const & style =
4709                 textclasslist.Style(current_view->buffer()->params.textclass,
4710                                     layout);
4711        
4712         if (pextra_type == PEXTRA_INDENT) {
4713                 if (!pextra_width.empty()) {
4714                         os << "\\begin{LyXParagraphIndent}{"
4715                            << pextra_width << "}\n";
4716                 } else {
4717                         //float ib = atof(pextra_widthp.c_str())/100;
4718                         // string can't handle floats at present (971109)
4719                         // so I'll do a conversion by hand knowing that
4720                         // the limits are 0.0 to 1.0. ARRae.
4721                         os << "\\begin{LyXParagraphIndent}{";
4722                         switch (pextra_widthp.length()) {
4723                         case 3:
4724                                 os << "1.00";
4725                                 break;
4726                         case 2:
4727                                 os << "0."
4728                                    << pextra_widthp;
4729                                 break;
4730                         case 1:
4731                                 os << "0.0"
4732                                    << pextra_widthp;
4733                         }
4734                         os << "\\columnwidth}\n";
4735                 }
4736                 texrow.newline();
4737                 eindent_open = true;
4738         }
4739         if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
4740                 if (pextra_hfill && Previous() &&
4741                     (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
4742                         os << "\\hfill{}\n";
4743                         texrow.newline();
4744                 }
4745                 if (par_sep == BufferParams::PARSEP_INDENT) {
4746                         os << "{\\setlength\\parindent{0pt}\n";
4747                         texrow.newline();
4748                 }
4749                 os << "\\begin{minipage}";
4750                 switch(pextra_alignment) {
4751                 case MINIPAGE_ALIGN_TOP:
4752                         os << "[t]";
4753                         break;
4754                 case MINIPAGE_ALIGN_MIDDLE:
4755                         os << "[m]";
4756                         break;
4757                 case MINIPAGE_ALIGN_BOTTOM:
4758                         os << "[b]";
4759                         break;
4760                 }
4761                 if (!pextra_width.empty()) {
4762                         os << '{' << pextra_width << "}\n";
4763                 } else {
4764                         //float ib = atof(par->pextra_width.c_str())/100;
4765                         // string can't handle floats at present
4766                         // so I'll do a conversion by hand knowing that
4767                         // the limits are 0.0 to 1.0. ARRae.
4768                         os << '{';
4769                         switch (pextra_widthp.length()) {
4770                         case 3:
4771                                 os << "1.00";
4772                                 break;
4773                         case 2:
4774                                 os << "0."
4775                                    << pextra_widthp;
4776                                 break;
4777                         case 1:
4778                                 os << "0.0"
4779                                    << pextra_widthp;
4780                         }
4781                         os << "\\columnwidth}\n";
4782                 }
4783                 texrow.newline();
4784                 if (par_sep == BufferParams::PARSEP_INDENT) {
4785                         os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
4786                         texrow.newline();
4787                 }
4788                 minipage_open = true;
4789                 minipage_open_depth = depth;
4790         }
4791
4792 #ifdef WITH_WARNINGS
4793 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
4794         //I disabled it because it breaks when lists span on several
4795         //pages (JMarc)
4796 #endif
4797         if (style.isEnvironment()){
4798                 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
4799 #ifdef FANCY_FOOTNOTE_CODE
4800                         if (foot_count < 0) {
4801                                 // flag that footnote[mark][text] should be
4802                                 // used for any footnotes from now on
4803                                 foot_count = 0;
4804                                 foot_this_level = true;
4805                         }
4806 #endif
4807                         os << "\\begin{" << style.latexname() << "}{"
4808                            << labelwidthstring << "}\n";
4809                 } else if (style.labeltype == LABEL_BIBLIO) {
4810                         // ale970405
4811                         os << "\\begin{" << style.latexname() << "}{"
4812                            << bibitemWidthest(current_view->painter())
4813                            << "}\n";
4814                 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
4815 #ifdef FANCY_FOOTNOTE_CODE
4816                         if (foot_count < 0) {
4817                                 // flag that footnote[mark][text] should be
4818                                 // used for any footnotes from now on
4819                                 foot_count = 0;
4820                                 foot_this_level = true;
4821                         }
4822 #endif
4823                         os << "\\begin{" << style.latexname() << '}'
4824                            << style.latexparam() << '\n';
4825                 } else 
4826                         os << "\\begin{" << style.latexname() << '}'
4827                            << style.latexparam() << '\n';
4828                 texrow.newline();
4829         }
4830         LyXParagraph * par = this;
4831         do {
4832                 par = par->TeXOnePar(os, texrow,
4833                                      foot, foot_texrow, foot_count);
4834
4835                 if (minipage_open && par && !style.isEnvironment() &&
4836                     (par->pextra_type == PEXTRA_MINIPAGE) &&
4837                     par->pextra_start_minipage) {
4838                         os << "\\end{minipage}\n";
4839                         texrow.newline();
4840                         if (par_sep == BufferParams::PARSEP_INDENT) {
4841                                 os << "}\n";
4842                                 texrow.newline();
4843                         }
4844                         minipage_open = false;
4845                 }
4846                 if (par && par->depth > depth) {
4847                         if (textclasslist.Style(current_view->buffer()->params.textclass,
4848                                                 par->layout).isParagraph()
4849                             && !par->table
4850                             // Thinko!
4851                             // How to handle this? (Lgb)
4852                             //&& !suffixIs(os, "\n\n")
4853                                 ) {
4854                                 // There should be at least one '\n' already
4855                                 // but we need there to be two for Standard 
4856                                 // paragraphs that are depth-increment'ed to be
4857                                 // output correctly.  However, tables can
4858                                 // also be paragraphs so don't adjust them.
4859                                 // ARRae
4860                                 // Thinkee:
4861                                 // Will it ever harm to have one '\n' too
4862                                 // many? i.e. that we sometimes will have
4863                                 // three in a row. (Lgb)
4864                                 os << '\n';
4865                                 texrow.newline();
4866                         }
4867                         par = par->TeXDeeper(os, texrow,
4868                                              foot, foot_texrow, foot_count);
4869                 }
4870                 if (par && par->layout == layout && par->depth == depth &&
4871                     (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
4872                         if (par->pextra_hfill && par->Previous() &&
4873                             (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
4874                                 os << "\\hfill{}\n";
4875                                 texrow.newline();
4876                         }
4877                         if (par_sep == BufferParams::PARSEP_INDENT) {
4878                                 os << "{\\setlength\\parindent{0pt}\n";
4879                                 texrow.newline();
4880                         }
4881                         os << "\\begin{minipage}";
4882                         switch(par->pextra_alignment) {
4883                         case MINIPAGE_ALIGN_TOP:
4884                                 os << "[t]";
4885                                 break;
4886                         case MINIPAGE_ALIGN_MIDDLE:
4887                                 os << "[m]";
4888                                 break;
4889                         case MINIPAGE_ALIGN_BOTTOM:
4890                                 os << "[b]";
4891                                 break;
4892                         }
4893                         if (!par->pextra_width.empty()) {
4894                                 os << '{' << par->pextra_width << "}\n";
4895                         } else {
4896                                 //float ib = atof(par->pextra_widthp.c_str())/100;
4897                                 // string can't handle floats at present
4898                                 // so I'll do a conversion by hand knowing that
4899                                 // the limits are 0.0 to 1.0. ARRae.
4900                                 os << '{';
4901                                 switch (par->pextra_widthp.length()) {
4902                                 case 3:
4903                                         os << "1.00";
4904                                         break;
4905                                 case 2:
4906                                         os << "0." << par->pextra_widthp;
4907                                         break;
4908                                 case 1:
4909                                         os << "0.0" << par->pextra_widthp;
4910                                 }
4911                                 os << "\\columnwidth}\n";
4912                         }
4913                         texrow.newline();
4914                         if (par_sep == BufferParams::PARSEP_INDENT) {
4915                                 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
4916                                 texrow.newline();
4917                         }
4918                         minipage_open = true;
4919                         minipage_open_depth = par->depth;
4920                 }
4921         } while (par
4922                  && par->layout == layout
4923                  && par->depth == depth
4924                  && par->pextra_type == pextra_type);
4925  
4926         if (style.isEnvironment()) {
4927                 os << "\\end{" << style.latexname() << '}';
4928                 // maybe this should go after the minipage closes?
4929                 if (foot_this_level) {
4930                         if (foot_count >= 1) {
4931                                 if (foot_count > 1) {
4932                                         os << "\\addtocounter{footnote}{-"
4933                                            << foot_count - 1
4934                                            << '}';
4935                                 }
4936                                 os << foot;
4937                                 texrow += foot_texrow;
4938                                 foot.clear();
4939                                 foot_texrow.reset();
4940                                 foot_count = 0;
4941                         }
4942                 }
4943         }
4944         if (minipage_open && (minipage_open_depth == depth) &&
4945             (!par || par->pextra_start_minipage ||
4946              par->pextra_type != PEXTRA_MINIPAGE)) {
4947                 os << "\\end{minipage}\n";
4948                 texrow.newline();
4949                 if (par_sep == BufferParams::PARSEP_INDENT) {
4950                         os << "}\n";
4951                         texrow.newline();
4952                 }
4953                 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
4954                         os << "\\medskip\n\n";
4955                         texrow.newline();
4956                         texrow.newline();
4957                 }
4958                 minipage_open = false;
4959         }
4960         if (eindent_open) {
4961                 os << "\\end{LyXParagraphIndent}\n";
4962                 texrow.newline();
4963         }
4964         if (!(par && (par->pextra_type == PEXTRA_MINIPAGE) 
4965               && par->pextra_hfill)) {
4966                 os << '\n';
4967                 texrow.newline();
4968         }
4969         lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
4970         return par;  // ale970302
4971 }
4972 #else
4973 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
4974                                             string & foot,
4975                                             TexRow & foot_texrow,
4976                                             int & foot_count)
4977 {
4978         bool eindent_open = false;
4979         bool foot_this_level = false;
4980         // flags when footnotetext should be appended to file.
4981         static bool minipage_open = false;
4982         static int minipage_open_depth = 0;
4983         char par_sep = current_view->buffer()->params.paragraph_separation;
4984     
4985         lyxerr[Debug::LATEX] << "TeXEnvironment...     " << this << endl;
4986         if (IsDummy())
4987                 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
4988
4989         LyXLayout const & style =
4990                 textclasslist.Style(current_view->buffer()->params.textclass,
4991                                     layout);
4992        
4993         if (pextra_type == PEXTRA_INDENT) {
4994                 if (!pextra_width.empty()) {
4995                         file += "\\begin{LyXParagraphIndent}{"
4996                                 + pextra_width + "}\n";
4997                 } else {
4998                         //float ib = atof(pextra_widthp.c_str())/100;
4999                         // string can't handle floats at present (971109)
5000                         // so I'll do a conversion by hand knowing that
5001                         // the limits are 0.0 to 1.0. ARRae.
5002                         file += "\\begin{LyXParagraphIndent}{";
5003                         switch (pextra_widthp.length()) {
5004                         case 3:
5005                                 file += "1.00";
5006                                 break;
5007                         case 2:
5008                                 file += "0.";
5009                                 file += pextra_widthp;
5010                                 break;
5011                         case 1:
5012                                 file += "0.0";
5013                                 file += pextra_widthp;
5014                         }
5015                         file += "\\columnwidth}\n";
5016                 }
5017                 texrow.newline();
5018                 eindent_open = true;
5019         }
5020         if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
5021                 if (pextra_hfill && Previous() &&
5022                     (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
5023                         file += "\\hfill{}\n";
5024                         texrow.newline();
5025                 }
5026                 if (par_sep == BufferParams::PARSEP_INDENT) {
5027                         file += "{\\setlength\\parindent{0pt}\n";
5028                         texrow.newline();
5029                 }
5030                 file += "\\begin{minipage}";
5031                 switch(pextra_alignment) {
5032                 case MINIPAGE_ALIGN_TOP:
5033                         file += "[t]";
5034                         break;
5035                 case MINIPAGE_ALIGN_MIDDLE:
5036                         file += "[m]";
5037                         break;
5038                 case MINIPAGE_ALIGN_BOTTOM:
5039                         file += "[b]";
5040                         break;
5041                 }
5042                 if (!pextra_width.empty()) {
5043                         file += '{';
5044                         file += pextra_width + "}\n";
5045                 } else {
5046                         //float ib = atof(par->pextra_width.c_str())/100;
5047                         // string can't handle floats at present
5048                         // so I'll do a conversion by hand knowing that
5049                         // the limits are 0.0 to 1.0. ARRae.
5050                         file += '{';
5051                         switch (pextra_widthp.length()) {
5052                         case 3:
5053                                 file += "1.00";
5054                                 break;
5055                         case 2:
5056                                 file += "0.";
5057                                 file += pextra_widthp;
5058                                 break;
5059                         case 1:
5060                                 file += "0.0";
5061                                 file += pextra_widthp;
5062                         }
5063                         file += "\\columnwidth}\n";
5064                 }
5065                 texrow.newline();
5066                 if (par_sep == BufferParams::PARSEP_INDENT) {
5067                         file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
5068                         texrow.newline();
5069                 }
5070                 minipage_open = true;
5071                 minipage_open_depth = depth;
5072         }
5073
5074 #ifdef WITH_WARNINGS
5075 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
5076         //I disabled it because it breaks when lists span on several
5077         //pages (JMarc)
5078 #endif
5079         if (style.isEnvironment()){
5080                 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
5081 #ifdef FANCY_FOOTNOTE_CODE
5082                         if (foot_count < 0) {
5083                                 // flag that footnote[mark][text] should be
5084                                 // used for any footnotes from now on
5085                                 foot_count = 0;
5086                                 foot_this_level = true;
5087                         }
5088 #endif
5089                         file += "\\begin{" + style.latexname() + "}{"
5090                                 + labelwidthstring + "}\n";
5091                 } else if (style.labeltype == LABEL_BIBLIO) {
5092                         // ale970405
5093                         file += "\\begin{" + style.latexname() + "}{"
5094                                 + bibitemWidthest(current_view->painter())
5095                                 + "}\n";
5096                 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
5097 #ifdef FANCY_FOOTNOTE_CODE
5098                         if (foot_count < 0) {
5099                                 // flag that footnote[mark][text] should be
5100                                 // used for any footnotes from now on
5101                                 foot_count = 0;
5102                                 foot_this_level = true;
5103                         }
5104 #endif
5105                         file += "\\begin{" + style.latexname() + '}'
5106                                 + style.latexparam() + '\n';
5107                 } else 
5108                         file += "\\begin{" + style.latexname() + '}'
5109                                 + style.latexparam() + '\n';
5110                 texrow.newline();
5111         }
5112         LyXParagraph * par = this;
5113         do {
5114                 par = par->TeXOnePar(file, texrow,
5115                                      foot, foot_texrow, foot_count);
5116
5117                 if (minipage_open && par && !style.isEnvironment() &&
5118                     (par->pextra_type == PEXTRA_MINIPAGE) &&
5119                     par->pextra_start_minipage) {
5120                         file += "\\end{minipage}\n";
5121                         texrow.newline();
5122                         if (par_sep == BufferParams::PARSEP_INDENT) {
5123                                 file += "}\n";
5124                                 texrow.newline();
5125                         }
5126                         minipage_open = false;
5127                 }
5128                 if (par && par->depth > depth) {
5129                         if (textclasslist.Style(current_view->buffer()->params.textclass,
5130                                                 par->layout).isParagraph()
5131                             && !par->table
5132                             && !suffixIs(file, "\n\n")) {
5133                                 // There should be at least one '\n' already
5134                                 // but we need there to be two for Standard 
5135                                 // paragraphs that are depth-increment'ed to be
5136                                 // output correctly.  However, tables can
5137                                 // also be paragraphs so don't adjust them.
5138                                 // ARRae
5139                                 file += '\n';
5140                                 texrow.newline();
5141                         }
5142                         par = par->TeXDeeper(file, texrow,
5143                                              foot, foot_texrow, foot_count);
5144                 }
5145                 if (par && par->layout == layout && par->depth == depth &&
5146                     (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
5147                         if (par->pextra_hfill && par->Previous() &&
5148                             (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
5149                                 file += "\\hfill{}\n";
5150                                 texrow.newline();
5151                         }
5152                         if (par_sep == BufferParams::PARSEP_INDENT) {
5153                                 file += "{\\setlength\\parindent{0pt}\n";
5154                                 texrow.newline();
5155                         }
5156                         file += "\\begin{minipage}";
5157                         switch(par->pextra_alignment) {
5158                         case MINIPAGE_ALIGN_TOP:
5159                                 file += "[t]";
5160                                 break;
5161                         case MINIPAGE_ALIGN_MIDDLE:
5162                                 file += "[m]";
5163                                 break;
5164                         case MINIPAGE_ALIGN_BOTTOM:
5165                                 file += "[b]";
5166                                 break;
5167                         }
5168                         if (!par->pextra_width.empty()) {
5169                                 file += '{';
5170                                 file += par->pextra_width;
5171                                 file += "}\n";
5172                         } else {
5173                                 //float ib = atof(par->pextra_widthp.c_str())/100;
5174                                 // string can't handle floats at present
5175                                 // so I'll do a conversion by hand knowing that
5176                                 // the limits are 0.0 to 1.0. ARRae.
5177                                 file += '{';
5178                                 switch (par->pextra_widthp.length()) {
5179                                 case 3:
5180                                         file += "1.00";
5181                                         break;
5182                                 case 2:
5183                                         file += "0.";
5184                                         file += par->pextra_widthp;
5185                                         break;
5186                                 case 1:
5187                                         file += "0.0";
5188                                         file += par->pextra_widthp;
5189                                 }
5190                                 file += "\\columnwidth}\n";
5191                         }
5192                         texrow.newline();
5193                         if (par_sep == BufferParams::PARSEP_INDENT) {
5194                                 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
5195                                 texrow.newline();
5196                         }
5197                         minipage_open = true;
5198                         minipage_open_depth = par->depth;
5199                 }
5200         } while (par
5201                  && par->layout == layout
5202                  && par->depth == depth
5203                  && par->pextra_type == pextra_type);
5204  
5205         if (style.isEnvironment()) {
5206                 file += "\\end{" + style.latexname() + '}';
5207                 // maybe this should go after the minipage closes?
5208                 if (foot_this_level) {
5209                         if (foot_count >= 1) {
5210                                 if (foot_count > 1) {
5211                                         file += "\\addtocounter{footnote}{-";
5212                                         file += tostr(foot_count - 1);
5213                                         file += '}';
5214                                 }
5215                                 file += foot;
5216                                 texrow += foot_texrow;
5217                                 foot.clear();
5218                                 foot_texrow.reset();
5219                                 foot_count = 0;
5220                         }
5221                 }
5222         }
5223         if (minipage_open && (minipage_open_depth == depth) &&
5224             (!par || par->pextra_start_minipage ||
5225              par->pextra_type != PEXTRA_MINIPAGE)) {
5226                 file += "\\end{minipage}\n";
5227                 texrow.newline();
5228                 if (par_sep == BufferParams::PARSEP_INDENT) {
5229                         file += "}\n";
5230                         texrow.newline();
5231                 }
5232                 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
5233                         file += "\\medskip\n\n";
5234                         texrow.newline();
5235                         texrow.newline();
5236                 }
5237                 minipage_open = false;
5238         }
5239         if (eindent_open) {
5240                 file += "\\end{LyXParagraphIndent}\n";
5241                 texrow.newline();
5242         }
5243         if (!(par && (par->pextra_type == PEXTRA_MINIPAGE) 
5244               && par->pextra_hfill)) {
5245                 file += '\n';
5246                 texrow.newline();
5247         }
5248         lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
5249         return par;  // ale970302
5250 }
5251 #endif
5252
5253
5254 #ifdef USE_OSTREAM_ONLY
5255 LyXParagraph * LyXParagraph::TeXFootnote(ostream & os, TexRow & texrow,
5256                                          ostream & foot, TexRow & foot_texrow,
5257                                          int & foot_count,
5258                                          LyXDirection par_direction)
5259 {
5260         lyxerr[Debug::LATEX] << "TeXFootnote...  " << this << endl;
5261         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
5262                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5263                         "No footnote!" << endl;
5264
5265         LyXParagraph * par = this;
5266         LyXLayout const & style =
5267                 textclasslist.Style(current_view->buffer()->params.textclass, 
5268                                     previous->GetLayout());
5269         
5270         if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
5271                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5272                         "Float other than footnote in command"
5273                         " with moving argument is illegal" << endl;
5274         }
5275
5276         if (footnotekind != LyXParagraph::FOOTNOTE
5277             && footnotekind != LyXParagraph::MARGIN
5278             && os.tellp()
5279             // Thinko
5280             // How to solve this?
5281             //&& !suffixIs(file, '\n')
5282                 ) {
5283                 // we need to ensure that real floats like tables and figures
5284                 // have their \begin{} on a new line otherwise we can get
5285                 // incorrect results when using the endfloat.sty package
5286                 // especially if two floats follow one another.  ARRae 981022
5287                 // NOTE: if the file is length 0 it must have just been
5288                 //       written out so we assume it ended with a '\n'
5289                 // Thinkee:
5290                 // As far as I can see there is never any harm in writing
5291                 // a '\n' too much. Please tell me if I am wrong. (Lgb)
5292                 os << '\n';
5293                 texrow.newline();
5294         }
5295         
5296         BufferParams * params = &current_view->buffer()->params;
5297         bool footer_in_body = true;
5298         switch (footnotekind) {
5299         case LyXParagraph::FOOTNOTE:
5300                 if (style.intitle) {
5301                         os << "\\thanks{\n";
5302                         footer_in_body = false;
5303                 } else {
5304                         if (foot_count == -1) {
5305                                 // we're at depth 0 so we can use:
5306                                 os << "\\footnote{%\n";
5307                                 footer_in_body = false;
5308                         } else {
5309                                 os << "\\footnotemark{}%\n";
5310                                 if (foot_count) {
5311                                         // we only need this when there are
5312                                         // multiple footnotes
5313                                         os << "\\stepcounter{footnote}";
5314                                 }
5315                                 os << "\\footnotetext{%\n";
5316                                 foot_texrow.start(this, 0);
5317                                 foot_texrow.newline();
5318                                 ++foot_count;
5319                         }
5320                 }
5321                 break;
5322         case LyXParagraph::MARGIN:
5323                 os << "\\marginpar{\n";
5324                 break;
5325         case LyXParagraph::FIG:
5326                 if (pextra_type == PEXTRA_FLOATFLT
5327                     && (!pextra_width.empty()
5328                         || !pextra_widthp.empty())) {
5329                         if (!pextra_width.empty())
5330                                 os << "\\begin{floatingfigure}{"
5331                                    << pextra_width << "}\n";
5332                         else
5333                                 os << "\\begin{floatingfigure}{"
5334                                    << atoi(pextra_widthp.c_str())/100.0
5335                                    << "\\textwidth}\n";
5336                 } else {
5337                         os << "\\begin{figure}";
5338                         if (!params->float_placement.empty()) { 
5339                                 os << '[' << params->float_placement << "]\n";
5340                         } else {
5341                                 os << '\n';
5342                         }
5343                 }
5344                 break;
5345         case LyXParagraph::TAB:
5346                 os << "\\begin{table}";
5347                 if (!params->float_placement.empty()) { 
5348                         os << '[' << params->float_placement << "]\n";
5349                 } else {
5350                         os << '\n';
5351                 }
5352                 break;
5353         case LyXParagraph::WIDE_FIG:
5354                 os << "\\begin{figure*}";
5355                 if (!params->float_placement.empty()) { 
5356                         os << '[' << params->float_placement << "]\n";
5357                 } else {
5358                         os << '\n';
5359                 }
5360                 break;
5361         case LyXParagraph::WIDE_TAB:
5362                 os << "\\begin{table*}";
5363                 if (!params->float_placement.empty()) { 
5364                         os << '[' << params->float_placement << "]\n";
5365                 } else {
5366                         os << '\n';
5367                 }
5368                 break;
5369         case LyXParagraph::ALGORITHM:
5370                 os << "\\begin{algorithm}\n";
5371                 break;
5372         }
5373         texrow.newline();
5374    
5375  
5376         LyXDirection direction = getParDirection();
5377         if (direction != par_direction) {
5378                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
5379                         os << "\\unsethebrew\n";
5380                 else
5381                         os << "\\sethebrew\n";
5382                 texrow.newline();
5383         }
5384
5385         if (footnotekind != LyXParagraph::FOOTNOTE
5386             || !footer_in_body) {
5387                 // Process text for all floats except footnotes in body
5388                 do {
5389                         LyXLayout const & style =
5390                                 textclasslist
5391                                 .Style(current_view->buffer()->params
5392                                        .textclass,
5393                                        par->layout);
5394                         if (par->IsDummy())
5395                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5396                                        << endl;
5397                         if (style.isEnvironment()
5398                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5399                                 // Allows the use of minipages within float
5400                                 // environments. Shouldn't be circular because
5401                                 // we don't support footnotes inside
5402                                 // floats (yet). ARRae
5403                                 par = par->TeXEnvironment(os, texrow,
5404                                                           foot, foot_texrow,
5405                                                           foot_count);
5406                         } else {
5407                                 par = par->TeXOnePar(os, texrow,
5408                                                      foot, foot_texrow,
5409                                                      foot_count);
5410                         }
5411                         
5412                         if (par && !par->IsDummy() && par->depth > depth) {
5413                                 par = par->TeXDeeper(os, texrow,
5414                                                      foot, foot_texrow,
5415                                                      foot_count);
5416                         }
5417                 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5418         } else {
5419                 // process footnotes > depth 0 or in environments separately
5420                 // NOTE: Currently don't support footnotes within footnotes
5421                 //       even though that is possible using the \footnotemark
5422 #ifdef HAVE_SSTREAM
5423                 ostringstream dummy;
5424 #else
5425                 ostrstream dummy;
5426 #endif
5427                 TexRow dummy_texrow;
5428                 int dummy_count = 0;
5429                 do {
5430                         LyXLayout const & style =
5431                                 textclasslist
5432                                 .Style(current_view->buffer()->params
5433                                        .textclass,
5434                                        par->layout);
5435                         if (par->IsDummy())
5436                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5437                                        << endl;
5438                         if (style.isEnvironment()
5439                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5440                                 // Allows the use of minipages within float
5441                                 // environments. Shouldn't be circular because
5442                                 // we don't support footnotes inside
5443                                 // floats (yet). ARRae
5444                                 par = par->TeXEnvironment(foot, foot_texrow,
5445                                                           dummy, dummy_texrow,
5446                                                           dummy_count);
5447                         } else {
5448                                 par = par->TeXOnePar(foot, foot_texrow,
5449                                                      dummy, dummy_texrow,
5450                                                      dummy_count);
5451                         }
5452
5453                         if (par && !par->IsDummy() && par->depth > depth) {
5454                                 par = par->TeXDeeper(foot, foot_texrow,
5455                                                      dummy, dummy_texrow,
5456                                                      dummy_count);
5457                         }
5458                 } while (par
5459                          && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5460                 if (dummy_count) {
5461                         lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5462                                 "Footnote in a Footnote -- not supported"
5463                                << endl;
5464                 }
5465 #ifndef HAVE_OSTREAM
5466                 delete [] dummy.str();
5467 #endif
5468         }
5469
5470         switch (footnotekind) {
5471         case LyXParagraph::FOOTNOTE:
5472                 if (footer_in_body) {
5473                         // This helps tell which of the multiple
5474                         // footnotetexts an error was in.
5475                         foot << "}%\n";
5476                         foot_texrow.newline();
5477                 } else {
5478                         os << '}';
5479                 }
5480                 break;
5481         case LyXParagraph::MARGIN:
5482                 os << '}';
5483                 break;
5484         case LyXParagraph::FIG:
5485                 if (pextra_type == PEXTRA_FLOATFLT
5486                     && (!pextra_width.empty()
5487                         || !pextra_widthp.empty()))
5488                         os << "\\end{floatingfigure}";
5489                 else
5490                         os << "\\end{figure}";
5491                 break;
5492         case LyXParagraph::TAB:
5493                 os << "\\end{table}";
5494                 break;
5495         case LyXParagraph::WIDE_FIG:
5496                 os << "\\end{figure*}";
5497                 break;
5498         case LyXParagraph::WIDE_TAB:
5499                 os << "\\end{table*}";
5500                 break;
5501         case LyXParagraph::ALGORITHM:
5502                 os << "\\end{algorithm}";
5503                 break;
5504         }
5505
5506         if (footnotekind != LyXParagraph::FOOTNOTE
5507             && footnotekind != LyXParagraph::MARGIN) {
5508                 // we need to ensure that real floats like tables and figures
5509                 // have their \end{} on a line of their own otherwise we can
5510                 // get incorrect results when using the endfloat.sty package.
5511                 os << "\n";
5512                 texrow.newline();
5513         }
5514
5515         lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
5516         return par;
5517 }
5518 #else
5519 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
5520                                          string & foot, TexRow & foot_texrow,
5521                                          int & foot_count,
5522                                          LyXDirection par_direction)
5523 {
5524         lyxerr[Debug::LATEX] << "TeXFootnote...  " << this << endl;
5525         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
5526                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5527                         "No footnote!" << endl;
5528
5529         LyXParagraph * par = this;
5530         LyXLayout const & style =
5531                 textclasslist.Style(current_view->buffer()->params.textclass, 
5532                                     previous->GetLayout());
5533         
5534         if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
5535                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5536                         "Float other than footnote in command"
5537                         " with moving argument is illegal" << endl;
5538         }
5539
5540         if (footnotekind != LyXParagraph::FOOTNOTE
5541             && footnotekind != LyXParagraph::MARGIN
5542             && file.length()
5543             && !suffixIs(file, '\n')) {
5544                 // we need to ensure that real floats like tables and figures
5545                 // have their \begin{} on a new line otherwise we can get
5546                 // incorrect results when using the endfloat.sty package
5547                 // especially if two floats follow one another.  ARRae 981022
5548                 // NOTE: if the file is length 0 it must have just been
5549                 //       written out so we assume it ended with a '\n'
5550                 file += '\n';
5551                 texrow.newline();
5552         }
5553         
5554         BufferParams * params = &current_view->buffer()->params;
5555         bool footer_in_body = true;
5556         switch (footnotekind) {
5557         case LyXParagraph::FOOTNOTE:
5558                 if (style.intitle) {
5559                         file += "\\thanks{\n";
5560                         footer_in_body = false;
5561                 } else {
5562                         if (foot_count == -1) {
5563                                 // we're at depth 0 so we can use:
5564                                 file += "\\footnote{%\n";
5565                                 footer_in_body = false;
5566                         } else {
5567                                 file += "\\footnotemark{}%\n";
5568                                 if (foot_count) {
5569                                         // we only need this when there are
5570                                         // multiple footnotes
5571                                         foot += "\\stepcounter{footnote}";
5572                                 }
5573                                 foot += "\\footnotetext{%\n";
5574                                 foot_texrow.start(this, 0);
5575                                 foot_texrow.newline();
5576                                 ++foot_count;
5577                         }
5578                 }
5579                 break;
5580         case LyXParagraph::MARGIN:
5581                 file += "\\marginpar{\n";
5582                 break;
5583         case LyXParagraph::FIG:
5584                 if (pextra_type == PEXTRA_FLOATFLT
5585                     && (!pextra_width.empty()
5586                         || !pextra_widthp.empty())) {
5587                         char bufr[80];
5588                         if (!pextra_width.empty())
5589                                 sprintf(bufr,
5590                                         "\\begin{floatingfigure}{%s}\n",
5591                                         pextra_width.c_str());
5592                         else
5593                                 sprintf(bufr,
5594                                         "\\begin{floatingfigure}{%f\\textwidth}\n",
5595                                         atoi(pextra_widthp.c_str())/100.0);
5596                         file += bufr;
5597                 } else {
5598                         file += "\\begin{figure}";
5599                         if (!params->float_placement.empty()) { 
5600                                 file += '[';
5601                                 file += params->float_placement;
5602                                 file += "]\n";
5603                         } else {
5604                                 file += '\n';
5605                         }
5606                 }
5607                 break;
5608         case LyXParagraph::TAB:
5609                 file += "\\begin{table}";
5610                 if (!params->float_placement.empty()) { 
5611                         file += '[';
5612                         file += params->float_placement;
5613                         file += "]\n";
5614                 } else {
5615                         file += '\n';
5616                 }
5617                 break;
5618         case LyXParagraph::WIDE_FIG:
5619                 file += "\\begin{figure*}";
5620                 if (!params->float_placement.empty()) { 
5621                         file += '[';
5622                         file += params->float_placement;
5623                         file += "]\n";
5624                 } else {
5625                         file += '\n';
5626                 }
5627                 break;
5628         case LyXParagraph::WIDE_TAB:
5629                 file += "\\begin{table*}";
5630                 if (!params->float_placement.empty()) { 
5631                         file += '[';
5632                         file += params->float_placement;
5633                         file += "]\n";
5634                 } else {
5635                         file += '\n';
5636                 }
5637                 break;
5638         case LyXParagraph::ALGORITHM:
5639                 file += "\\begin{algorithm}\n";
5640                 break;
5641         }
5642         texrow.newline();
5643    
5644  
5645         LyXDirection direction = getParDirection();
5646         if (direction != par_direction) {
5647                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
5648                         file += "\\unsethebrew\n";
5649                 else
5650                         file += "\\sethebrew\n";
5651                 texrow.newline();
5652         }
5653
5654         if (footnotekind != LyXParagraph::FOOTNOTE
5655             || !footer_in_body) {
5656                 // Process text for all floats except footnotes in body
5657                 do {
5658                         LyXLayout const & style =
5659                                 textclasslist
5660                                 .Style(current_view->buffer()->params
5661                                        .textclass,
5662                                        par->layout);
5663                         if (par->IsDummy())
5664                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5665                                        << endl;
5666                         if (style.isEnvironment()
5667                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5668                                 // Allows the use of minipages within float
5669                                 // environments. Shouldn't be circular because
5670                                 // we don't support footnotes inside
5671                                 // floats (yet). ARRae
5672                                 par = par->TeXEnvironment(file, texrow,
5673                                                           foot, foot_texrow,
5674                                                           foot_count);
5675                         } else {
5676                                 par = par->TeXOnePar(file, texrow,
5677                                                      foot, foot_texrow,
5678                                                      foot_count);
5679                         }
5680                         
5681                         if (par && !par->IsDummy() && par->depth > depth) {
5682                                 par = par->TeXDeeper(file, texrow,
5683                                                      foot, foot_texrow,
5684                                                      foot_count);
5685                         }
5686                 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5687         } else {
5688                 // process footnotes > depth 0 or in environments separately
5689                 // NOTE: Currently don't support footnotes within footnotes
5690                 //       even though that is possible using the \footnotemark
5691                 string dummy;
5692                 TexRow dummy_texrow;
5693                 int dummy_count = 0;
5694                 do {
5695                         LyXLayout const & style =
5696                                 textclasslist
5697                                 .Style(current_view->buffer()->params
5698                                        .textclass,
5699                                        par->layout);
5700                         if (par->IsDummy())
5701                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5702                                        << endl;
5703                         if (style.isEnvironment()
5704                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5705                                 // Allows the use of minipages within float
5706                                 // environments. Shouldn't be circular because
5707                                 // we don't support footnotes inside
5708                                 // floats (yet). ARRae
5709                                 par = par->TeXEnvironment(foot, foot_texrow,
5710                                                           dummy, dummy_texrow,
5711                                                           dummy_count);
5712                         } else {
5713                                 par = par->TeXOnePar(foot, foot_texrow,
5714                                                      dummy, dummy_texrow,
5715                                                      dummy_count);
5716                         }
5717
5718                         if (par && !par->IsDummy() && par->depth > depth) {
5719                                 par = par->TeXDeeper(foot, foot_texrow,
5720                                                      dummy, dummy_texrow,
5721                                                      dummy_count);
5722                         }
5723                 } while (par
5724                          && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5725                 if (dummy_count) {
5726                         lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5727                                 "Footnote in a Footnote -- not supported"
5728                                << endl;
5729                 }
5730         }
5731
5732         switch (footnotekind) {
5733         case LyXParagraph::FOOTNOTE:
5734                 if (footer_in_body) {
5735                         // This helps tell which of the multiple
5736                         // footnotetexts an error was in.
5737                         foot += "}%\n";
5738                         foot_texrow.newline();
5739                 } else {
5740                         file += '}';
5741                 }
5742                 break;
5743         case LyXParagraph::MARGIN:
5744                 file += '}';
5745                 break;
5746         case LyXParagraph::FIG:
5747                 if (pextra_type == PEXTRA_FLOATFLT
5748                     && (!pextra_width.empty()
5749                         || !pextra_widthp.empty()))
5750                         file += "\\end{floatingfigure}";
5751                 else
5752                         file += "\\end{figure}";
5753                 break;
5754         case LyXParagraph::TAB:
5755                 file += "\\end{table}";
5756                 break;
5757         case LyXParagraph::WIDE_FIG:
5758                 file += "\\end{figure*}";
5759                 break;
5760         case LyXParagraph::WIDE_TAB:
5761                 file += "\\end{table*}";
5762                 break;
5763         case LyXParagraph::ALGORITHM:
5764                 file += "\\end{algorithm}";
5765                 break;
5766         }
5767
5768         if (footnotekind != LyXParagraph::FOOTNOTE
5769             && footnotekind != LyXParagraph::MARGIN) {
5770                 // we need to ensure that real floats like tables and figures
5771                 // have their \end{} on a line of their own otherwise we can
5772                 // get incorrect results when using the endfloat.sty package.
5773                 file += "\n";
5774                 texrow.newline();
5775         }
5776
5777         lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
5778         return par;
5779 }
5780 #endif
5781
5782
5783 void LyXParagraph::SetPExtraType(int type, char const * width,
5784                                  char const * widthp)
5785 {
5786         pextra_type = type;
5787         pextra_width = width;
5788         pextra_widthp = widthp;
5789
5790         if (textclasslist.Style(current_view->buffer()->params.textclass, 
5791                                 layout).isEnvironment()) {
5792                 LyXParagraph
5793                         * par = this,
5794                         * ppar = par;
5795
5796                 while (par && (par->layout == layout)
5797                        && (par->depth == depth)) {
5798                         ppar = par;
5799                         par = par->Previous();
5800                         if (par)
5801                                 par = par->FirstPhysicalPar();
5802                         while (par && par->depth > depth) {
5803                                 par = par->Previous();
5804                                 if (par)
5805                                         par = par->FirstPhysicalPar();
5806                         }
5807                 }
5808                 par = ppar;
5809                 while (par && (par->layout == layout)
5810                        && (par->depth == depth)) {
5811                         par->pextra_type = type;
5812                         par->pextra_width = width;
5813                         par->pextra_widthp = widthp;
5814                         par = par->NextAfterFootnote();
5815                         if (par && (par->depth > depth))
5816                                 par->SetPExtraType(type, width, widthp);
5817                         while (par && ((par->depth > depth) || par->IsDummy()))
5818                                 par = par->NextAfterFootnote();
5819                 }
5820         }
5821 }
5822
5823
5824 void LyXParagraph::UnsetPExtraType()
5825 {
5826         if (pextra_type == PEXTRA_NONE)
5827                 return;
5828     
5829         pextra_type = PEXTRA_NONE;
5830         pextra_width.clear();
5831         pextra_widthp.clear();
5832
5833         if (textclasslist.Style(current_view->buffer()->params.textclass, 
5834                                 layout).isEnvironment()) {
5835                 LyXParagraph
5836                         * par = this,
5837                         * ppar = par;
5838
5839                 while (par && (par->layout == layout)
5840                        && (par->depth == depth)) {
5841                         ppar = par;
5842                         par = par->Previous();
5843                         if (par)
5844                                 par = par->FirstPhysicalPar();
5845                         while (par && par->depth > depth) {
5846                                 par = par->Previous();
5847                                 if (par)
5848                                         par = par->FirstPhysicalPar();
5849                         }
5850                 }
5851                 par = ppar;
5852                 while (par && (par->layout == layout)
5853                        && (par->depth == depth)) {
5854                         par->pextra_type = PEXTRA_NONE;
5855                         par->pextra_width.clear();
5856                         par->pextra_widthp.clear();
5857                         par = par->NextAfterFootnote();
5858                         if (par && (par->depth > depth))
5859                                 par->UnsetPExtraType();
5860                         while (par && ((par->depth > depth) || par->IsDummy()))
5861                                 par = par->NextAfterFootnote();
5862                 }
5863         }
5864 }
5865
5866
5867 bool LyXParagraph::IsHfill(size_type pos) const
5868 {
5869         return IsHfillChar(GetChar(pos));
5870 }
5871
5872
5873 bool LyXParagraph::IsInset(size_type pos) const
5874 {
5875         return IsInsetChar(GetChar(pos));
5876 }
5877
5878
5879 bool LyXParagraph::IsFloat(size_type pos) const
5880 {
5881         return IsFloatChar(GetChar(pos));
5882 }
5883
5884
5885 bool LyXParagraph::IsNewline(size_type pos) const
5886 {
5887         bool tmp = false;
5888         if (pos >= 0)
5889                 tmp = IsNewlineChar(GetChar(pos));
5890         return tmp;
5891 }
5892
5893
5894 bool LyXParagraph::IsSeparator(size_type pos) const
5895 {
5896         return IsSeparatorChar(GetChar(pos));
5897 }
5898
5899
5900 bool LyXParagraph::IsLineSeparator(size_type pos) const
5901 {
5902         return IsLineSeparatorChar(GetChar(pos));
5903 }
5904
5905
5906 bool LyXParagraph::IsKomma(size_type pos) const
5907 {
5908         return IsKommaChar(GetChar(pos));
5909 }
5910
5911
5912 /// Used by the spellchecker
5913 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
5914 {
5915         unsigned char c = GetChar(pos);
5916         if (IsLetterChar(c))
5917                 return true;
5918         // '\0' is not a letter, allthough every string contains "" (below)
5919         if( c == '\0')
5920                 return false;
5921         // We want to pass the ' and escape chars to ispell
5922         string extra = lyxrc->isp_esc_chars + '\'';
5923         char ch[2];
5924         ch[0] = c;
5925         ch[1] = 0;
5926         return contains(extra, ch);
5927 }
5928  
5929  
5930 bool LyXParagraph::IsWord(size_type pos ) const
5931 {
5932         return IsWordChar(GetChar(pos)) ;
5933 }
5934
5935
5936 LyXDirection LyXParagraph::getParDirection() const
5937 {
5938         if (!lyxrc->rtl_support || table)
5939                 return LYX_DIR_LEFT_TO_RIGHT;
5940
5941         if (size() > 0)
5942                 return (getFont(0).direction() ==  LyXFont::RTL_DIR)
5943                         ? LYX_DIR_RIGHT_TO_LEFT : LYX_DIR_LEFT_TO_RIGHT;
5944         else
5945                 return current_view->buffer()->params.getDocumentDirection();
5946 }
5947
5948
5949 LyXDirection
5950 LyXParagraph::getLetterDirection(LyXParagraph::size_type pos) const
5951 {
5952         if (!lyxrc->rtl_support)
5953                 return LYX_DIR_LEFT_TO_RIGHT;
5954
5955         LyXDirection direction = getFont(pos).getFontDirection();
5956         if (IsLineSeparator(pos) && 0 < pos && pos < Last() - 1
5957             && !IsLineSeparator(pos + 1)
5958             && !(table && IsNewline(pos + 1))
5959             && (getFont(pos - 1).getFontDirection() != direction
5960                 || getFont(pos + 1).getFontDirection() != direction))
5961                 return getParDirection();
5962         else
5963                 return direction;
5964 }