]> git.lyx.org Git - features.git/blob - src/paragraph.C
the freespacing patch from Kayvan, draw the math empty delim with onoffdash, asure...
[features.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, 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                                                style.free_spacing);
4008
4009                         if (close)
4010                                 os << "}";
4011                         
4012                         if (tmp) {
4013                                 column = 0;
4014                         } else {
4015                                 column += os.tellp() - len;
4016                         }
4017                         for (; tmp--;) {
4018                                 texrow.newline();
4019                         }
4020                 }
4021         }
4022         break;
4023
4024         case LyXParagraph::META_NEWLINE:
4025                 if (open_font) {
4026                         column += running_font.latexWriteEndChanges(os,
4027                                                                     basefont,
4028                                                                     basefont);
4029                         open_font = false;
4030                 }
4031                 basefont = getFont(-1);
4032                 running_font = basefont;
4033                 break;
4034
4035         case LyXParagraph::META_HFILL: 
4036                 os << "\\hfill{}";
4037                 column += 7;
4038                 break;
4039
4040         default:
4041                 // And now for the special cases within each mode
4042                 // Are we in LaTeX mode?
4043                 if (font.latex() == LyXFont::ON) {
4044                         // at present we only have one option
4045                         // but I'll leave it as a switch statement
4046                         // so its simpler to extend. (ARRae)
4047                         switch (c) {
4048 #if 0
4049                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
4050                                 os << ' ';
4051                                 break;
4052 #endif
4053                         default:
4054                                 // make sure that we will not print
4055                                 // error generating chars to the tex
4056                                 // file. This test would not be needed
4057                                 // if it were done in the buffer
4058                                 // itself.
4059                                 if (c != '\0') {
4060                                         os << c;
4061                                 }
4062                                 break;
4063                         }
4064                 } else {
4065                         // Plain mode (i.e. not LaTeX)
4066                         switch (c) {
4067 #if 0
4068                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
4069                                 os << '~';
4070                                 break;
4071 #endif
4072                         case '\\': 
4073                                 os << "\\textbackslash{}";
4074                                 column += 15;
4075                                 break;
4076                 
4077                         case '°': case '±': case '²': case '³':  
4078                         case '×': case '÷': case '¹': case 'ª':
4079                         case 'º': case '¬': case 'µ':
4080                                 if (current_view->buffer()->params.inputenc == "latin1") {
4081                                         os << "\\ensuremath{"
4082                                            << c
4083                                            << '}';
4084                                         column += 13;
4085                                 } else {
4086                                         os << c;
4087                                 }
4088                                 break;
4089
4090                         case '|': case '<': case '>':
4091                                 // In T1 encoding, these characters exist
4092                                 if (lyxrc->fontenc == "T1") {
4093                                         os << c;
4094                                         //... but we should avoid ligatures
4095                                         if ((c == '>' || c == '<')
4096                                             && i <= size() - 2
4097                                             && GetChar(i + 1) == c){
4098                                                 os << "\\textcompwordmark{}";
4099                                                 column += 19;
4100                                         }
4101                                         break;
4102                                 }
4103                                 // Typewriter font also has them
4104                                 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
4105                                         os << c;
4106                                         break;
4107                                 } 
4108                                 // Otherwise, we use what LaTeX
4109                                 // provides us.
4110                                 switch(c) {
4111                                 case '<':
4112                                         os << "\\textless{}";
4113                                         column += 10;
4114                                         break;
4115                                 case '>':
4116                                         os << "\\textgreater{}";
4117                                         column += 13;
4118                                         break;
4119                                 case '|':
4120                                         os << "\\textbar{}";
4121                                         column += 9;
4122                                         break;
4123                                 }
4124                                 break;
4125
4126                         case '-': // "--" in Typewriter mode -> "-{}-"
4127                                 if (i <= size() - 2
4128                                     && GetChar(i + 1) == '-'
4129                                     && font.family() == LyXFont::TYPEWRITER_FAMILY) {
4130                                         os << "-{}";
4131                                         column += 2;
4132                                 } else {
4133                                         os << '-';
4134                                 }
4135                                 break;
4136
4137                         case '\"': 
4138                                 os << "\\char`\\\"{}";
4139                                 column += 9;
4140                                 break;
4141
4142                         case '£':
4143                                 if (current_view->buffer()->params.inputenc == "default") {
4144                                         os << "\\pounds{}";
4145                                         column += 8;
4146                                 } else {
4147                                         os << c;
4148                                 }
4149                                 break;
4150
4151                         case '$': case '&':
4152                         case '%': case '#': case '{':
4153                         case '}': case '_':
4154                                 os << '\\' << c;
4155                                 column += 1;
4156                                 break;
4157
4158                         case '~':
4159                                 os << "\\textasciitilde{}";
4160                                 column += 16;
4161                                 break;
4162
4163                         case '^':
4164                                 os << "\\textasciicircum{}";
4165                                 column += 17;
4166                                 break;
4167
4168                         case '*': case '[': case ']':
4169                                 // avoid being mistaken for optional arguments
4170                                 os << '{' << c << '}';
4171                                 column += 2;
4172                                 break;
4173
4174                         case ' ':
4175                                 // Blanks are printed before font switching.
4176                                 // Sure? I am not! (try nice-latex)
4177                                 // I am sure it's correct. LyX might be smarter
4178                                 // in the future, but for now, nothing wrong is
4179                                 // written. (Asger)
4180                                 break;
4181
4182                         default:
4183                                 /* idea for labels --- begin*/
4184                                 // Check for "LyX"
4185                                 if (c ==  'L'
4186                                     && i <= size() - 3
4187                                     && font.family() != LyXFont::TYPEWRITER_FAMILY
4188                                     && GetChar(i + 1) == 'y'
4189                                     && GetChar(i + 2) == 'X') {
4190                                         os << "\\LyX{}";
4191                                         i += 2;
4192                                         column += 5;
4193                                 }
4194                                 // Check for "TeX"
4195                                 else if (c == 'T'
4196                                          && i <= size() - 3
4197                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4198                                          && GetChar(i + 1) == 'e'
4199                                          && GetChar(i + 2) == 'X') {
4200                                         os << "\\TeX{}";
4201                                         i += 2;
4202                                         column += 5;
4203                                 }
4204                                 // Check for "LaTeX2e"
4205                                 else if (c == 'L'
4206                                          && i <= size() - 7
4207                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4208                                          && GetChar(i + 1) == 'a'
4209                                          && GetChar(i + 2) == 'T'
4210                                          && GetChar(i + 3) == 'e'
4211                                          && GetChar(i + 4) == 'X'
4212                                          && GetChar(i + 5) == '2'
4213                                          && GetChar(i + 6) == 'e') {
4214                                         os << "\\LaTeXe{}";
4215                                         i += 6;
4216                                         column += 8;
4217                                 }
4218                                 // Check for "LaTeX"
4219                                 else if (c == 'L'
4220                                          && i <= size() - 5
4221                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4222                                          && GetChar(i + 1) == 'a'
4223                                          && GetChar(i + 2) == 'T'
4224                                          && GetChar(i + 3) == 'e'
4225                                          && GetChar(i + 4) == 'X') {
4226                                         os << "\\LaTeX{}";
4227                                         i += 4;
4228                                         column += 7;
4229                                         /* idea for labels --- end*/ 
4230                                 } else if (c != '\0') {
4231                                         os << c;
4232                                 }
4233                                 break;
4234                         }
4235                 }
4236         }
4237 }
4238 #else
4239 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
4240                                          LyXFont & font,
4241                                          LyXFont & running_font,
4242                                          LyXFont & basefont,
4243                                          bool & open_font,
4244                                          LyXLayout const & style,
4245                                          LyXParagraph::size_type & i,
4246                                          int & column, char const c)
4247 {
4248         // Two major modes:  LaTeX or plain
4249         // Handle here those cases common to both modes
4250         // and then split to handle the two modes separately.
4251         switch (c) {
4252         case LyXParagraph::META_INSET: {
4253                 Inset * inset = GetInset(i);
4254                 if (inset) {
4255                         bool close = false;
4256                         int len = file.length();
4257                         if ((inset->LyxCode() == Inset::GRAPHICS_CODE
4258                              || inset->LyxCode() == Inset::MATH_CODE
4259                              || inset->LyxCode() == Inset::URL_CODE)
4260                             && running_font.getFontDirection()
4261                             == LYX_DIR_RIGHT_TO_LEFT) {
4262                                 file += "\\L{";
4263                                 close = true;
4264                         }
4265 #ifdef USE_OSTREAM_ONLY
4266 #ifdef HAVE_SSTREAM
4267                         ostringstream ost;
4268                         int tmp = inset->Latex(ost, style.isCommand());
4269                         file += ost.str().c_str();
4270 #else
4271                         ostrstream ost;
4272                         int tmp = inset->Latex(ost, style.isCommand());
4273                         ost << '\0';
4274                         char * chtmp = ost.str();
4275                         file += chtmp;
4276                         delete [] chtmp;
4277 #endif          
4278 #else
4279                         int tmp = inset->Latex(file, style.isCommand());
4280 #endif
4281                         if (close)
4282                                 file += "}";
4283                         
4284                         if (tmp) {
4285                                 column = 0;
4286                         } else {
4287                                 column += file.length() - len;
4288                         }
4289                         for (; tmp--;) {
4290                                 texrow.newline();
4291                         }
4292                 }
4293         }
4294         break;
4295
4296         case LyXParagraph::META_NEWLINE:
4297                 if (open_font) {
4298                         column += running_font.latexWriteEndChanges(file,
4299                                                                     basefont, basefont);
4300                         open_font = false;
4301                 }
4302                 basefont = getFont(-1);
4303                 running_font = basefont;
4304                 break;
4305
4306         case LyXParagraph::META_HFILL: 
4307                 file += "\\hfill{}";
4308                 column += 7;
4309                 break;
4310
4311         default:
4312                 // And now for the special cases within each mode
4313                 // Are we in LaTeX mode?
4314                 if (font.latex() == LyXFont::ON) {
4315                         // at present we only have one option
4316                         // but I'll leave it as a switch statement
4317                         // so its simpler to extend. (ARRae)
4318                         switch (c) {
4319 #if 0
4320                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
4321                                 file += ' ';
4322                                 break;
4323 #endif
4324                         default:
4325                                 // make sure that we will not print
4326                                 // error generating chars to the tex
4327                                 // file. This test would not be needed
4328                                 // if it were done in the buffer
4329                                 // itself.
4330                                 if (c != '\0') {
4331                                         file += c;
4332                                 }
4333                                 break;
4334                         }
4335                 } else {
4336                         // Plain mode (i.e. not LaTeX)
4337                         switch (c) {
4338 #if 0
4339                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
4340                                 file += '~';
4341                                 break;
4342 #endif
4343                         case '\\': 
4344                                 file += "\\textbackslash{}";
4345                                 column += 15;
4346                                 break;
4347                 
4348                         case '°': case '±': case '²': case '³':  
4349                         case '×': case '÷': case '¹': case 'ª':
4350                         case 'º': case '¬': case 'µ':
4351                                 if (current_view->buffer()->params.inputenc == "latin1") {
4352                                         file += "\\ensuremath{";
4353                                         file += c;
4354                                         file += '}';
4355                                         column += 13;
4356                                 } else {
4357                                         file += c;
4358                                 }
4359                                 break;
4360
4361                         case '|': case '<': case '>':
4362                                 // In T1 encoding, these characters exist
4363                                 if (lyxrc->fontenc == "T1") {
4364                                         file += c;
4365                                         //... but we should avoid ligatures
4366                                         if ((c == '>' || c == '<')
4367                                             && i <= size() - 2
4368                                             && GetChar(i+1) == c){
4369                                                 file += "\\textcompwordmark{}";
4370                                                 column += 19;
4371                                         }
4372                                         break;
4373                                 }
4374                                 // Typewriter font also has them
4375                                 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
4376                                         file += c;
4377                                         break;
4378                                 } 
4379                                 // Otherwise, we use what LaTeX
4380                                 // provides us.
4381                                 switch(c) {
4382                                 case '<':
4383                                         file += "\\textless{}";
4384                                         column += 10;
4385                                         break;
4386                                 case '>':
4387                                         file += "\\textgreater{}";
4388                                         column += 13;
4389                                         break;
4390                                 case '|':
4391                                         file += "\\textbar{}";
4392                                         column += 9;
4393                                         break;
4394                                 }
4395                                 break;
4396
4397                         case '-': // "--" in Typewriter mode -> "-{}-"
4398                                 if (i <= size() - 2
4399                                     && GetChar(i + 1) == '-'
4400                                     && font.family() == LyXFont::TYPEWRITER_FAMILY) {
4401                                         file += "-{}";
4402                                         column += 2;
4403                                 } else {
4404                                         file += '-';
4405                                 }
4406                                 break;
4407
4408                         case '\"': 
4409                                 file += "\\char`\\\"{}";
4410                                 column += 9;
4411                                 break;
4412
4413                         case '£':
4414                                 if (current_view->buffer()->params.inputenc == "default") {
4415                                         file += "\\pounds{}";
4416                                         column += 8;
4417                                 } else {
4418                                         file += c;
4419                                 }
4420                                 break;
4421
4422                         case '$': case '&':
4423                         case '%': case '#': case '{':
4424                         case '}': case '_':
4425                                 file += '\\';
4426                                 file += c;
4427                                 column += 1;
4428                                 break;
4429
4430                         case '~':
4431                                 file += "\\textasciitilde{}";
4432                                 column += 16;
4433                                 break;
4434
4435                         case '^':
4436                                 file += "\\textasciicircum{}";
4437                                 column += 17;
4438                                 break;
4439
4440                         case '*': case '[': case ']':
4441                                 // avoid being mistaken for optional arguments
4442                                 file += '{';
4443                                 file += c;
4444                                 file += '}';
4445                                 column += 2;
4446                                 break;
4447
4448                         case ' ':
4449                                 // Blanks are printed before font switching.
4450                                 // Sure? I am not! (try nice-latex)
4451                                 // I am sure it's correct. LyX might be smarter
4452                                 // in the future, but for now, nothing wrong is
4453                                 // written. (Asger)
4454                                 break;
4455
4456                         default:
4457                                 /* idea for labels --- begin*/
4458                                 // Check for "LyX"
4459                                 if (c ==  'L'
4460                                     && i <= size() - 3
4461                                     && font.family() != LyXFont::TYPEWRITER_FAMILY
4462                                     && GetChar(i + 1) == 'y'
4463                                     && GetChar(i + 2) == 'X') {
4464                                         file += "\\LyX{}";
4465                                         i += 2;
4466                                         column += 5;
4467                                 }
4468                                 // Check for "TeX"
4469                                 else if (c == 'T'
4470                                          && i <= size() - 3
4471                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4472                                          && GetChar(i + 1) == 'e'
4473                                          && GetChar(i + 2) == 'X') {
4474                                         file += "\\TeX{}";
4475                                         i += 2;
4476                                         column += 5;
4477                                 }
4478                                 // Check for "LaTeX2e"
4479                                 else if (c == 'L'
4480                                          && i <= size() - 7
4481                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4482                                          && GetChar(i + 1) == 'a'
4483                                          && GetChar(i + 2) == 'T'
4484                                          && GetChar(i + 3) == 'e'
4485                                          && GetChar(i + 4) == 'X'
4486                                          && GetChar(i + 5) == '2'
4487                                          && GetChar(i + 6) == 'e') {
4488                                         file += "\\LaTeXe{}";
4489                                         i += 6;
4490                                         column += 8;
4491                                 }
4492                                 // Check for "LaTeX"
4493                                 else if (c == 'L'
4494                                          && i <= size() - 5
4495                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
4496                                          && GetChar(i + 1) == 'a'
4497                                          && GetChar(i + 2) == 'T'
4498                                          && GetChar(i + 3) == 'e'
4499                                          && GetChar(i + 4) == 'X') {
4500                                         file += "\\LaTeX{}";
4501                                         i += 4;
4502                                         column += 7;
4503                                         /* idea for labels --- end*/ 
4504                                 } else if (c != '\0') {
4505                                         file += c;
4506                                 }
4507                                 break;
4508                         }
4509                 }
4510         }
4511 }
4512 #endif
4513
4514
4515 #if 0
4516 bool LyXParagraph::RoffContTableRows(ostream & os,
4517                                      LyXParagraph::size_type i,
4518                                      int actcell)
4519 {
4520         if (!table)
4521                 return false;
4522
4523         LyXFont font1(LyXFont::ALL_INHERIT);
4524         LyXFont font2;
4525         Inset * inset;
4526         char c;
4527
4528         string fname2 = TmpFileName(string(), "RAT2");
4529         int lastpos = i;
4530         int cell = table->CellHasContRow(actcell);
4531         ++actcell;
4532         while(cell >= 0) {
4533                 // first find the right position
4534                 i = lastpos;
4535                 for (; i < size() && actcell < cell; ++i) {
4536                         c = GetChar(i);
4537                         if (c == LyXParagraph::META_NEWLINE)
4538                                 ++actcell;
4539                 }
4540                 lastpos = i;
4541                 c = GetChar(i);
4542                 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
4543                         os << " ";
4544                 for (; i < size()
4545                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
4546                      ++i) {
4547                         font2 = GetFontSettings(i);
4548                         if (font1.latex() != font2.latex()) {
4549                                 if (font2.latex() != LyXFont::OFF)
4550                                         continue;
4551                         }
4552                         c = GetChar(i);
4553                         switch (c) {
4554                         case LyXParagraph::META_INSET:
4555                                 if ((inset = GetInset(i))) {
4556 #if 1
4557 #ifdef HAVE_SSTREAM
4558                                         stringstream ss(ios::in | ios::out);
4559                                         inset->Latex(ss, -1);
4560                                         ss.seekp(0);
4561                                         ss.get(c);
4562                                         while (!ss) {
4563                                                 if (c == '\\')
4564                                                         os << "\\\\";
4565                                                 else
4566                                                         os << c;
4567                                                 ss.get(c);
4568                                         }
4569 #else
4570                                         strstream ss;
4571                                         inset->Latex(ss, -1);
4572                                         ss.seekp(0);
4573                                         ss.get(c);
4574                                         while (!ss) {
4575                                                 if (c == '\\')
4576                                                         os << "\\\\";
4577                                                 else
4578                                                         os << c;
4579                                                 ss.get(c);
4580                                         }
4581                                         delete [] ss.str();
4582 #endif
4583 #else
4584                                         fstream fs(fname2.c_str(),
4585                                                    ios::in|ios::out);
4586                                         if (!fs) {
4587                                                 WriteAlert(_("LYX_ERROR:"),
4588                                                            _("Cannot open temporary file:"),
4589                                                            fname2);
4590                                                 return false;
4591                                         }
4592                                         inset->Latex(fs, -1);
4593                                         fs.seekp(0);
4594                                         fs.get(c);
4595                                         while (!fs) {
4596                                                 if (c == '\\')
4597                                                         os << "\\\\";
4598                                                 else
4599                                                         os << c;
4600                                                 fs.get(c);
4601                                         }
4602                                         fs.close();
4603 #endif
4604                                 }
4605                                 break;
4606                         case LyXParagraph::META_NEWLINE:
4607                                 break;
4608                         case LyXParagraph::META_HFILL: 
4609                                 break;
4610 #if 0
4611                         case LyXParagraph::META_PROTECTED_SEPARATOR:
4612                                 break;
4613 #endif
4614                         case '\\': 
4615                                 os << "\\\\";
4616                                 break;
4617                         default:
4618                                 if (c != '\0')
4619                                         os << c;
4620                                 else
4621                                         lyxerr.debug() << "RoffAsciiTable: "
4622                                                 "NULL char in structure."
4623                                                        << endl;
4624                                 break;
4625                         }
4626                 }
4627                 cell = table->CellHasContRow(actcell);
4628         }
4629         return true;
4630 }
4631 #endif
4632
4633
4634 #ifdef USE_OSTREAM_ONLY
4635 LyXParagraph * LyXParagraph::TeXDeeper(ostream & os, TexRow & texrow,
4636                                        ostream & foot, TexRow & foot_texrow,
4637                                        int & foot_count)
4638 {
4639         lyxerr[Debug::LATEX] << "TeXDeeper...     " << this << endl;
4640         LyXParagraph * par = this;
4641
4642         while (par && par->depth == depth) {
4643                 if (par->IsDummy())
4644                         lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
4645                 if (textclasslist.Style(current_view->buffer()->params.textclass, 
4646                                         par->layout).isEnvironment()
4647                     || par->pextra_type != PEXTRA_NONE) {
4648                         par = par->TeXEnvironment(os, texrow,
4649                                                   foot, foot_texrow,
4650                                                   foot_count);
4651                 } else {
4652                         par = par->TeXOnePar(os, texrow,
4653                                              foot, foot_texrow,
4654                                              foot_count);
4655                 }
4656         }
4657         lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
4658
4659         return par;
4660 }
4661 #else
4662 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
4663                                        string & foot, TexRow & foot_texrow,
4664                                        int & foot_count)
4665 {
4666         lyxerr[Debug::LATEX] << "TeXDeeper...     " << this << endl;
4667         LyXParagraph * par = this;
4668
4669         while (par && par->depth == depth) {
4670                 if (par->IsDummy())
4671                         lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
4672                 if (textclasslist.Style(current_view->buffer()->params.textclass, 
4673                                         par->layout).isEnvironment()
4674                     || par->pextra_type != PEXTRA_NONE) 
4675                         {
4676                                 par = par->TeXEnvironment(file, texrow,
4677                                                           foot, foot_texrow,
4678                                                           foot_count);
4679                         } else {
4680                                 par = par->TeXOnePar(file, texrow,
4681                                                      foot, foot_texrow,
4682                                                      foot_count);
4683                         }
4684         }
4685         lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
4686
4687         return par;
4688 }
4689 #endif
4690
4691
4692 #ifdef USE_OSTREAM_ONLY
4693 LyXParagraph * LyXParagraph::TeXEnvironment(ostream & os, TexRow & texrow,
4694                                             ostream & foot,
4695                                             TexRow & foot_texrow,
4696                                             int & foot_count)
4697 {
4698         bool eindent_open = false;
4699         bool foot_this_level = false;
4700         // flags when footnotetext should be appended to file.
4701         static bool minipage_open = false;
4702         static int minipage_open_depth = 0;
4703         char par_sep = current_view->buffer()->params.paragraph_separation;
4704     
4705         lyxerr[Debug::LATEX] << "TeXEnvironment...     " << this << endl;
4706         if (IsDummy())
4707                 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
4708
4709         LyXLayout const & style =
4710                 textclasslist.Style(current_view->buffer()->params.textclass,
4711                                     layout);
4712        
4713         if (pextra_type == PEXTRA_INDENT) {
4714                 if (!pextra_width.empty()) {
4715                         os << "\\begin{LyXParagraphIndent}{"
4716                            << pextra_width << "}\n";
4717                 } else {
4718                         //float ib = atof(pextra_widthp.c_str())/100;
4719                         // string can't handle floats at present (971109)
4720                         // so I'll do a conversion by hand knowing that
4721                         // the limits are 0.0 to 1.0. ARRae.
4722                         os << "\\begin{LyXParagraphIndent}{";
4723                         switch (pextra_widthp.length()) {
4724                         case 3:
4725                                 os << "1.00";
4726                                 break;
4727                         case 2:
4728                                 os << "0."
4729                                    << pextra_widthp;
4730                                 break;
4731                         case 1:
4732                                 os << "0.0"
4733                                    << pextra_widthp;
4734                         }
4735                         os << "\\columnwidth}\n";
4736                 }
4737                 texrow.newline();
4738                 eindent_open = true;
4739         }
4740         if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
4741                 if (pextra_hfill && Previous() &&
4742                     (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
4743                         os << "\\hfill{}\n";
4744                         texrow.newline();
4745                 }
4746                 if (par_sep == BufferParams::PARSEP_INDENT) {
4747                         os << "{\\setlength\\parindent{0pt}\n";
4748                         texrow.newline();
4749                 }
4750                 os << "\\begin{minipage}";
4751                 switch(pextra_alignment) {
4752                 case MINIPAGE_ALIGN_TOP:
4753                         os << "[t]";
4754                         break;
4755                 case MINIPAGE_ALIGN_MIDDLE:
4756                         os << "[m]";
4757                         break;
4758                 case MINIPAGE_ALIGN_BOTTOM:
4759                         os << "[b]";
4760                         break;
4761                 }
4762                 if (!pextra_width.empty()) {
4763                         os << '{' << pextra_width << "}\n";
4764                 } else {
4765                         //float ib = atof(par->pextra_width.c_str())/100;
4766                         // string can't handle floats at present
4767                         // so I'll do a conversion by hand knowing that
4768                         // the limits are 0.0 to 1.0. ARRae.
4769                         os << '{';
4770                         switch (pextra_widthp.length()) {
4771                         case 3:
4772                                 os << "1.00";
4773                                 break;
4774                         case 2:
4775                                 os << "0."
4776                                    << pextra_widthp;
4777                                 break;
4778                         case 1:
4779                                 os << "0.0"
4780                                    << pextra_widthp;
4781                         }
4782                         os << "\\columnwidth}\n";
4783                 }
4784                 texrow.newline();
4785                 if (par_sep == BufferParams::PARSEP_INDENT) {
4786                         os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
4787                         texrow.newline();
4788                 }
4789                 minipage_open = true;
4790                 minipage_open_depth = depth;
4791         }
4792
4793 #ifdef WITH_WARNINGS
4794 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
4795         //I disabled it because it breaks when lists span on several
4796         //pages (JMarc)
4797 #endif
4798         if (style.isEnvironment()){
4799                 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
4800 #ifdef FANCY_FOOTNOTE_CODE
4801                         if (foot_count < 0) {
4802                                 // flag that footnote[mark][text] should be
4803                                 // used for any footnotes from now on
4804                                 foot_count = 0;
4805                                 foot_this_level = true;
4806                         }
4807 #endif
4808                         os << "\\begin{" << style.latexname() << "}{"
4809                            << labelwidthstring << "}\n";
4810                 } else if (style.labeltype == LABEL_BIBLIO) {
4811                         // ale970405
4812                         os << "\\begin{" << style.latexname() << "}{"
4813                            << bibitemWidthest(current_view->painter())
4814                            << "}\n";
4815                 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
4816 #ifdef FANCY_FOOTNOTE_CODE
4817                         if (foot_count < 0) {
4818                                 // flag that footnote[mark][text] should be
4819                                 // used for any footnotes from now on
4820                                 foot_count = 0;
4821                                 foot_this_level = true;
4822                         }
4823 #endif
4824                         os << "\\begin{" << style.latexname() << '}'
4825                            << style.latexparam() << '\n';
4826                 } else 
4827                         os << "\\begin{" << style.latexname() << '}'
4828                            << style.latexparam() << '\n';
4829                 texrow.newline();
4830         }
4831         LyXParagraph * par = this;
4832         do {
4833                 par = par->TeXOnePar(os, texrow,
4834                                      foot, foot_texrow, foot_count);
4835
4836                 if (minipage_open && par && !style.isEnvironment() &&
4837                     (par->pextra_type == PEXTRA_MINIPAGE) &&
4838                     par->pextra_start_minipage) {
4839                         os << "\\end{minipage}\n";
4840                         texrow.newline();
4841                         if (par_sep == BufferParams::PARSEP_INDENT) {
4842                                 os << "}\n";
4843                                 texrow.newline();
4844                         }
4845                         minipage_open = false;
4846                 }
4847                 if (par && par->depth > depth) {
4848                         if (textclasslist.Style(current_view->buffer()->params.textclass,
4849                                                 par->layout).isParagraph()
4850                             && !par->table
4851                             // Thinko!
4852                             // How to handle this? (Lgb)
4853                             //&& !suffixIs(os, "\n\n")
4854                                 ) {
4855                                 // There should be at least one '\n' already
4856                                 // but we need there to be two for Standard 
4857                                 // paragraphs that are depth-increment'ed to be
4858                                 // output correctly.  However, tables can
4859                                 // also be paragraphs so don't adjust them.
4860                                 // ARRae
4861                                 // Thinkee:
4862                                 // Will it ever harm to have one '\n' too
4863                                 // many? i.e. that we sometimes will have
4864                                 // three in a row. (Lgb)
4865                                 os << '\n';
4866                                 texrow.newline();
4867                         }
4868                         par = par->TeXDeeper(os, texrow,
4869                                              foot, foot_texrow, foot_count);
4870                 }
4871                 if (par && par->layout == layout && par->depth == depth &&
4872                     (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
4873                         if (par->pextra_hfill && par->Previous() &&
4874                             (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
4875                                 os << "\\hfill{}\n";
4876                                 texrow.newline();
4877                         }
4878                         if (par_sep == BufferParams::PARSEP_INDENT) {
4879                                 os << "{\\setlength\\parindent{0pt}\n";
4880                                 texrow.newline();
4881                         }
4882                         os << "\\begin{minipage}";
4883                         switch(par->pextra_alignment) {
4884                         case MINIPAGE_ALIGN_TOP:
4885                                 os << "[t]";
4886                                 break;
4887                         case MINIPAGE_ALIGN_MIDDLE:
4888                                 os << "[m]";
4889                                 break;
4890                         case MINIPAGE_ALIGN_BOTTOM:
4891                                 os << "[b]";
4892                                 break;
4893                         }
4894                         if (!par->pextra_width.empty()) {
4895                                 os << '{' << par->pextra_width << "}\n";
4896                         } else {
4897                                 //float ib = atof(par->pextra_widthp.c_str())/100;
4898                                 // string can't handle floats at present
4899                                 // so I'll do a conversion by hand knowing that
4900                                 // the limits are 0.0 to 1.0. ARRae.
4901                                 os << '{';
4902                                 switch (par->pextra_widthp.length()) {
4903                                 case 3:
4904                                         os << "1.00";
4905                                         break;
4906                                 case 2:
4907                                         os << "0." << par->pextra_widthp;
4908                                         break;
4909                                 case 1:
4910                                         os << "0.0" << par->pextra_widthp;
4911                                 }
4912                                 os << "\\columnwidth}\n";
4913                         }
4914                         texrow.newline();
4915                         if (par_sep == BufferParams::PARSEP_INDENT) {
4916                                 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
4917                                 texrow.newline();
4918                         }
4919                         minipage_open = true;
4920                         minipage_open_depth = par->depth;
4921                 }
4922         } while (par
4923                  && par->layout == layout
4924                  && par->depth == depth
4925                  && par->pextra_type == pextra_type);
4926  
4927         if (style.isEnvironment()) {
4928                 os << "\\end{" << style.latexname() << '}';
4929                 // maybe this should go after the minipage closes?
4930                 if (foot_this_level) {
4931                         if (foot_count >= 1) {
4932                                 if (foot_count > 1) {
4933                                         os << "\\addtocounter{footnote}{-"
4934                                            << foot_count - 1
4935                                            << '}';
4936                                 }
4937                                 os << foot;
4938                                 texrow += foot_texrow;
4939                                 foot.clear();
4940                                 foot_texrow.reset();
4941                                 foot_count = 0;
4942                         }
4943                 }
4944         }
4945         if (minipage_open && (minipage_open_depth == depth) &&
4946             (!par || par->pextra_start_minipage ||
4947              par->pextra_type != PEXTRA_MINIPAGE)) {
4948                 os << "\\end{minipage}\n";
4949                 texrow.newline();
4950                 if (par_sep == BufferParams::PARSEP_INDENT) {
4951                         os << "}\n";
4952                         texrow.newline();
4953                 }
4954                 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
4955                         os << "\\medskip\n\n";
4956                         texrow.newline();
4957                         texrow.newline();
4958                 }
4959                 minipage_open = false;
4960         }
4961         if (eindent_open) {
4962                 os << "\\end{LyXParagraphIndent}\n";
4963                 texrow.newline();
4964         }
4965         if (!(par && (par->pextra_type == PEXTRA_MINIPAGE) 
4966               && par->pextra_hfill)) {
4967                 os << '\n';
4968                 texrow.newline();
4969         }
4970         lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
4971         return par;  // ale970302
4972 }
4973 #else
4974 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
4975                                             string & foot,
4976                                             TexRow & foot_texrow,
4977                                             int & foot_count)
4978 {
4979         bool eindent_open = false;
4980         bool foot_this_level = false;
4981         // flags when footnotetext should be appended to file.
4982         static bool minipage_open = false;
4983         static int minipage_open_depth = 0;
4984         char par_sep = current_view->buffer()->params.paragraph_separation;
4985     
4986         lyxerr[Debug::LATEX] << "TeXEnvironment...     " << this << endl;
4987         if (IsDummy())
4988                 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
4989
4990         LyXLayout const & style =
4991                 textclasslist.Style(current_view->buffer()->params.textclass,
4992                                     layout);
4993        
4994         if (pextra_type == PEXTRA_INDENT) {
4995                 if (!pextra_width.empty()) {
4996                         file += "\\begin{LyXParagraphIndent}{"
4997                                 + pextra_width + "}\n";
4998                 } else {
4999                         //float ib = atof(pextra_widthp.c_str())/100;
5000                         // string can't handle floats at present (971109)
5001                         // so I'll do a conversion by hand knowing that
5002                         // the limits are 0.0 to 1.0. ARRae.
5003                         file += "\\begin{LyXParagraphIndent}{";
5004                         switch (pextra_widthp.length()) {
5005                         case 3:
5006                                 file += "1.00";
5007                                 break;
5008                         case 2:
5009                                 file += "0.";
5010                                 file += pextra_widthp;
5011                                 break;
5012                         case 1:
5013                                 file += "0.0";
5014                                 file += pextra_widthp;
5015                         }
5016                         file += "\\columnwidth}\n";
5017                 }
5018                 texrow.newline();
5019                 eindent_open = true;
5020         }
5021         if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
5022                 if (pextra_hfill && Previous() &&
5023                     (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
5024                         file += "\\hfill{}\n";
5025                         texrow.newline();
5026                 }
5027                 if (par_sep == BufferParams::PARSEP_INDENT) {
5028                         file += "{\\setlength\\parindent{0pt}\n";
5029                         texrow.newline();
5030                 }
5031                 file += "\\begin{minipage}";
5032                 switch(pextra_alignment) {
5033                 case MINIPAGE_ALIGN_TOP:
5034                         file += "[t]";
5035                         break;
5036                 case MINIPAGE_ALIGN_MIDDLE:
5037                         file += "[m]";
5038                         break;
5039                 case MINIPAGE_ALIGN_BOTTOM:
5040                         file += "[b]";
5041                         break;
5042                 }
5043                 if (!pextra_width.empty()) {
5044                         file += '{';
5045                         file += pextra_width + "}\n";
5046                 } else {
5047                         //float ib = atof(par->pextra_width.c_str())/100;
5048                         // string can't handle floats at present
5049                         // so I'll do a conversion by hand knowing that
5050                         // the limits are 0.0 to 1.0. ARRae.
5051                         file += '{';
5052                         switch (pextra_widthp.length()) {
5053                         case 3:
5054                                 file += "1.00";
5055                                 break;
5056                         case 2:
5057                                 file += "0.";
5058                                 file += pextra_widthp;
5059                                 break;
5060                         case 1:
5061                                 file += "0.0";
5062                                 file += pextra_widthp;
5063                         }
5064                         file += "\\columnwidth}\n";
5065                 }
5066                 texrow.newline();
5067                 if (par_sep == BufferParams::PARSEP_INDENT) {
5068                         file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
5069                         texrow.newline();
5070                 }
5071                 minipage_open = true;
5072                 minipage_open_depth = depth;
5073         }
5074
5075 #ifdef WITH_WARNINGS
5076 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
5077         //I disabled it because it breaks when lists span on several
5078         //pages (JMarc)
5079 #endif
5080         if (style.isEnvironment()){
5081                 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
5082 #ifdef FANCY_FOOTNOTE_CODE
5083                         if (foot_count < 0) {
5084                                 // flag that footnote[mark][text] should be
5085                                 // used for any footnotes from now on
5086                                 foot_count = 0;
5087                                 foot_this_level = true;
5088                         }
5089 #endif
5090                         file += "\\begin{" + style.latexname() + "}{"
5091                                 + labelwidthstring + "}\n";
5092                 } else if (style.labeltype == LABEL_BIBLIO) {
5093                         // ale970405
5094                         file += "\\begin{" + style.latexname() + "}{"
5095                                 + bibitemWidthest(current_view->painter())
5096                                 + "}\n";
5097                 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
5098 #ifdef FANCY_FOOTNOTE_CODE
5099                         if (foot_count < 0) {
5100                                 // flag that footnote[mark][text] should be
5101                                 // used for any footnotes from now on
5102                                 foot_count = 0;
5103                                 foot_this_level = true;
5104                         }
5105 #endif
5106                         file += "\\begin{" + style.latexname() + '}'
5107                                 + style.latexparam() + '\n';
5108                 } else 
5109                         file += "\\begin{" + style.latexname() + '}'
5110                                 + style.latexparam() + '\n';
5111                 texrow.newline();
5112         }
5113         LyXParagraph * par = this;
5114         do {
5115                 par = par->TeXOnePar(file, texrow,
5116                                      foot, foot_texrow, foot_count);
5117
5118                 if (minipage_open && par && !style.isEnvironment() &&
5119                     (par->pextra_type == PEXTRA_MINIPAGE) &&
5120                     par->pextra_start_minipage) {
5121                         file += "\\end{minipage}\n";
5122                         texrow.newline();
5123                         if (par_sep == BufferParams::PARSEP_INDENT) {
5124                                 file += "}\n";
5125                                 texrow.newline();
5126                         }
5127                         minipage_open = false;
5128                 }
5129                 if (par && par->depth > depth) {
5130                         if (textclasslist.Style(current_view->buffer()->params.textclass,
5131                                                 par->layout).isParagraph()
5132                             && !par->table
5133                             && !suffixIs(file, "\n\n")) {
5134                                 // There should be at least one '\n' already
5135                                 // but we need there to be two for Standard 
5136                                 // paragraphs that are depth-increment'ed to be
5137                                 // output correctly.  However, tables can
5138                                 // also be paragraphs so don't adjust them.
5139                                 // ARRae
5140                                 file += '\n';
5141                                 texrow.newline();
5142                         }
5143                         par = par->TeXDeeper(file, texrow,
5144                                              foot, foot_texrow, foot_count);
5145                 }
5146                 if (par && par->layout == layout && par->depth == depth &&
5147                     (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
5148                         if (par->pextra_hfill && par->Previous() &&
5149                             (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
5150                                 file += "\\hfill{}\n";
5151                                 texrow.newline();
5152                         }
5153                         if (par_sep == BufferParams::PARSEP_INDENT) {
5154                                 file += "{\\setlength\\parindent{0pt}\n";
5155                                 texrow.newline();
5156                         }
5157                         file += "\\begin{minipage}";
5158                         switch(par->pextra_alignment) {
5159                         case MINIPAGE_ALIGN_TOP:
5160                                 file += "[t]";
5161                                 break;
5162                         case MINIPAGE_ALIGN_MIDDLE:
5163                                 file += "[m]";
5164                                 break;
5165                         case MINIPAGE_ALIGN_BOTTOM:
5166                                 file += "[b]";
5167                                 break;
5168                         }
5169                         if (!par->pextra_width.empty()) {
5170                                 file += '{';
5171                                 file += par->pextra_width;
5172                                 file += "}\n";
5173                         } else {
5174                                 //float ib = atof(par->pextra_widthp.c_str())/100;
5175                                 // string can't handle floats at present
5176                                 // so I'll do a conversion by hand knowing that
5177                                 // the limits are 0.0 to 1.0. ARRae.
5178                                 file += '{';
5179                                 switch (par->pextra_widthp.length()) {
5180                                 case 3:
5181                                         file += "1.00";
5182                                         break;
5183                                 case 2:
5184                                         file += "0.";
5185                                         file += par->pextra_widthp;
5186                                         break;
5187                                 case 1:
5188                                         file += "0.0";
5189                                         file += par->pextra_widthp;
5190                                 }
5191                                 file += "\\columnwidth}\n";
5192                         }
5193                         texrow.newline();
5194                         if (par_sep == BufferParams::PARSEP_INDENT) {
5195                                 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
5196                                 texrow.newline();
5197                         }
5198                         minipage_open = true;
5199                         minipage_open_depth = par->depth;
5200                 }
5201         } while (par
5202                  && par->layout == layout
5203                  && par->depth == depth
5204                  && par->pextra_type == pextra_type);
5205  
5206         if (style.isEnvironment()) {
5207                 file += "\\end{" + style.latexname() + '}';
5208                 // maybe this should go after the minipage closes?
5209                 if (foot_this_level) {
5210                         if (foot_count >= 1) {
5211                                 if (foot_count > 1) {
5212                                         file += "\\addtocounter{footnote}{-";
5213                                         file += tostr(foot_count - 1);
5214                                         file += '}';
5215                                 }
5216                                 file += foot;
5217                                 texrow += foot_texrow;
5218                                 foot.clear();
5219                                 foot_texrow.reset();
5220                                 foot_count = 0;
5221                         }
5222                 }
5223         }
5224         if (minipage_open && (minipage_open_depth == depth) &&
5225             (!par || par->pextra_start_minipage ||
5226              par->pextra_type != PEXTRA_MINIPAGE)) {
5227                 file += "\\end{minipage}\n";
5228                 texrow.newline();
5229                 if (par_sep == BufferParams::PARSEP_INDENT) {
5230                         file += "}\n";
5231                         texrow.newline();
5232                 }
5233                 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
5234                         file += "\\medskip\n\n";
5235                         texrow.newline();
5236                         texrow.newline();
5237                 }
5238                 minipage_open = false;
5239         }
5240         if (eindent_open) {
5241                 file += "\\end{LyXParagraphIndent}\n";
5242                 texrow.newline();
5243         }
5244         if (!(par && (par->pextra_type == PEXTRA_MINIPAGE) 
5245               && par->pextra_hfill)) {
5246                 file += '\n';
5247                 texrow.newline();
5248         }
5249         lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
5250         return par;  // ale970302
5251 }
5252 #endif
5253
5254
5255 #ifdef USE_OSTREAM_ONLY
5256 LyXParagraph * LyXParagraph::TeXFootnote(ostream & os, TexRow & texrow,
5257                                          ostream & foot, TexRow & foot_texrow,
5258                                          int & foot_count,
5259                                          LyXDirection par_direction)
5260 {
5261         lyxerr[Debug::LATEX] << "TeXFootnote...  " << this << endl;
5262         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
5263                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5264                         "No footnote!" << endl;
5265
5266         LyXParagraph * par = this;
5267         LyXLayout const & style =
5268                 textclasslist.Style(current_view->buffer()->params.textclass, 
5269                                     previous->GetLayout());
5270         
5271         if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
5272                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5273                         "Float other than footnote in command"
5274                         " with moving argument is illegal" << endl;
5275         }
5276
5277         if (footnotekind != LyXParagraph::FOOTNOTE
5278             && footnotekind != LyXParagraph::MARGIN
5279             && os.tellp()
5280             // Thinko
5281             // How to solve this?
5282             //&& !suffixIs(file, '\n')
5283                 ) {
5284                 // we need to ensure that real floats like tables and figures
5285                 // have their \begin{} on a new line otherwise we can get
5286                 // incorrect results when using the endfloat.sty package
5287                 // especially if two floats follow one another.  ARRae 981022
5288                 // NOTE: if the file is length 0 it must have just been
5289                 //       written out so we assume it ended with a '\n'
5290                 // Thinkee:
5291                 // As far as I can see there is never any harm in writing
5292                 // a '\n' too much. Please tell me if I am wrong. (Lgb)
5293                 os << '\n';
5294                 texrow.newline();
5295         }
5296         
5297         BufferParams * params = &current_view->buffer()->params;
5298         bool footer_in_body = true;
5299         switch (footnotekind) {
5300         case LyXParagraph::FOOTNOTE:
5301                 if (style.intitle) {
5302                         os << "\\thanks{\n";
5303                         footer_in_body = false;
5304                 } else {
5305                         if (foot_count == -1) {
5306                                 // we're at depth 0 so we can use:
5307                                 os << "\\footnote{%\n";
5308                                 footer_in_body = false;
5309                         } else {
5310                                 os << "\\footnotemark{}%\n";
5311                                 if (foot_count) {
5312                                         // we only need this when there are
5313                                         // multiple footnotes
5314                                         os << "\\stepcounter{footnote}";
5315                                 }
5316                                 os << "\\footnotetext{%\n";
5317                                 foot_texrow.start(this, 0);
5318                                 foot_texrow.newline();
5319                                 ++foot_count;
5320                         }
5321                 }
5322                 break;
5323         case LyXParagraph::MARGIN:
5324                 os << "\\marginpar{\n";
5325                 break;
5326         case LyXParagraph::FIG:
5327                 if (pextra_type == PEXTRA_FLOATFLT
5328                     && (!pextra_width.empty()
5329                         || !pextra_widthp.empty())) {
5330                         if (!pextra_width.empty())
5331                                 os << "\\begin{floatingfigure}{"
5332                                    << pextra_width << "}\n";
5333                         else
5334                                 os << "\\begin{floatingfigure}{"
5335                                    << atoi(pextra_widthp.c_str())/100.0
5336                                    << "\\textwidth}\n";
5337                 } else {
5338                         os << "\\begin{figure}";
5339                         if (!params->float_placement.empty()) { 
5340                                 os << '[' << params->float_placement << "]\n";
5341                         } else {
5342                                 os << '\n';
5343                         }
5344                 }
5345                 break;
5346         case LyXParagraph::TAB:
5347                 os << "\\begin{table}";
5348                 if (!params->float_placement.empty()) { 
5349                         os << '[' << params->float_placement << "]\n";
5350                 } else {
5351                         os << '\n';
5352                 }
5353                 break;
5354         case LyXParagraph::WIDE_FIG:
5355                 os << "\\begin{figure*}";
5356                 if (!params->float_placement.empty()) { 
5357                         os << '[' << params->float_placement << "]\n";
5358                 } else {
5359                         os << '\n';
5360                 }
5361                 break;
5362         case LyXParagraph::WIDE_TAB:
5363                 os << "\\begin{table*}";
5364                 if (!params->float_placement.empty()) { 
5365                         os << '[' << params->float_placement << "]\n";
5366                 } else {
5367                         os << '\n';
5368                 }
5369                 break;
5370         case LyXParagraph::ALGORITHM:
5371                 os << "\\begin{algorithm}\n";
5372                 break;
5373         }
5374         texrow.newline();
5375    
5376  
5377         LyXDirection direction = getParDirection();
5378         if (direction != par_direction) {
5379                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
5380                         os << "\\unsethebrew\n";
5381                 else
5382                         os << "\\sethebrew\n";
5383                 texrow.newline();
5384         }
5385
5386         if (footnotekind != LyXParagraph::FOOTNOTE
5387             || !footer_in_body) {
5388                 // Process text for all floats except footnotes in body
5389                 do {
5390                         LyXLayout const & style =
5391                                 textclasslist
5392                                 .Style(current_view->buffer()->params
5393                                        .textclass,
5394                                        par->layout);
5395                         if (par->IsDummy())
5396                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5397                                        << endl;
5398                         if (style.isEnvironment()
5399                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5400                                 // Allows the use of minipages within float
5401                                 // environments. Shouldn't be circular because
5402                                 // we don't support footnotes inside
5403                                 // floats (yet). ARRae
5404                                 par = par->TeXEnvironment(os, texrow,
5405                                                           foot, foot_texrow,
5406                                                           foot_count);
5407                         } else {
5408                                 par = par->TeXOnePar(os, texrow,
5409                                                      foot, foot_texrow,
5410                                                      foot_count);
5411                         }
5412                         
5413                         if (par && !par->IsDummy() && par->depth > depth) {
5414                                 par = par->TeXDeeper(os, texrow,
5415                                                      foot, foot_texrow,
5416                                                      foot_count);
5417                         }
5418                 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5419         } else {
5420                 // process footnotes > depth 0 or in environments separately
5421                 // NOTE: Currently don't support footnotes within footnotes
5422                 //       even though that is possible using the \footnotemark
5423 #ifdef HAVE_SSTREAM
5424                 ostringstream dummy;
5425 #else
5426                 ostrstream dummy;
5427 #endif
5428                 TexRow dummy_texrow;
5429                 int dummy_count = 0;
5430                 do {
5431                         LyXLayout const & style =
5432                                 textclasslist
5433                                 .Style(current_view->buffer()->params
5434                                        .textclass,
5435                                        par->layout);
5436                         if (par->IsDummy())
5437                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5438                                        << endl;
5439                         if (style.isEnvironment()
5440                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5441                                 // Allows the use of minipages within float
5442                                 // environments. Shouldn't be circular because
5443                                 // we don't support footnotes inside
5444                                 // floats (yet). ARRae
5445                                 par = par->TeXEnvironment(foot, foot_texrow,
5446                                                           dummy, dummy_texrow,
5447                                                           dummy_count);
5448                         } else {
5449                                 par = par->TeXOnePar(foot, foot_texrow,
5450                                                      dummy, dummy_texrow,
5451                                                      dummy_count);
5452                         }
5453
5454                         if (par && !par->IsDummy() && par->depth > depth) {
5455                                 par = par->TeXDeeper(foot, foot_texrow,
5456                                                      dummy, dummy_texrow,
5457                                                      dummy_count);
5458                         }
5459                 } while (par
5460                          && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5461                 if (dummy_count) {
5462                         lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5463                                 "Footnote in a Footnote -- not supported"
5464                                << endl;
5465                 }
5466 #ifndef HAVE_OSTREAM
5467                 delete [] dummy.str();
5468 #endif
5469         }
5470
5471         switch (footnotekind) {
5472         case LyXParagraph::FOOTNOTE:
5473                 if (footer_in_body) {
5474                         // This helps tell which of the multiple
5475                         // footnotetexts an error was in.
5476                         foot << "}%\n";
5477                         foot_texrow.newline();
5478                 } else {
5479                         os << '}';
5480                 }
5481                 break;
5482         case LyXParagraph::MARGIN:
5483                 os << '}';
5484                 break;
5485         case LyXParagraph::FIG:
5486                 if (pextra_type == PEXTRA_FLOATFLT
5487                     && (!pextra_width.empty()
5488                         || !pextra_widthp.empty()))
5489                         os << "\\end{floatingfigure}";
5490                 else
5491                         os << "\\end{figure}";
5492                 break;
5493         case LyXParagraph::TAB:
5494                 os << "\\end{table}";
5495                 break;
5496         case LyXParagraph::WIDE_FIG:
5497                 os << "\\end{figure*}";
5498                 break;
5499         case LyXParagraph::WIDE_TAB:
5500                 os << "\\end{table*}";
5501                 break;
5502         case LyXParagraph::ALGORITHM:
5503                 os << "\\end{algorithm}";
5504                 break;
5505         }
5506
5507         if (footnotekind != LyXParagraph::FOOTNOTE
5508             && footnotekind != LyXParagraph::MARGIN) {
5509                 // we need to ensure that real floats like tables and figures
5510                 // have their \end{} on a line of their own otherwise we can
5511                 // get incorrect results when using the endfloat.sty package.
5512                 os << "\n";
5513                 texrow.newline();
5514         }
5515
5516         lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
5517         return par;
5518 }
5519 #else
5520 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
5521                                          string & foot, TexRow & foot_texrow,
5522                                          int & foot_count,
5523                                          LyXDirection par_direction)
5524 {
5525         lyxerr[Debug::LATEX] << "TeXFootnote...  " << this << endl;
5526         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
5527                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5528                         "No footnote!" << endl;
5529
5530         LyXParagraph * par = this;
5531         LyXLayout const & style =
5532                 textclasslist.Style(current_view->buffer()->params.textclass, 
5533                                     previous->GetLayout());
5534         
5535         if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
5536                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5537                         "Float other than footnote in command"
5538                         " with moving argument is illegal" << endl;
5539         }
5540
5541         if (footnotekind != LyXParagraph::FOOTNOTE
5542             && footnotekind != LyXParagraph::MARGIN
5543             && file.length()
5544             && !suffixIs(file, '\n')) {
5545                 // we need to ensure that real floats like tables and figures
5546                 // have their \begin{} on a new line otherwise we can get
5547                 // incorrect results when using the endfloat.sty package
5548                 // especially if two floats follow one another.  ARRae 981022
5549                 // NOTE: if the file is length 0 it must have just been
5550                 //       written out so we assume it ended with a '\n'
5551                 file += '\n';
5552                 texrow.newline();
5553         }
5554         
5555         BufferParams * params = &current_view->buffer()->params;
5556         bool footer_in_body = true;
5557         switch (footnotekind) {
5558         case LyXParagraph::FOOTNOTE:
5559                 if (style.intitle) {
5560                         file += "\\thanks{\n";
5561                         footer_in_body = false;
5562                 } else {
5563                         if (foot_count == -1) {
5564                                 // we're at depth 0 so we can use:
5565                                 file += "\\footnote{%\n";
5566                                 footer_in_body = false;
5567                         } else {
5568                                 file += "\\footnotemark{}%\n";
5569                                 if (foot_count) {
5570                                         // we only need this when there are
5571                                         // multiple footnotes
5572                                         foot += "\\stepcounter{footnote}";
5573                                 }
5574                                 foot += "\\footnotetext{%\n";
5575                                 foot_texrow.start(this, 0);
5576                                 foot_texrow.newline();
5577                                 ++foot_count;
5578                         }
5579                 }
5580                 break;
5581         case LyXParagraph::MARGIN:
5582                 file += "\\marginpar{\n";
5583                 break;
5584         case LyXParagraph::FIG:
5585                 if (pextra_type == PEXTRA_FLOATFLT
5586                     && (!pextra_width.empty()
5587                         || !pextra_widthp.empty())) {
5588                         char bufr[80];
5589                         if (!pextra_width.empty())
5590                                 sprintf(bufr,
5591                                         "\\begin{floatingfigure}{%s}\n",
5592                                         pextra_width.c_str());
5593                         else
5594                                 sprintf(bufr,
5595                                         "\\begin{floatingfigure}{%f\\textwidth}\n",
5596                                         atoi(pextra_widthp.c_str())/100.0);
5597                         file += bufr;
5598                 } else {
5599                         file += "\\begin{figure}";
5600                         if (!params->float_placement.empty()) { 
5601                                 file += '[';
5602                                 file += params->float_placement;
5603                                 file += "]\n";
5604                         } else {
5605                                 file += '\n';
5606                         }
5607                 }
5608                 break;
5609         case LyXParagraph::TAB:
5610                 file += "\\begin{table}";
5611                 if (!params->float_placement.empty()) { 
5612                         file += '[';
5613                         file += params->float_placement;
5614                         file += "]\n";
5615                 } else {
5616                         file += '\n';
5617                 }
5618                 break;
5619         case LyXParagraph::WIDE_FIG:
5620                 file += "\\begin{figure*}";
5621                 if (!params->float_placement.empty()) { 
5622                         file += '[';
5623                         file += params->float_placement;
5624                         file += "]\n";
5625                 } else {
5626                         file += '\n';
5627                 }
5628                 break;
5629         case LyXParagraph::WIDE_TAB:
5630                 file += "\\begin{table*}";
5631                 if (!params->float_placement.empty()) { 
5632                         file += '[';
5633                         file += params->float_placement;
5634                         file += "]\n";
5635                 } else {
5636                         file += '\n';
5637                 }
5638                 break;
5639         case LyXParagraph::ALGORITHM:
5640                 file += "\\begin{algorithm}\n";
5641                 break;
5642         }
5643         texrow.newline();
5644    
5645  
5646         LyXDirection direction = getParDirection();
5647         if (direction != par_direction) {
5648                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
5649                         file += "\\unsethebrew\n";
5650                 else
5651                         file += "\\sethebrew\n";
5652                 texrow.newline();
5653         }
5654
5655         if (footnotekind != LyXParagraph::FOOTNOTE
5656             || !footer_in_body) {
5657                 // Process text for all floats except footnotes in body
5658                 do {
5659                         LyXLayout const & style =
5660                                 textclasslist
5661                                 .Style(current_view->buffer()->params
5662                                        .textclass,
5663                                        par->layout);
5664                         if (par->IsDummy())
5665                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5666                                        << endl;
5667                         if (style.isEnvironment()
5668                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5669                                 // Allows the use of minipages within float
5670                                 // environments. Shouldn't be circular because
5671                                 // we don't support footnotes inside
5672                                 // floats (yet). ARRae
5673                                 par = par->TeXEnvironment(file, texrow,
5674                                                           foot, foot_texrow,
5675                                                           foot_count);
5676                         } else {
5677                                 par = par->TeXOnePar(file, texrow,
5678                                                      foot, foot_texrow,
5679                                                      foot_count);
5680                         }
5681                         
5682                         if (par && !par->IsDummy() && par->depth > depth) {
5683                                 par = par->TeXDeeper(file, texrow,
5684                                                      foot, foot_texrow,
5685                                                      foot_count);
5686                         }
5687                 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5688         } else {
5689                 // process footnotes > depth 0 or in environments separately
5690                 // NOTE: Currently don't support footnotes within footnotes
5691                 //       even though that is possible using the \footnotemark
5692                 string dummy;
5693                 TexRow dummy_texrow;
5694                 int dummy_count = 0;
5695                 do {
5696                         LyXLayout const & style =
5697                                 textclasslist
5698                                 .Style(current_view->buffer()->params
5699                                        .textclass,
5700                                        par->layout);
5701                         if (par->IsDummy())
5702                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5703                                        << endl;
5704                         if (style.isEnvironment()
5705                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5706                                 // Allows the use of minipages within float
5707                                 // environments. Shouldn't be circular because
5708                                 // we don't support footnotes inside
5709                                 // floats (yet). ARRae
5710                                 par = par->TeXEnvironment(foot, foot_texrow,
5711                                                           dummy, dummy_texrow,
5712                                                           dummy_count);
5713                         } else {
5714                                 par = par->TeXOnePar(foot, foot_texrow,
5715                                                      dummy, dummy_texrow,
5716                                                      dummy_count);
5717                         }
5718
5719                         if (par && !par->IsDummy() && par->depth > depth) {
5720                                 par = par->TeXDeeper(foot, foot_texrow,
5721                                                      dummy, dummy_texrow,
5722                                                      dummy_count);
5723                         }
5724                 } while (par
5725                          && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5726                 if (dummy_count) {
5727                         lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5728                                 "Footnote in a Footnote -- not supported"
5729                                << endl;
5730                 }
5731         }
5732
5733         switch (footnotekind) {
5734         case LyXParagraph::FOOTNOTE:
5735                 if (footer_in_body) {
5736                         // This helps tell which of the multiple
5737                         // footnotetexts an error was in.
5738                         foot += "}%\n";
5739                         foot_texrow.newline();
5740                 } else {
5741                         file += '}';
5742                 }
5743                 break;
5744         case LyXParagraph::MARGIN:
5745                 file += '}';
5746                 break;
5747         case LyXParagraph::FIG:
5748                 if (pextra_type == PEXTRA_FLOATFLT
5749                     && (!pextra_width.empty()
5750                         || !pextra_widthp.empty()))
5751                         file += "\\end{floatingfigure}";
5752                 else
5753                         file += "\\end{figure}";
5754                 break;
5755         case LyXParagraph::TAB:
5756                 file += "\\end{table}";
5757                 break;
5758         case LyXParagraph::WIDE_FIG:
5759                 file += "\\end{figure*}";
5760                 break;
5761         case LyXParagraph::WIDE_TAB:
5762                 file += "\\end{table*}";
5763                 break;
5764         case LyXParagraph::ALGORITHM:
5765                 file += "\\end{algorithm}";
5766                 break;
5767         }
5768
5769         if (footnotekind != LyXParagraph::FOOTNOTE
5770             && footnotekind != LyXParagraph::MARGIN) {
5771                 // we need to ensure that real floats like tables and figures
5772                 // have their \end{} on a line of their own otherwise we can
5773                 // get incorrect results when using the endfloat.sty package.
5774                 file += "\n";
5775                 texrow.newline();
5776         }
5777
5778         lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
5779         return par;
5780 }
5781 #endif
5782
5783
5784 void LyXParagraph::SetPExtraType(int type, char const * width,
5785                                  char const * widthp)
5786 {
5787         pextra_type = type;
5788         pextra_width = width;
5789         pextra_widthp = widthp;
5790
5791         if (textclasslist.Style(current_view->buffer()->params.textclass, 
5792                                 layout).isEnvironment()) {
5793                 LyXParagraph
5794                         * par = this,
5795                         * ppar = par;
5796
5797                 while (par && (par->layout == layout)
5798                        && (par->depth == depth)) {
5799                         ppar = par;
5800                         par = par->Previous();
5801                         if (par)
5802                                 par = par->FirstPhysicalPar();
5803                         while (par && par->depth > depth) {
5804                                 par = par->Previous();
5805                                 if (par)
5806                                         par = par->FirstPhysicalPar();
5807                         }
5808                 }
5809                 par = ppar;
5810                 while (par && (par->layout == layout)
5811                        && (par->depth == depth)) {
5812                         par->pextra_type = type;
5813                         par->pextra_width = width;
5814                         par->pextra_widthp = widthp;
5815                         par = par->NextAfterFootnote();
5816                         if (par && (par->depth > depth))
5817                                 par->SetPExtraType(type, width, widthp);
5818                         while (par && ((par->depth > depth) || par->IsDummy()))
5819                                 par = par->NextAfterFootnote();
5820                 }
5821         }
5822 }
5823
5824
5825 void LyXParagraph::UnsetPExtraType()
5826 {
5827         if (pextra_type == PEXTRA_NONE)
5828                 return;
5829     
5830         pextra_type = PEXTRA_NONE;
5831         pextra_width.clear();
5832         pextra_widthp.clear();
5833
5834         if (textclasslist.Style(current_view->buffer()->params.textclass, 
5835                                 layout).isEnvironment()) {
5836                 LyXParagraph
5837                         * par = this,
5838                         * ppar = par;
5839
5840                 while (par && (par->layout == layout)
5841                        && (par->depth == depth)) {
5842                         ppar = par;
5843                         par = par->Previous();
5844                         if (par)
5845                                 par = par->FirstPhysicalPar();
5846                         while (par && par->depth > depth) {
5847                                 par = par->Previous();
5848                                 if (par)
5849                                         par = par->FirstPhysicalPar();
5850                         }
5851                 }
5852                 par = ppar;
5853                 while (par && (par->layout == layout)
5854                        && (par->depth == depth)) {
5855                         par->pextra_type = PEXTRA_NONE;
5856                         par->pextra_width.clear();
5857                         par->pextra_widthp.clear();
5858                         par = par->NextAfterFootnote();
5859                         if (par && (par->depth > depth))
5860                                 par->UnsetPExtraType();
5861                         while (par && ((par->depth > depth) || par->IsDummy()))
5862                                 par = par->NextAfterFootnote();
5863                 }
5864         }
5865 }
5866
5867
5868 bool LyXParagraph::IsHfill(size_type pos) const
5869 {
5870         return IsHfillChar(GetChar(pos));
5871 }
5872
5873
5874 bool LyXParagraph::IsInset(size_type pos) const
5875 {
5876         return IsInsetChar(GetChar(pos));
5877 }
5878
5879
5880 bool LyXParagraph::IsFloat(size_type pos) const
5881 {
5882         return IsFloatChar(GetChar(pos));
5883 }
5884
5885
5886 bool LyXParagraph::IsNewline(size_type pos) const
5887 {
5888         bool tmp = false;
5889         if (pos >= 0)
5890                 tmp = IsNewlineChar(GetChar(pos));
5891         return tmp;
5892 }
5893
5894
5895 bool LyXParagraph::IsSeparator(size_type pos) const
5896 {
5897         return IsSeparatorChar(GetChar(pos));
5898 }
5899
5900
5901 bool LyXParagraph::IsLineSeparator(size_type pos) const
5902 {
5903         return IsLineSeparatorChar(GetChar(pos));
5904 }
5905
5906
5907 bool LyXParagraph::IsKomma(size_type pos) const
5908 {
5909         return IsKommaChar(GetChar(pos));
5910 }
5911
5912
5913 /// Used by the spellchecker
5914 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
5915 {
5916         unsigned char c = GetChar(pos);
5917         if (IsLetterChar(c))
5918                 return true;
5919         // '\0' is not a letter, allthough every string contains "" (below)
5920         if( c == '\0')
5921                 return false;
5922         // We want to pass the ' and escape chars to ispell
5923         string extra = lyxrc->isp_esc_chars + '\'';
5924         char ch[2];
5925         ch[0] = c;
5926         ch[1] = 0;
5927         return contains(extra, ch);
5928 }
5929  
5930  
5931 bool LyXParagraph::IsWord(size_type pos ) const
5932 {
5933         return IsWordChar(GetChar(pos)) ;
5934 }
5935
5936
5937 LyXDirection LyXParagraph::getParDirection() const
5938 {
5939         if (!lyxrc->rtl_support || table)
5940                 return LYX_DIR_LEFT_TO_RIGHT;
5941
5942         if (size() > 0)
5943                 return (getFont(0).direction() ==  LyXFont::RTL_DIR)
5944                         ? LYX_DIR_RIGHT_TO_LEFT : LYX_DIR_LEFT_TO_RIGHT;
5945         else
5946                 return current_view->buffer()->params.getDocumentDirection();
5947 }
5948
5949
5950 LyXDirection
5951 LyXParagraph::getLetterDirection(LyXParagraph::size_type pos) const
5952 {
5953         if (!lyxrc->rtl_support)
5954                 return LYX_DIR_LEFT_TO_RIGHT;
5955
5956         LyXDirection direction = getFont(pos).getFontDirection();
5957         if (IsLineSeparator(pos) && 0 < pos && pos < Last() - 1
5958             && !IsLineSeparator(pos + 1)
5959             && !(table && IsNewline(pos + 1))
5960             && (getFont(pos - 1).getFontDirection() != direction
5961                 || getFont(pos + 1).getFontDirection() != direction))
5962                 return getParDirection();
5963         else
5964                 return direction;
5965 }