]> git.lyx.org Git - lyx.git/blob - src/paragraph.C
cb8fca6d47390e29b7708d5280a8b8ed638e4566
[lyx.git] / src / paragraph.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2000 The LyX Team. 
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation "lyxparagraph.h"
15 #endif
16
17 #include <algorithm>
18 #include <fstream>
19 using std::fstream;
20 using std::ios;
21
22 #include "lyxparagraph.h"
23 #include "support/textutils.h"
24 #include "lyxrc.h"
25 #include "layout.h"
26 #include "tex-strings.h"
27 #include "bufferparams.h"
28 #include "support/FileInfo.h"
29 #include "support/LAssert.h"
30 #include "debug.h"
31 #include "LaTeXFeatures.h"
32 #include "insets/insetinclude.h"
33 #include "insets/insetbib.h"
34 #include "support/filetools.h"
35 #include "lyx_gui_misc.h"
36 #include "texrow.h"
37 #include "support/lyxmanip.h"
38
39
40 int tex_code_break_column = 72;  // needs non-zero initialization. set later.
41 // this is a bad idea, but how can LyXParagraph find its buffer to get
42 // parameters? (JMarc)
43 extern BufferView * current_view;
44
45
46 // ale970405
47 extern string bibitemWidthest(Painter &);
48
49 // this is a minibuffer
50 static char minibuffer_char;
51 static LyXFont minibuffer_font;
52 static Inset * minibuffer_inset;
53
54
55 // Initialization of the counter for the paragraph id's,
56 // declared in lyxparagraph.h
57 unsigned int LyXParagraph::paragraph_id = 0;
58
59
60 LyXParagraph::LyXParagraph()
61 {
62         text.reserve(500); // is this number too big?
63
64         for (int i = 0; i < 10; ++i) setCounter(i , 0);
65         appendix = false;
66         enumdepth = 0;
67         itemdepth = 0;
68         next = 0;
69         previous = 0;
70         footnoteflag = LyXParagraph::NO_FOOTNOTE;
71         footnotekind = LyXParagraph::FOOTNOTE; // should not be needed
72         
73         align = LYX_ALIGN_BLOCK;
74
75         /* table stuff -- begin*/ 
76         table = 0;
77         /* table stuff -- end*/ 
78         id_ = paragraph_id++;
79         bibkey = 0; // ale970302
80         Clear();
81 }
82
83
84 // This konstruktor inserts the new paragraph in a list.
85 LyXParagraph::LyXParagraph(LyXParagraph * par)
86 {
87         text.reserve(500);
88         par->text.resize(par->text.size());
89
90         for (int i = 0; i < 10; ++i) setCounter(i, 0);
91         appendix = false;
92         enumdepth = 0;
93         itemdepth = 0;
94         // double linked list begin
95         next = par->next;
96         if (next)
97                 next->previous = this;
98         previous = par;
99         previous->next = this;
100         // end
101         footnoteflag = LyXParagraph::NO_FOOTNOTE;
102         footnotekind = LyXParagraph::FOOTNOTE;
103         
104         /* table stuff -- begin*/ 
105         table = 0;
106         /* table stuff -- end*/ 
107         id_ = paragraph_id++;
108
109         bibkey = 0; // ale970302        
110     
111         Clear();
112 }
113
114
115 void LyXParagraph::writeFile(ostream & os, BufferParams const & params,
116                              char footflag, char dth) const
117 {
118         LyXFont font1, font2;
119         int column = 0;
120         int h = 0;
121         char c = 0;
122
123         if (footnoteflag != LyXParagraph::NO_FOOTNOTE
124             || !previous
125             || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
126                 
127                 // The beginning or the end of a footnote environment?
128                 if (footflag != footnoteflag) {
129                         footflag = footnoteflag;
130                         if (footflag) {
131                                 os << "\n\\begin_float "
132                                    << string_footnotekinds[footnotekind]
133                                    << " ";
134                         } else {
135                                 os << "\n\\end_float ";
136                         }
137                 }
138
139                 // The beginning or end of a deeper (i.e. nested) area?
140                 if (dth != depth) {
141                         if (depth > dth) {
142                                 while (depth > dth) {
143                                         os << "\n\\begin_deeper ";
144                                         ++dth;
145                                 }
146                         } else {
147                                 while (depth < dth) {
148                                         os << "\n\\end_deeper ";
149                                         --dth;
150                                 }
151                         }
152                 }
153
154                 // First write the layout
155                 os << "\n\\layout "
156                    << textclasslist.NameOfLayout(params.textclass, layout)
157                    << "\n";
158
159                 // Maybe some vertical spaces.
160                 if (added_space_top.kind() != VSpace::NONE)
161                         os << "\\added_space_top "
162                            << added_space_top.asLyXCommand() << " ";
163                 if (added_space_bottom.kind() != VSpace::NONE)
164                         os << "\\added_space_bottom "
165                            << added_space_bottom.asLyXCommand() << " ";
166                         
167                 // The labelwidth string used in lists.
168                 if (!labelwidthstring.empty())
169                         os << "\\labelwidthstring "
170                            << labelwidthstring << '\n';
171
172                 // Lines above or below?
173                 if (line_top)
174                         os << "\\line_top ";
175                 if (line_bottom)
176                         os << "\\line_bottom ";
177
178                 // Pagebreaks above or below?
179                 if (pagebreak_top)
180                         os << "\\pagebreak_top ";
181                 if (pagebreak_bottom)
182                         os << "\\pagebreak_bottom ";
183                         
184                 // Start of appendix?
185                 if (start_of_appendix)
186                         os << "\\start_of_appendix ";
187
188                 // Noindent?
189                 if (noindent)
190                         os << "\\noindent ";
191                         
192                 // Alignment?
193                 if (align != LYX_ALIGN_LAYOUT) {
194                         switch (align) {
195                         case LYX_ALIGN_LEFT: h = 1; break;
196                         case LYX_ALIGN_RIGHT: h = 2; break;
197                         case LYX_ALIGN_CENTER: h = 3; break;
198                         default: h = 0; break;
199                         }
200                         os << "\\align " << string_align[h] << " ";
201                 }
202                 if (pextra_type != PEXTRA_NONE) {
203                         os << "\\pextra_type " << pextra_type;
204                         if (pextra_type == PEXTRA_MINIPAGE) {
205                                 os << " \\pextra_alignment "
206                                    << pextra_alignment;
207                                 if (pextra_hfill)
208                                         os << " \\pextra_hfill "
209                                            << pextra_hfill;
210                                 if (pextra_start_minipage)
211                                         os << " \\pextra_start_minipage "
212                                            << pextra_start_minipage;
213                         }
214                         if (!pextra_width.empty()) {
215                                 os << " \\pextra_width "
216                                    << VSpace(pextra_width).asLyXCommand();
217                         } else if (!pextra_widthp.empty()) {
218                                 os << " \\pextra_widthp "
219                                    << pextra_widthp;
220                         }
221                         os << '\n';
222                 }
223         } else {
224                 // Dummy layout. This means that a footnote ended.
225                 os << "\n\\end_float ";
226                 footflag = LyXParagraph::NO_FOOTNOTE;
227         }
228                 
229         // It might be a table.
230         if (table){
231                 os << "\\LyXTable\n";
232                 table->Write(os);
233         }
234
235         // bibitem  ale970302
236         if (bibkey)
237                 bibkey->Write(os);
238
239         font1 = LyXFont(LyXFont::ALL_INHERIT,params.language_info);
240
241         column = 0;
242         for (size_type i = 0; i < size(); ++i) {
243                 if (!i) {
244                         os << "\n";
245                         column = 0;
246                 }
247                 
248                 // Write font changes
249                 font2 = GetFontSettings(i);
250                 if (font2 != font1) {
251                         font2.lyxWriteChanges(font1, os);
252                         column = 0;
253                         font1 = font2;
254                 }
255
256                 c = GetChar(i);
257                 switch (c) {
258                 case META_INSET:
259                 {
260                         Inset const * inset = GetInset(i);
261                         if (inset)
262                                 if (inset->DirectWrite()) {
263                                         // international char, let it write
264                                         // code directly so it's shorter in
265                                         // the file
266                                         inset->Write(os);
267                                 } else {
268                                         os << "\n\\begin_inset ";
269                                         inset->Write(os);
270                                         os << "\n\\end_inset \n\n";
271                                         column = 0;
272                                 }
273                 }
274                 break;
275                 case META_NEWLINE: 
276                         os << "\n\\newline \n";
277                         column = 0;
278                         break;
279                 case META_HFILL: 
280                         os << "\n\\hfill \n";
281                         column = 0;
282                         break;
283 #if 0
284                 case META_PROTECTED_SEPARATOR: 
285                         os << "\n\\protected_separator \n";
286                         column = 0;
287                         break;
288 #endif
289                 case '\\':
290                         os << "\n\\backslash \n";
291                         column = 0;
292                         break;
293                 case '.':
294                         if (i + 1 < size() && GetChar(i + 1) == ' ') {
295                                 os << ".\n";
296                                 column = 0;
297                         } else
298                                 os << ".";
299                         break;
300                 default:
301                         if ((column > 70 && c == ' ')
302                             || column > 79) {
303                                 os << "\n";
304                                 column = 0;
305                         }
306                         // this check is to amend a bug. LyX sometimes
307                         // inserts '\0' this could cause problems.
308                         if (c != '\0')
309                                 os << c;
310                         else
311                                 lyxerr << "ERROR (LyXParagraph::writeFile):"
312                                         " NULL char in structure." << endl;
313                         ++column;
314                         break;
315                 }
316         }
317
318         // now write the next paragraph
319         if (next)
320                 next->writeFile(os, params, footflag, dth);
321 }
322
323
324 void LyXParagraph::validate(LaTeXFeatures & features) const
325 {
326         // this will be useful later
327         LyXLayout const & layout =
328                 textclasslist.Style(current_view->buffer()->params.textclass, 
329                                     GetLayout());
330         
331         // check the params.
332         if (line_top || line_bottom)
333                 features.lyxline = true;
334         
335         // then the layouts
336         features.layout[GetLayout()] = true;
337
338         // then the fonts
339         Language const * doc_language = current_view->buffer()->params.language_info;
340         for (FontList::const_iterator cit = fontlist.begin();
341              cit != fontlist.end(); ++cit) {
342                 if ((*cit).font.noun() == LyXFont::ON) {
343                         lyxerr[Debug::LATEX] << "font.noun: "
344                                              << (*cit).font.noun()
345                                              << endl;
346                         features.noun = true;
347                         lyxerr[Debug::LATEX] << "Noun enabled. Font: "
348                                              << (*cit).font.stateText()
349                                              << endl;
350                 }
351                 switch ((*cit).font.color()) {
352                 case LColor::none:
353                 case LColor::inherit:
354                 case LColor::ignore:
355                         break;
356                 default:
357                         features.color = true;
358                         lyxerr[Debug::LATEX] << "Color enabled. Font: "
359                                              << (*cit).font.stateText()
360                                              << endl;
361                 }
362                 Language const * language = (*cit).font.language();
363                 if (language != doc_language && language != default_language) {
364                         features.UsedLanguages.insert(language);
365                         lyxerr[Debug::LATEX] << "Found language "
366                                              << language->lang << endl;
367                 }               
368         }
369
370         // then the insets
371         for (InsetList::const_iterator cit = insetlist.begin();
372              cit != insetlist.end(); ++cit) {
373                 if ((*cit).inset)
374                         (*cit).inset->Validate(features);
375         }
376
377         if (table && table->IsLongTable())
378                 features.longtable = true;
379         if (pextra_type == PEXTRA_INDENT)
380                 features.LyXParagraphIndent = true;
381         if (pextra_type == PEXTRA_FLOATFLT)
382                 features.floatflt = true;
383         if (layout.needprotect 
384             && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
385                 features.NeedLyXFootnoteCode = true;
386         if ((current_view->buffer()->params.paragraph_separation == BufferParams::PARSEP_INDENT) &&
387             (pextra_type == LyXParagraph::PEXTRA_MINIPAGE))
388                 features.NeedLyXMinipageIndent = true;
389         if (table && table->NeedRotating())
390                 features.rotating = true;
391         if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
392                 features.algorithm = true;
393 }
394
395
396 // First few functions needed for cut and paste and paragraph breaking.
397 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos) const
398 {
399         minibuffer_char = GetChar(pos);
400         minibuffer_font = GetFontSettings(pos);
401         minibuffer_inset = 0;
402         if (minibuffer_char == LyXParagraph::META_INSET) {
403                 if (GetInset(pos)) {
404                         minibuffer_inset = GetInset(pos)->Clone();
405                 } else {
406                         minibuffer_inset = 0;
407                         minibuffer_char = ' ';
408                         // This reflects what GetInset() does (ARRae)
409                 }
410         }
411 }
412
413
414 void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos)
415 {
416         minibuffer_char = GetChar(pos);
417         minibuffer_font = GetFontSettings(pos);
418         minibuffer_inset = 0;
419         if (minibuffer_char == LyXParagraph::META_INSET) {
420                 if (GetInset(pos)) {
421                         minibuffer_inset = GetInset(pos);
422                         // This is a little hack since I want exactly
423                         // the inset, not just a clone. Otherwise
424                         // the inset would be deleted when calling Erase(pos)
425                         // find the entry
426                         for (InsetList::iterator it = insetlist.begin();
427                              it != insetlist.end(); ++it) {
428                                 if ((*it).pos == pos) {
429                                         (*it).inset = 0;
430                                         break;
431                                 }
432                                         
433                         }
434                 } else {
435                         minibuffer_inset = 0;
436                         minibuffer_char = ' ';
437                         // This reflects what GetInset() does (ARRae)
438                 }
439
440         }
441
442         // Erase(pos); now the caller is responsible for that.
443 }
444
445
446 void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
447 {
448         InsertChar(pos, minibuffer_char);
449         SetFont(pos, minibuffer_font);
450         if (minibuffer_char == LyXParagraph::META_INSET)
451                 InsertInset(pos, minibuffer_inset);
452 }
453
454 // end of minibuffer
455
456
457
458 void LyXParagraph::Clear()
459 {
460         line_top = false;
461         line_bottom = false;
462    
463         pagebreak_top = false;
464         pagebreak_bottom = false;
465
466         added_space_top = VSpace(VSpace::NONE);
467         added_space_bottom = VSpace(VSpace::NONE);
468
469         align = LYX_ALIGN_LAYOUT;
470         depth = 0;
471         noindent = false;
472
473         pextra_type = PEXTRA_NONE;
474         pextra_width.clear();
475         pextra_widthp.clear();
476         pextra_alignment = MINIPAGE_ALIGN_TOP;
477         pextra_hfill = false;
478         pextra_start_minipage = false;
479
480         labelstring.clear();
481         labelwidthstring.clear();
482         layout = 0;
483         bibkey = 0;
484         
485         start_of_appendix = false;
486 }
487
488
489 // the destructor removes the new paragraph from the list
490 LyXParagraph::~LyXParagraph()
491 {
492         if (previous)
493                 previous->next = next;
494         if (next)
495                 next->previous = previous;
496
497         for (InsetList::iterator it = insetlist.begin();
498              it != insetlist.end(); ++it) {
499                 delete (*it).inset;
500         }
501
502         /* table stuff -- begin*/ 
503         delete table;
504         /* table stuff -- end*/ 
505
506         // ale970302
507         delete bibkey;
508 }
509
510
511 void LyXParagraph::Erase(LyXParagraph::size_type pos)
512 {
513         // > because last is the next unused position, and you can 
514         // use it if you want
515         if (pos > size()) {
516                 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
517                         NextAfterFootnote()->Erase(pos - text.size() - 1);
518                 else 
519                         lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
520                                 "position does not exist." << endl;
521                 return;
522         }
523         if (pos < size()) { // last is free for insertation, but should be empty
524                 // if it is an inset, delete the inset entry 
525                 if (text[pos] == LyXParagraph::META_INSET) {
526                         // find the entry
527                         for (InsetList::iterator it = insetlist.begin();
528                              it != insetlist.end(); ++it) {
529                                 if ((*it).pos == pos) {
530                                         delete (*it).inset;
531                                         insetlist.erase(it);
532                                         break;
533                                 }
534                         }
535                 }
536                 text.erase(text.begin() + pos);
537                 // Erase entries in the tables.
538                 for (FontList::iterator it = fontlist.begin();
539                      it != fontlist.end(); ++it) {
540                         if (pos >= (*it).pos && pos <= (*it).pos_end) {
541                                 if ((*it).pos == (*it).pos_end) {
542                                         // If it is a multi-character font
543                                         // entry, we just make it smaller
544                                         // (see update below), otherwise we
545                                         // should delete it.
546                                         fontlist.erase(it);
547                                         break;
548                                 }
549                         }
550                 }
551                 // Update all other entries.
552                 for (FontList::iterator it = fontlist.begin();
553                      it != fontlist.end(); ++it) {
554                         if ((*it).pos > pos)
555                                 (*it).pos--;
556                         if ((*it).pos_end >= pos)
557                                 (*it).pos_end--;
558                 }
559
560                 // Update the inset table.
561                 for (InsetList::iterator it = insetlist.begin();
562                      it != insetlist.end(); ++it) {
563                         if ((*it).pos > pos)
564                                 (*it).pos--;
565                 }
566         } else {
567                 lyxerr << "ERROR (LyXParagraph::Erase): "
568                         "can't erase non-existant char." << endl;
569         }
570 }
571
572
573 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
574 {
575         // > because last is the next unused position, and you can 
576         // use it if you want
577         if (pos > size()) {
578                 if (next
579                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
580                         NextAfterFootnote()->InsertChar(pos - text.size() - 1,
581                                                         c);
582                 else 
583                         lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
584                                 "position does not exist." << endl;
585                 return;
586         }
587         text.insert(text.begin() + pos, c);
588         // Update the font table.
589         for (FontList::iterator it = fontlist.begin();
590              it != fontlist.end(); ++it) {
591                 if ((*it).pos >= pos)
592                         (*it).pos++;
593                 if ((*it).pos_end >= pos)
594                         (*it).pos_end++;
595         }
596    
597         // Update the inset table.
598         for (InsetList::iterator it = insetlist.begin();
599              it != insetlist.end(); ++it) {
600                 if ((*it).pos >= pos)
601                         (*it).pos++;
602         }
603 }
604
605
606 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
607                                Inset * inset)
608 {
609         // > because last is the next unused position, and you can 
610         // use it if you want
611         if (pos > size()) {
612                 if (next
613                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
614                         NextAfterFootnote()
615                                 ->InsertInset(pos - text.size() - 1, inset);
616                 else 
617                         lyxerr << "ERROR (LyXParagraph::InsertInset): " 
618                                 "position does not exist: " << pos << endl;
619                 return;
620         }
621         if (text[pos] != LyXParagraph::META_INSET) {
622                 lyxerr << "ERROR (LyXParagraph::InsertInset): "
623                         "there is no LyXParagraph::META_INSET" << endl;
624                 return;
625         }
626
627         if (inset) {
628                 // Add a new entry in the inset table.
629                 InsetList::iterator it =
630                         insetlist.insert(insetlist.begin(), InsetTable());
631                 (*it).inset = inset;
632                 (*it).pos = pos;
633         }
634 }
635
636
637 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
638 {
639         if (pos >= size()) {
640                 if (next
641                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
642                         return NextAfterFootnote()
643                                 ->GetInset(pos - text.size() - 1);
644                 else { 
645                         lyxerr << "ERROR (LyXParagraph::GetInset): "
646                                 "position does not exist: "
647                                << pos << endl;
648                 }
649                 return 0;
650         }
651         // Find the inset.
652         for (InsetList::iterator it = insetlist.begin();
653              it != insetlist.end(); ++it) {
654                 if ((*it).pos == pos) {
655                         return (*it).inset;
656                 }
657         }
658         lyxerr << "ERROR (LyXParagraph::GetInset): "
659                 "Inset does not exist: " << pos << endl;
660         text[pos] = ' '; // WHY!!! does this set the pos to ' '????
661         // Did this commenting out introduce a bug? So far I have not
662         // see any, please enlighten me. (Lgb)
663         // My guess is that since the inset does not exist, we might
664         // as well replace it with a space to prevent craches. (Asger)
665         return 0;
666 }
667
668
669 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
670 {
671         if (pos >= size()) {
672                 if (next
673                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
674                         return NextAfterFootnote()
675                                 ->GetInset(pos - text.size() - 1);
676                 else { 
677                         lyxerr << "ERROR (LyXParagraph::GetInset): "
678                                 "position does not exist: "
679                                << pos << endl;
680                 }
681                 return 0;
682         }
683         // Find the inset.
684         for (InsetList::const_iterator cit = insetlist.begin();
685              cit != insetlist.end(); ++cit) {
686                 if ((*cit).pos == pos) {
687                         return (*cit).inset;
688                 }
689         }
690         lyxerr << "ERROR (LyXParagraph::GetInset): "
691                 "Inset does not exist: " << pos << endl;
692         //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
693         // Did this commenting out introduce a bug? So far I have not
694         // see any, please enlighten me. (Lgb)
695         // My guess is that since the inset does not exist, we might
696         // as well replace it with a space to prevent craches. (Asger)
697         return 0;
698 }
699
700
701 // Gets uninstantiated font setting at position.
702 // Optimized after profiling. (Asger)
703 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos) const
704 {
705         if (pos < size()) {
706 #ifdef SORTED_FONT_LIST
707                 for (FontList::const_iterator cit = fontlist.begin();
708                      cit != fontlist.end() && pos <= (*cit).pos_end; ++cit)
709                         if (pos >= (*cit).pos)
710                                 return (*cit).font;
711 #else
712                 for (FontList::const_iterator cit = fontlist.begin();
713                      cit != fontlist.end(); ++cit)
714                         if (pos >= (*cit).pos && pos <= (*cit).pos_end)
715                                 return (*cit).font;
716 #endif
717         }
718         // > because last is the next unused position, and you can 
719         // use it if you want
720         else if (pos > size()) {
721                 if (next
722                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
723                         return NextAfterFootnote()
724                                 ->GetFontSettings(pos - text.size() - 1);
725                 else {
726                         // Why is it an error to ask for the font of a
727                         // position that does not exist? Would it be
728                         // enough for this to be enabled on debug?
729                         // We want strict error checking, but it's ok to only
730                         // have it when debugging. (Asger)
731                         lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
732                                 "position does not exist. "
733                                << pos << " (" << static_cast<int>(pos)
734                                << ")" << endl;
735                 }
736         } else if (pos > 0) {
737                 return GetFontSettings(pos - 1);
738         } else // pos = size() = 0
739                 return LyXFont(LyXFont::ALL_INHERIT,getParLanguage());
740
741         return LyXFont(LyXFont::ALL_INHERIT);
742 }
743
744 // Gets uninstantiated font setting at position 0
745 LyXFont LyXParagraph::GetFirstFontSettings() const
746 {
747         if (size() > 0) {
748 #ifdef SORTED_FONT_LIST
749                 if (!fontlist.empty() && fontlist.front().pos == 0)
750                         return fontlist.front().font;
751 #else
752                 for (FontList::const_iterator cit = fontlist.begin();
753                      cit != fontlist.end(); ++cit)
754                         if (0 >= (*cit).pos && 0 <= (*cit).pos_end)
755                                 return (*cit).font;
756 #endif
757         }
758         return LyXFont(LyXFont::ALL_INHERIT);
759 }
760
761 // Gets the fully instantiated font at a given position in a paragraph
762 // This is basically the same function as LyXText::GetFont() in text2.C.
763 // The difference is that this one is used for generating the LaTeX file,
764 // and thus cosmetic "improvements" are disallowed: This has to deliver
765 // the true picture of the buffer. (Asger)
766 // If position is -1, we get the layout font of the paragraph.
767 // If position is -2, we get the font of the manual label of the paragraph.
768 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos) const
769 {
770         LyXFont tmpfont;
771         LyXLayout const & layout =
772                 textclasslist.Style(current_view->buffer()->params.textclass, 
773                                     GetLayout());
774         LyXParagraph::size_type main_body = 0;
775         if (layout.labeltype == LABEL_MANUAL)
776                 main_body = BeginningOfMainBody();
777
778         if (pos >= 0){
779                 LyXFont layoutfont;
780                 if (pos < main_body)
781                         layoutfont = layout.labelfont;
782                 else
783                         layoutfont = layout.font;
784                 tmpfont = GetFontSettings(pos);
785                 tmpfont.realize(layoutfont);
786         } else {
787                 // process layoutfont for pos == -1 and labelfont for pos < -1
788                 if (pos == -1)
789                         tmpfont = layout.font;
790                 else
791                         tmpfont = layout.labelfont;
792                 tmpfont.setLanguage(getParLanguage());
793         }
794
795         // check for environment font information
796         char par_depth = GetDepth();
797         LyXParagraph const * par = this;
798         while (par && par_depth && !tmpfont.resolved()) {
799                 par = par->DepthHook(par_depth - 1);
800                 if (par) {
801                         tmpfont.realize(textclasslist.
802                                         Style(current_view->buffer()->params.textclass,
803                                               par->GetLayout()).font);
804                         par_depth = par->GetDepth();
805                 }
806         }
807
808         tmpfont.realize(textclasslist
809                         .TextClass(current_view->buffer()->params.textclass)
810                         .defaultfont());
811         return tmpfont;
812 }
813
814
815 /// Returns the height of the highest font in range
816 LyXFont::FONT_SIZE
817 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
818                                  LyXParagraph::size_type endpos) const
819 {
820         LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
821         for (FontList::const_iterator cit = fontlist.begin();
822              cit != fontlist.end(); ++cit) {
823                 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
824                         LyXFont::FONT_SIZE size = (*cit).font.size();
825                         if (size > maxsize && size <= LyXFont::SIZE_HUGER)
826                                 maxsize = size;
827                 }
828         }
829         return maxsize;
830 }
831
832
833 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
834 {
835         Assert(pos >= 0);
836
837         if (pos < size()) {
838                 return text[pos];
839         }
840         // > because last is the next unused position, and you can 
841         // use it if you want
842         else if (pos > size()) {
843                 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) 
844                         return NextAfterFootnote()
845                                 ->GetChar(pos - text.size() - 1);
846                 else {
847                         lyxerr << "ERROR (LyXParagraph::GetChar): "
848                                 "position does not exist."
849                                << pos << " (" << static_cast<int>(pos)
850                                << ")\n";
851                         // Assert(false); // This triggers sometimes...
852                         // Why?
853                 }
854                 return '\0';
855         } else {
856                 // We should have a footnote environment.
857                 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
858                         // Notice that LyX does request the
859                         // last char from time to time. (Asger)
860                         //lyxerr << "ERROR (LyXParagraph::GetChar): "
861                         //      "expected footnote." << endl;
862                         return '\0';
863                 }
864                 switch (next->footnotekind) {
865                 case LyXParagraph::FOOTNOTE:
866                         return LyXParagraph::META_FOOTNOTE;
867                 case LyXParagraph::MARGIN:
868                         return LyXParagraph::META_MARGIN;
869                 case LyXParagraph::FIG:
870                 case LyXParagraph::WIDE_FIG:
871                         return LyXParagraph::META_FIG;
872                 case LyXParagraph::TAB:
873                 case LyXParagraph::WIDE_TAB:
874                         return LyXParagraph::META_TAB;
875                 case LyXParagraph::ALGORITHM:
876                         return LyXParagraph::META_ALGORITHM;
877                 }
878                 return '\0'; // to shut up gcc
879         }
880 }
881
882
883 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
884 {
885         Assert(pos >= 0);
886
887         if (pos < size()) {
888                 return text[pos];
889         }
890         // > because last is the next unused position, and you can 
891         // use it if you want
892         else if (pos > size()) {
893                 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) 
894                         return NextAfterFootnote()
895                                 ->GetChar(pos - text.size() - 1);
896                 else {
897                         lyxerr << "ERROR (LyXParagraph::GetChar const): "
898                                 "position does not exist."
899                                << pos << " (" << static_cast<int>(pos)
900                                << ")\n";
901                         Assert(false);
902                 }
903                 return '\0';
904         } else {
905                 // We should have a footnote environment.
906                 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
907                         // Notice that LyX does request the
908                         // last char from time to time. (Asger)
909                         //lyxerr << "ERROR (LyXParagraph::GetChar): "
910                         //      "expected footnote." << endl;
911                         return '\0';
912                 }
913                 switch (next->footnotekind) {
914                 case LyXParagraph::FOOTNOTE:
915                         return LyXParagraph::META_FOOTNOTE;
916                 case LyXParagraph::MARGIN:
917                         return LyXParagraph::META_MARGIN;
918                 case LyXParagraph::FIG:
919                 case LyXParagraph::WIDE_FIG:
920                         return LyXParagraph::META_FIG;
921                 case LyXParagraph::TAB:
922                 case LyXParagraph::WIDE_TAB:
923                         return LyXParagraph::META_TAB;
924                 case LyXParagraph::ALGORITHM:
925                         return LyXParagraph::META_ALGORITHM;
926                 }
927                 return '\0'; // to shut up gcc
928         }
929 }
930
931
932 // return an string of the current word, and the end of the word in lastpos.
933 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
934 {
935         Assert(lastpos>=0);
936
937         // the current word is defined as starting at the first character
938         // from the immediate left of lastpospos which meets the definition
939         // of IsLetter(), continuing to the last character to the right
940         // of this meeting IsLetter.
941
942         string theword;
943
944         // grab a word
945                 
946         // move back until we have a letter
947
948         //there's no real reason to have firstpos & lastpos as
949         //separate variables as this is written, but maybe someon
950         // will want to return firstpos in the future.
951
952         //since someone might have typed a punctuation first
953         int firstpos = lastpos;
954         
955         while ((firstpos >= 0) && !IsLetter(firstpos))
956                 --firstpos;
957
958         // now find the beginning by looking for a nonletter
959         
960         while ((firstpos>= 0) && IsLetter(firstpos))
961                 --firstpos;
962
963         // the above is now pointing to the preceeding non-letter
964         ++firstpos;
965         lastpos = firstpos;
966
967         // so copy characters into theword  until we get a nonletter
968         // note that this can easily exceed lastpos, wich means
969         // that if used in the middle of a word, the whole word
970         // is included
971
972         while (IsLetter(lastpos)) theword += GetChar(lastpos++);
973         
974         return theword;
975
976 }
977
978  
979 LyXParagraph::size_type LyXParagraph::Last() const
980 {
981         if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
982                 return text.size() + NextAfterFootnote()->Last() + 1;
983         // the 1 is the symbol
984         // for the footnote
985         else
986                 return text.size();
987 }
988
989
990 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
991 {
992         // > because last is the next unused position, and you can 
993         // use it if you want
994         if (pos > size()) {
995                 if (next
996                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
997                         return NextAfterFootnote()
998                                 ->ParFromPos(pos - text.size() - 1);
999                 else 
1000                         lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1001                                 "position does not exist." << endl;
1002                 return this;
1003         } else
1004                 return this;
1005 }
1006
1007
1008 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
1009 {
1010         // > because last is the next unused position, and you can 
1011         // use it if you want
1012         if (pos > size()) {
1013                 if (next
1014                     && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
1015                         return NextAfterFootnote()
1016                                 ->PositionInParFromPos(pos - text.size() - 1);
1017                 else 
1018                         lyxerr <<
1019                                 "ERROR (LyXParagraph::PositionInParFromPos): "
1020                                 "position does not exist." << endl;
1021                 return pos;
1022         }
1023         else
1024                 return pos;
1025 }
1026
1027
1028 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1029                            LyXFont const & font)
1030 {
1031         // > because last is the next unused position, and you can 
1032         // use it if you want
1033         if (pos > size()) {
1034                 if (next &&
1035                     next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1036                         NextAfterFootnote()->SetFont(pos - text.size() - 1,
1037                                                      font);
1038                 } else {
1039                         lyxerr << "ERROR (LyXParagraph::SetFont): "
1040                                 "position does not exist." << endl;
1041                 }
1042                 return;
1043         }
1044         LyXFont patternfont(LyXFont::ALL_INHERIT);
1045
1046         // First, reduce font against layout/label font
1047         // Update: The SetCharFont() routine in text2.C already
1048         // reduces font, so we don't need to do that here. (Asger)
1049         // No need to simplify this because it will disappear
1050         // in a new kernel. (Asger)
1051         // Next search font table
1052         FontList::iterator tmp = fontlist.begin();
1053         for (; tmp != fontlist.end(); ++tmp) {
1054                 if (pos >= (*tmp).pos && pos <= (*tmp).pos_end) {
1055                         break;
1056                 }
1057         }
1058         if (tmp == fontlist.end()) { // !found
1059                 // if we did not find a font entry, but if the font at hand
1060                 // is the same as default, we just forget it
1061                 if (font == patternfont) return;
1062
1063                 // ok, we did not find a font entry. But maybe there is exactly
1064                 // the needed font ientry one position left
1065                 FontList::iterator tmp2 = fontlist.begin();
1066                 for (; tmp2 != fontlist.end(); ++tmp2) {
1067                         if (pos - 1 >= (*tmp2).pos
1068                             && pos - 1 <= (*tmp2).pos_end)
1069                                 break;
1070                 }
1071                 if (tmp2 != fontlist.end()) {
1072                         // ok there is one, maybe it is exactly
1073                         // the needed font
1074                         if ((*tmp2).font == font) {
1075                                 // put the position under the font
1076                                 (*tmp2).pos_end++;
1077                                 return;
1078                         }
1079                 }
1080                 // Add a new entry in the
1081                 // fontlist for the position
1082                 FontTable ft;
1083                 ft.pos = pos;
1084                 ft.pos_end = pos;
1085                 ft.font = font; // or patternfont
1086                 // It seems that using font instead of patternfont here
1087                 // fixes all the problems. This also surfaces a "bug" in
1088                 // the old code.
1089                 fontlist.insert(fontlist.begin(), ft);
1090         } else if ((*tmp).pos != (*tmp).pos_end) { // we found a font entry. maybe we have to split it and create a new one.
1091
1092 // more than one character
1093                 if (pos == (*tmp).pos) {
1094                         // maybe we should enlarge the left fonttable
1095                         FontList::iterator tmp2 = fontlist.begin();
1096                         for (; tmp2 != fontlist.end(); ++tmp2) {
1097                                 if (pos - 1 >= (*tmp2).pos
1098                                     && pos - 1 <= (*tmp2).pos_end)
1099                                         break;
1100                         }
1101                         // Is there is one, and is it exactly
1102                         // the needed font?
1103                         if (tmp2 != fontlist.end() &&
1104                             (*tmp2).font == font) {
1105                                 // Put the position under the font
1106                                 (*tmp2).pos_end++;
1107                                 (*tmp).pos++;
1108                                 return;
1109                         }
1110
1111                         // Add a new entry in the
1112                         // fontlist for the position
1113                         FontTable ft;
1114                         ft.pos = pos + 1;
1115                         ft.pos_end = (*tmp).pos_end;
1116                         ft.font = (*tmp).font;
1117                         (*tmp).pos_end = pos;
1118                         (*tmp).font = font;
1119                         fontlist.insert(fontlist.begin(), ft);
1120                 } else if (pos == (*tmp).pos_end) {
1121                         // Add a new entry in the
1122                         // fontlist for the position
1123                         FontTable ft;
1124                         ft.pos = (*tmp).pos;
1125                         ft.pos_end = (*tmp).pos_end - 1;
1126                         ft.font = (*tmp).font;
1127                         (*tmp).pos = (*tmp).pos_end;
1128                         (*tmp).font = font;
1129                         fontlist.insert(fontlist.begin(), ft);
1130                 } else {
1131                         // Add a new entry in the
1132                         // fontlist for the position
1133                         FontTable ft;
1134                         ft.pos = (*tmp).pos;
1135                         ft.pos_end = pos - 1;
1136                         ft.font = (*tmp).font;
1137                         
1138                         FontTable ft2;
1139                         ft2.pos = pos + 1;
1140                         ft2.pos_end = (*tmp).pos_end;
1141                         ft2.font = (*tmp).font;
1142                         
1143                         (*tmp).pos = pos;
1144                         (*tmp).pos_end = pos;
1145                         (*tmp).font = font;
1146                         
1147                         fontlist.insert(fontlist.begin(), ft);
1148                         fontlist.insert(fontlist.begin(), ft2);
1149                 }
1150         } else {
1151                 (*tmp).font = font;
1152         }
1153 }
1154
1155    
1156 // This function is able to hide closed footnotes.
1157 LyXParagraph * LyXParagraph::Next()
1158 {
1159         if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1160                 LyXParagraph * tmp = next;
1161                 while (tmp
1162                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1163                         tmp = tmp->next;
1164                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1165                         return tmp->Next(); /* there can be more than one
1166                                                footnote in a logical
1167                                                paragraph */
1168                 else
1169                         return next;  // This should never happen!
1170         } else
1171                 return next;
1172 }
1173
1174
1175 LyXParagraph * LyXParagraph::NextAfterFootnote()
1176 {
1177         if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1178                 LyXParagraph * tmp = next;
1179                 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1180                         tmp = tmp->next;
1181                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1182                         return tmp;   /* there can be more than one footnote
1183                                          in a logical paragraph */
1184                 else
1185                         return next;  // This should never happen!
1186         } else
1187                 return next;
1188 }
1189
1190
1191 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1192 {
1193         if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1194                 LyXParagraph * tmp = next;
1195                 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1196                         tmp = tmp->next;
1197                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1198                         return tmp;   /* there can be more than one footnote
1199                                          in a logical paragraph */
1200                 else
1201                         return next;  // This should never happen!
1202         } else
1203                 return next;
1204 }
1205
1206
1207 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1208 {
1209         LyXParagraph * tmp;
1210         if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1211                 tmp = previous;
1212                 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1213                         tmp = tmp->previous;
1214                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1215                         return tmp;    /* there can be more than one footnote
1216                                           in a logical paragraph */
1217                 else
1218                         return previous;  // This should never happen!
1219         } else
1220                 return previous;
1221 }
1222
1223
1224 LyXParagraph * LyXParagraph::LastPhysicalPar()
1225 {
1226         if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1227                 return this;
1228    
1229         LyXParagraph * tmp = this;
1230         while (tmp->next
1231                && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1232                 tmp = tmp->NextAfterFootnote();
1233    
1234         return tmp;
1235 }
1236
1237 LyXParagraph const * LyXParagraph::LastPhysicalPar() const
1238 {
1239         if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1240                 return this;
1241    
1242         LyXParagraph const * tmp = this;
1243         while (tmp->next
1244                && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1245                 tmp = tmp->NextAfterFootnote();
1246    
1247         return tmp;  
1248 }
1249
1250 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1251 {
1252         if (!IsDummy())
1253                 return this;
1254         LyXParagraph * tmppar = this;
1255
1256         while (tmppar &&
1257                (tmppar->IsDummy()
1258                 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1259                 tmppar = tmppar->previous;
1260    
1261         if (!tmppar) {
1262                 return this;
1263         } else
1264                 return tmppar;
1265 }
1266
1267
1268 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1269 {
1270         if (!IsDummy())
1271                 return this;
1272         LyXParagraph const * tmppar = this;
1273
1274         while (tmppar &&
1275                (tmppar->IsDummy()
1276                 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1277                 tmppar = tmppar->previous;
1278    
1279         if (!tmppar) {
1280                 return this;
1281         } else
1282                 return tmppar;
1283 }
1284
1285
1286 // This function is able to hide closed footnotes.
1287 LyXParagraph * LyXParagraph::Previous()
1288 {
1289         LyXParagraph * tmp = previous;
1290         if (!tmp)
1291                 return tmp;
1292    
1293         if (tmp->previous
1294             && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1295                 tmp = tmp->previous;
1296                 while (tmp
1297                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1298                         tmp = tmp->previous;
1299                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1300                         return tmp->next->Previous();   
1301
1302                 else
1303                         return previous; 
1304         } else
1305                 return previous;
1306 }
1307
1308
1309 // This function is able to hide closed footnotes.
1310 LyXParagraph const * LyXParagraph::Previous() const
1311 {
1312         LyXParagraph * tmp = previous;
1313         if (!tmp)
1314                 return tmp;
1315    
1316         if (tmp->previous
1317             && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1318                 tmp = tmp->previous;
1319                 while (tmp
1320                        && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1321                         tmp = tmp->previous;
1322                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1323                         return tmp->next->Previous();   
1324
1325                 else
1326                         return previous; 
1327         } else
1328                 return previous;
1329 }
1330
1331
1332 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1333                                   int flag)
1334 {
1335         size_type i, pos_end, pos_first;
1336         // create a new paragraph
1337         LyXParagraph * par = ParFromPos(pos);
1338         LyXParagraph * firstpar = FirstPhysicalPar();
1339    
1340         LyXParagraph * tmp = new LyXParagraph(par);
1341         
1342         tmp->footnoteflag = footnoteflag;
1343         tmp->footnotekind = footnotekind;
1344    
1345         // this is an idea for a more userfriendly layout handling, I will
1346         // see what the users say
1347    
1348         // layout stays the same with latex-environments
1349         if (flag) {
1350                 tmp->SetOnlyLayout(firstpar->layout);
1351                 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1352         }
1353
1354         if (Last() > pos || !Last() || flag == 2) {
1355                 tmp->SetOnlyLayout(firstpar->layout);
1356                 tmp->align = firstpar->align;
1357                 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1358       
1359                 tmp->line_bottom = firstpar->line_bottom;
1360                 firstpar->line_bottom = false;
1361                 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1362                 firstpar->pagebreak_bottom = false;
1363                 tmp->added_space_bottom = firstpar->added_space_bottom;
1364                 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1365       
1366                 tmp->depth = firstpar->depth;
1367                 tmp->noindent = firstpar->noindent;
1368    
1369                 // copy everything behind the break-position
1370                 // to the new paragraph
1371                 pos_first = 0;
1372                 while (ParFromPos(pos_first) != par)
1373                         ++pos_first;
1374
1375                 pos_end = pos_first + par->text.size() - 1;
1376                 // The constructor has already reserved 500 elements
1377                 //if (pos_end > pos)
1378                 //      tmp->text.reserve(pos_end - pos);
1379
1380                 for (i = pos; i <= pos_end; ++i) {
1381                         par->CutIntoMinibuffer(i - pos_first);
1382                         tmp->InsertFromMinibuffer(i - pos);
1383                 }
1384                 tmp->text.resize(tmp->text.size());
1385                 for (i = pos_end; i >= pos; --i)
1386                         par->Erase(i - pos_first);
1387
1388                 par->text.resize(par->text.size());
1389         }
1390
1391         // just an idea of me
1392         if (!pos) {
1393                 tmp->line_top = firstpar->line_top;
1394                 tmp->pagebreak_top = firstpar->pagebreak_top;
1395                 tmp->added_space_top = firstpar->added_space_top;
1396                 tmp->bibkey = firstpar->bibkey;
1397                 firstpar->Clear();
1398                 // layout stays the same with latex-environments
1399                 if (flag) {
1400                         firstpar->SetOnlyLayout(tmp->layout);
1401                         firstpar->SetLabelWidthString(tmp->labelwidthstring);
1402                         firstpar->depth = tmp->depth;
1403                 }
1404         }
1405 }
1406
1407
1408 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1409 {
1410         par = par->FirstPhysicalPar();
1411         footnoteflag = par->footnoteflag;
1412         footnotekind = par->footnotekind;
1413
1414         layout = par->layout;
1415         align = par-> align;
1416         SetLabelWidthString(par->labelwidthstring);
1417
1418         line_bottom = par->line_bottom;
1419         pagebreak_bottom = par->pagebreak_bottom;
1420         added_space_bottom = par->added_space_bottom;
1421
1422         line_top = par->line_top;
1423         pagebreak_top = par->pagebreak_top;
1424         added_space_top = par->added_space_top;
1425
1426         pextra_type = par->pextra_type;
1427         pextra_width = par->pextra_width;
1428         pextra_widthp = par->pextra_widthp;
1429         pextra_alignment = par->pextra_alignment;
1430         pextra_hfill = par->pextra_hfill;
1431         pextra_start_minipage = par->pextra_start_minipage;
1432
1433         noindent = par->noindent;
1434         depth = par->depth;
1435 }
1436
1437
1438 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1439 {
1440         LyXParagraph * tmppar = this;
1441         while (tmppar && (
1442                 (tmppar->IsDummy()
1443                  && tmppar->previous->footnoteflag == 
1444                  LyXParagraph::CLOSED_FOOTNOTE)
1445                 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1446                 tmppar = tmppar->previous;
1447    
1448         if (!tmppar)
1449                 return this;  // This should never happen!
1450         else
1451                 return tmppar;
1452 }
1453
1454
1455 LyXParagraph * LyXParagraph::Clone() const
1456 {
1457         // create a new paragraph
1458         LyXParagraph * result = new LyXParagraph;
1459    
1460         result->MakeSameLayout(this);
1461
1462         // this is because of the dummy layout of the paragraphs that
1463         // follow footnotes
1464         result->layout = layout;
1465    
1466         /* table stuff -- begin*/ 
1467         if (table)
1468                 result->table = table->Clone();
1469         else
1470                 result->table = 0;
1471         /* table stuff -- end*/ 
1472    
1473         // ale970302
1474         result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1475                
1476     
1477         // copy everything behind the break-position to the new paragraph
1478    
1479         for (size_type i = 0; i < size(); ++i) {
1480                 CopyIntoMinibuffer(i);
1481                 result->InsertFromMinibuffer(i);
1482         }
1483         result->text.resize(result->text.size());
1484         return result;
1485 }
1486
1487
1488 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1489 {
1490         par = par->FirstPhysicalPar();
1491
1492         return (
1493                 par->footnoteflag == footnoteflag &&
1494                 par->footnotekind == footnotekind &&
1495
1496                 par->layout == layout &&
1497
1498                 par->align == align &&
1499
1500                 par->line_bottom == line_bottom &&
1501                 par->pagebreak_bottom == pagebreak_bottom &&
1502                 par->added_space_bottom == added_space_bottom &&
1503
1504                 par->line_top == line_top &&
1505                 par->pagebreak_top == pagebreak_top &&
1506                 par->added_space_top == added_space_top &&
1507
1508                 par->pextra_type == pextra_type &&
1509                 par->pextra_width == pextra_width && 
1510                 par->pextra_widthp == pextra_widthp && 
1511                 par->pextra_alignment == pextra_alignment && 
1512                 par->pextra_hfill == pextra_hfill && 
1513                 par->pextra_start_minipage == pextra_start_minipage && 
1514
1515                 par->table == table && // what means: NO TABLE AT ALL 
1516
1517                 par->noindent == noindent &&
1518                 par->depth == depth);
1519 }
1520
1521
1522 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
1523 {
1524         // create a new paragraph
1525         LyXParagraph * par = ParFromPos(pos);
1526
1527         LyXParagraph * tmp = new LyXParagraph(par);
1528    
1529         tmp->MakeSameLayout(par);
1530
1531         // When can pos < Last()?
1532         // I guess pos == Last() is possible.
1533         if (Last() > pos) {
1534                 // copy everything behind the break-position to the new
1535                 // paragraph
1536                 size_type pos_first = 0;
1537                 while (ParFromPos(pos_first) != par)
1538                         ++pos_first;
1539                 size_type pos_end = pos_first + par->text.size() - 1;
1540                 // make sure there is enough memory for the now larger
1541                 // paragraph. This is not neccessary, because
1542                 // InsertFromMinibuffer will enlarge the memory (it uses
1543                 // InsertChar of course). But doing it by hand
1544                 // is MUCH faster! (only one time, not thousend times!!)
1545                 // Not needed since the constructor aleady have
1546                 // reserved 500 elements in text.
1547                 //if (pos_end > pos)
1548                 //      tmp->text.reserve(pos_end - pos);
1549
1550                 for (size_type i = pos; i <= pos_end; ++i) {
1551                         par->CutIntoMinibuffer(i - pos_first);
1552                         tmp->InsertFromMinibuffer(i - pos);
1553                 }
1554                 tmp->text.resize(tmp->text.size());
1555                 for (size_type i = pos_end; i >= pos; --i)
1556                         par->Erase(i - pos_first);
1557
1558                 par->text.resize(par->text.size());
1559         }
1560 }
1561    
1562
1563 // Be carefull, this does not make any check at all.
1564 void LyXParagraph::PasteParagraph()
1565 {
1566         // copy the next paragraph to this one
1567         LyXParagraph * the_next = Next();
1568    
1569         LyXParagraph * firstpar = FirstPhysicalPar();
1570    
1571         // first the DTP-stuff
1572         firstpar->line_bottom = the_next->line_bottom;
1573         firstpar->added_space_bottom = the_next->added_space_bottom;
1574         firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1575
1576         size_type pos_end = the_next->text.size() - 1;
1577         size_type pos_insert = Last();
1578
1579         // ok, now copy the paragraph
1580         for (size_type i = 0; i <= pos_end; ++i) {
1581                 the_next->CutIntoMinibuffer(i);
1582                 InsertFromMinibuffer(pos_insert + i);
1583         }
1584    
1585         // delete the next paragraph
1586         delete the_next;
1587 }
1588
1589
1590 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1591 {
1592         LyXParagraph * par = ParFromPos(pos);
1593         par = par->next;
1594         while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1595                 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1596                 par = par->next;
1597         }
1598 }
1599
1600
1601 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1602 {
1603         LyXParagraph * par = ParFromPos(pos);
1604         par = par->next;
1605         while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1606                 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1607                 par = par->next;
1608         }
1609 }
1610
1611 int LyXParagraph::GetEndLabel() const
1612 {
1613         LyXParagraph const * par = this;
1614         int par_depth = GetDepth();
1615         while (par) {
1616                 LyXTextClass::LayoutList::size_type layout = par->GetLayout();
1617                 int endlabeltype =
1618                         textclasslist.Style(current_view->buffer()->params.textclass,
1619                                             layout).endlabeltype;
1620                 if (endlabeltype != END_LABEL_NO_LABEL) {
1621                         LyXParagraph const * last = this;
1622                         if( footnoteflag == NO_FOOTNOTE)
1623                                 last = LastPhysicalPar();
1624                         else if (next->footnoteflag == NO_FOOTNOTE)
1625                                 return endlabeltype;
1626
1627                         if (!last || !last->next)
1628                                 return endlabeltype;
1629
1630                         int next_depth = last->next->GetDepth();
1631                         if (par_depth > next_depth ||
1632                             (par_depth == next_depth && layout != last->next->GetLayout() ))
1633                                 return endlabeltype;
1634                         break;
1635                 }
1636                 if (par_depth == 0)
1637                         break;
1638                 par = par->DepthHook(par_depth - 1);
1639                 if (par)
1640                         par_depth = par->GetDepth();
1641         }
1642         return END_LABEL_NO_LABEL;
1643 }
1644
1645 LyXTextClass::size_type LyXParagraph::GetLayout() const
1646 {
1647         return FirstPhysicalPar()->layout;
1648 }
1649
1650
1651 char LyXParagraph::GetDepth() const
1652 {
1653         return FirstPhysicalPar()->depth;
1654 }
1655
1656
1657 char LyXParagraph::GetAlign() const
1658 {
1659         return FirstPhysicalPar()->align;
1660 }
1661
1662
1663 string LyXParagraph::GetLabestring() const
1664 {
1665         return FirstPhysicalPar()->labelstring;
1666 }
1667
1668
1669 int LyXParagraph::GetFirstCounter(int i) const
1670 {
1671         return FirstPhysicalPar()->counter_[i];
1672 }
1673
1674
1675 // the next two functions are for the manual labels
1676 string LyXParagraph::GetLabelWidthString() const
1677 {
1678         if (!FirstPhysicalPar()->labelwidthstring.empty())
1679                 return FirstPhysicalPar()->labelwidthstring;
1680         else
1681                 return _("Senseless with this layout!");
1682 }
1683
1684
1685 void LyXParagraph::SetLabelWidthString(string const & s)
1686 {
1687         LyXParagraph * par = FirstPhysicalPar();
1688
1689         par->labelwidthstring = s;
1690 }
1691
1692
1693 void LyXParagraph::SetOnlyLayout(LyXTextClass::size_type new_layout)
1694 {
1695         LyXParagraph * par = FirstPhysicalPar();
1696         LyXParagraph * ppar = 0;
1697         LyXParagraph * npar = 0;
1698
1699         par->layout = new_layout;
1700         /* table stuff -- begin*/ 
1701         if (table) 
1702                 par->layout = 0;
1703         /* table stuff -- end*/ 
1704         if (par->pextra_type == PEXTRA_NONE) {
1705                 if (par->Previous()) {
1706                         ppar = par->Previous()->FirstPhysicalPar();
1707                         while(ppar
1708                               && ppar->Previous()
1709                               && (ppar->depth > par->depth))
1710                                 ppar = ppar->Previous()->FirstPhysicalPar();
1711                 }
1712                 if (par->Next()) {
1713                         npar = par->Next()->NextAfterFootnote();
1714                         while(npar
1715                               && npar->Next()
1716                               && (npar->depth > par->depth))
1717                                 npar = npar->Next()->NextAfterFootnote();
1718                 }
1719                 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1720                         string
1721                                 p1 = ppar->pextra_width,
1722                                 p2 = ppar->pextra_widthp;
1723                         ppar->SetPExtraType(ppar->pextra_type,
1724                                             p1.c_str(), p2.c_str());
1725                 }
1726                 if ((par->pextra_type == PEXTRA_NONE) &&
1727                     npar && (npar->pextra_type != PEXTRA_NONE)) {
1728                         string
1729                                 p1 = npar->pextra_width,
1730                                 p2 = npar->pextra_widthp;
1731                         npar->SetPExtraType(npar->pextra_type,
1732                                             p1.c_str(), p2.c_str());
1733                 }
1734         }
1735 }
1736
1737
1738 void LyXParagraph::SetLayout(LyXTextClass::size_type new_layout)
1739 {
1740         LyXParagraph
1741                 * par = FirstPhysicalPar(),
1742                 * ppar = 0,
1743                 * npar = 0;
1744
1745         par->layout = new_layout;
1746         par->labelwidthstring.clear();
1747         par->align = LYX_ALIGN_LAYOUT;
1748         par->added_space_top = VSpace(VSpace::NONE);
1749         par->added_space_bottom = VSpace(VSpace::NONE);
1750         /* table stuff -- begin*/ 
1751         if (table) 
1752                 par->layout = 0;
1753         /* table stuff -- end*/
1754         if (par->pextra_type == PEXTRA_NONE) {
1755                 if (par->Previous()) {
1756                         ppar = par->Previous()->FirstPhysicalPar();
1757                         while(ppar
1758                               && ppar->Previous()
1759                               && (ppar->depth > par->depth))
1760                                 ppar = ppar->Previous()->FirstPhysicalPar();
1761                 }
1762                 if (par->Next()) {
1763                         npar = par->Next()->NextAfterFootnote();
1764                         while(npar
1765                               && npar->Next()
1766                               && (npar->depth > par->depth))
1767                                 npar = npar->Next()->NextAfterFootnote();
1768                 }
1769                 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1770                         string
1771                                 p1 = ppar->pextra_width,
1772                                 p2 = ppar->pextra_widthp;
1773                         ppar->SetPExtraType(ppar->pextra_type,
1774                                             p1.c_str(), p2.c_str());
1775                 }
1776                 if ((par->pextra_type == PEXTRA_NONE) &&
1777                     npar && (npar->pextra_type != PEXTRA_NONE)) {
1778                         string
1779                                 p1 = npar->pextra_width,
1780                                 p2 = npar->pextra_widthp;
1781                         npar->SetPExtraType(npar->pextra_type,
1782                                             p1.c_str(), p2.c_str());
1783                 }
1784         }
1785 }
1786
1787
1788 // if the layout of a paragraph contains a manual label, the beginning of the 
1789 // main body is the beginning of the second word. This is what the par-
1790 // function returns. If the layout does not contain a label, the main
1791 // body always starts with position 0. This differentiation is necessary,
1792 // because there cannot be a newline or a blank <= the beginning of the 
1793 // main body in TeX.
1794
1795 int LyXParagraph::BeginningOfMainBody() const
1796 {
1797         if (FirstPhysicalPar() != this)
1798                 return -1;
1799    
1800         // Unroll the first two cycles of the loop
1801         // and remember the previous character to
1802         // remove unnecessary GetChar() calls
1803         size_type i = 0;
1804         if (i < size()
1805             && GetChar(i) != LyXParagraph::META_NEWLINE
1806                 ) {
1807                 ++i;
1808                 char previous_char = 0, temp = 0; 
1809                 if (i < size()
1810                     && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1811                         // Yes, this  ^ is supposed to be "= " not "=="
1812                         ++i;
1813                         while (i < size()
1814                                && previous_char != ' '
1815                                && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1816                                 ++i;
1817                                 previous_char = temp;
1818                         }
1819                 }
1820         }
1821
1822         if (i == 0 && i == size() &&
1823             !(footnoteflag == LyXParagraph::NO_FOOTNOTE
1824               && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1825                 ++i;                           /* the cursor should not jump  
1826                                                 * to the main body if there
1827                                                 * is nothing in! */
1828         return i;
1829 }
1830
1831
1832 LyXParagraph * LyXParagraph::DepthHook(int deth)
1833 {
1834         LyXParagraph * newpar = this;
1835         if (deth < 0)
1836                 return 0;
1837    
1838         do {
1839                 newpar = newpar->FirstPhysicalPar()->Previous();
1840         } while (newpar && newpar->GetDepth() > deth
1841                  && newpar->footnoteflag == footnoteflag);
1842    
1843         if (!newpar) {
1844                 if (Previous() || GetDepth())
1845                         lyxerr << "ERROR (LyXParagraph::DepthHook): "
1846                                 "no hook." << endl;
1847                 newpar = this;
1848         }
1849         return newpar->FirstPhysicalPar();
1850 }
1851
1852
1853 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
1854 {
1855         LyXParagraph const * newpar = this;
1856         if (deth < 0)
1857                 return 0;
1858    
1859         do {
1860                 newpar = newpar->FirstPhysicalPar()->Previous();
1861         } while (newpar && newpar->GetDepth() > deth
1862                  && newpar->footnoteflag == footnoteflag);
1863    
1864         if (!newpar) {
1865                 if (Previous() || GetDepth())
1866                         lyxerr << "ERROR (LyXParagraph::DepthHook): "
1867                                 "no hook." << endl;
1868                 newpar = this;
1869         }
1870         return newpar->FirstPhysicalPar();
1871 }
1872
1873
1874 int LyXParagraph::AutoDeleteInsets()
1875 {
1876         vector<size_type> tmpvec;
1877         int i = 0;
1878         for (InsetList::iterator it = insetlist.begin();
1879              it != insetlist.end(); ++it) {
1880                 if ((*it).inset && (*it).inset->AutoDelete()) {
1881                         tmpvec.push_back((*it).pos);
1882                         ++i;
1883                 }
1884         }
1885         for (vector<size_type>::const_iterator cit = tmpvec.begin();
1886              cit != tmpvec.end(); ++cit) {
1887                 Erase((*cit));
1888         }
1889         return i;
1890 }
1891
1892
1893 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
1894 {
1895         InsetList::iterator it2 = insetlist.end();
1896         for (InsetList::iterator it = insetlist.begin();
1897              it != insetlist.end(); ++it) {
1898                 if ((*it).pos >= pos) {
1899                         if (it2 == insetlist.end() || (*it).pos < (*it2).pos)
1900                                 it2 = it;
1901                 }
1902         }
1903         if (it2 != insetlist.end()) {
1904                 pos = (*it2).pos;
1905                 return (*it2).inset;
1906         }
1907         return 0;
1908 }
1909
1910
1911 // returns -1 if inset not found
1912 int LyXParagraph::GetPositionOfInset(Inset * inset) const
1913 {
1914         // Find the entry.
1915         for (InsetList::const_iterator cit = insetlist.begin();
1916              cit != insetlist.end(); ++cit) {
1917                 if ((*cit).inset == inset) {
1918                         return (*cit).pos;
1919                 }
1920         }
1921         // Think about footnotes.
1922         if (footnoteflag == LyXParagraph::NO_FOOTNOTE 
1923             && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1924                 int further = 
1925                         NextAfterFootnote()->GetPositionOfInset(inset);
1926                 if (further != -1)
1927                         return text.size() + 1 + further;
1928         }
1929         return -1;
1930 }
1931
1932
1933 LyXParagraph * LyXParagraph::TeXOnePar(ostream & os, TexRow & texrow,
1934                                        ostream & foot, TexRow & foot_texrow,
1935                                        int & foot_count)
1936 {
1937         lyxerr[Debug::LATEX] << "TeXOnePar...     " << this << endl;
1938         LyXLayout const & style =
1939                 textclasslist.Style(current_view->buffer()->params.textclass,
1940                                     layout);
1941
1942         bool further_blank_line = false;
1943         if (IsDummy())
1944                 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1945
1946         if (start_of_appendix) {
1947                 os << "\\appendix\n";
1948                 texrow.newline();
1949         }
1950
1951         if (tex_code_break_column && style.isCommand()){
1952                 os << '\n';
1953                 texrow.newline();
1954         }
1955
1956         if (pagebreak_top) {
1957                 os << "\\newpage";
1958                 further_blank_line = true;
1959         }
1960         if (added_space_top.kind() != VSpace::NONE) {
1961                 os << added_space_top.asLatexCommand(current_view->buffer()->params);
1962                 further_blank_line = true;
1963         }
1964       
1965         if (line_top) {
1966                 os << "\\lyxline{\\" << getFont(0).latexSize() << '}'
1967                    << "\\vspace{-1\\parskip}";
1968                 further_blank_line = true;
1969         }
1970
1971         if (further_blank_line){
1972                 os << '\n';
1973                 texrow.newline();
1974         }
1975
1976         Language const * language = getParLanguage();
1977         Language const * doc_language = current_view->buffer()->params.language_info;
1978         if (language != doc_language) {
1979                 os << subst(lyxrc.language_command_begin, "$$lang",
1980                             language->lang)
1981                    << endl;
1982                 texrow.newline();
1983         }
1984         
1985         switch (style.latextype) {
1986         case LATEX_COMMAND:
1987                 os << '\\'
1988                    << style.latexname()
1989                    << style.latexparam();
1990                 break;
1991         case LATEX_ITEM_ENVIRONMENT:
1992                 if (bibkey) {
1993                         bibkey->Latex(os, false, false);
1994                 } else
1995                         os << "\\item ";
1996                 break;
1997         case LATEX_LIST_ENVIRONMENT:
1998                 os << "\\item ";
1999                 break;
2000         default:
2001                 break;
2002         }
2003
2004         bool need_par = SimpleTeXOnePar(os, texrow);
2005  
2006         // Spit out footnotes
2007         LyXParagraph * par = next;
2008         if (lyxrc.rtl_support) {
2009                 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2010                     && next->footnoteflag != footnoteflag) {
2011                         LyXParagraph * p = 0;
2012                         bool is_rtl = GetFontSettings(size()-1).isRightToLeft();
2013                         if ( (p = NextAfterFootnote()) != 0 &&
2014                              p->GetFontSettings(0).isRightToLeft() != is_rtl)
2015                                 is_rtl = GetFontSettings(0).isRightToLeft();
2016                         while (par &&
2017                                par->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2018                                par->footnoteflag != footnoteflag) {
2019                                 LyXDirection dir = (is_rtl)
2020                                         ? LYX_DIR_RIGHT_TO_LEFT 
2021                                         : LYX_DIR_LEFT_TO_RIGHT;
2022                                 par = par->TeXFootnote(os, texrow, foot,
2023                                                        foot_texrow, foot_count,
2024                                                        dir);
2025                                 par->SimpleTeXOnePar(os, texrow);
2026                                 is_rtl = par->GetFontSettings(par->size()-1).isRightToLeft();
2027                                 if (par->next &&
2028                                     par->next->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2029                                     (p = par->NextAfterFootnote()) != 0 &&
2030                                     p->GetFontSettings(0).isRightToLeft() != is_rtl)
2031                                         is_rtl = GetFontSettings(0).isRightToLeft();
2032                                 par = par->next;
2033                         }
2034                 }
2035         } else {
2036                 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2037                        && par->footnoteflag != footnoteflag) {
2038                         par = par->TeXFootnote(os, texrow,
2039                                                foot, foot_texrow, foot_count,
2040                                                LYX_DIR_LEFT_TO_RIGHT);
2041                         par->SimpleTeXOnePar(os, texrow);
2042                         par = par->next;
2043                 }
2044         }
2045
2046         // Make sure that \\par is done with the font of the last
2047         // character if this has another size as the default.
2048         // This is necessary because LaTeX (and LyX on the screen)
2049         // calculates the space between the baselines according
2050         // to this font. (Matthias)
2051         LyXFont font = getFont(Last() - 1);
2052         if (need_par) {
2053                 if (style.resfont.size() != font.size()) {
2054                         os << '\\'
2055                            << font.latexSize()
2056                            << ' ';
2057                 }
2058                 os << "\\par}";
2059         } else if (textclasslist.Style(current_view->buffer()->params.textclass,
2060                                        GetLayout()).isCommand()){
2061                 if (style.resfont.size() != font.size()) {
2062                         os << '\\'
2063                            << font.latexSize()
2064                            << ' ';
2065                 }
2066                 os << '}';
2067         } else if (style.resfont.size() != font.size()){
2068                 os << "{\\" << font.latexSize() << " \\par}";
2069         }
2070
2071         if (language != doc_language) {
2072                 os << endl 
2073                    << subst(lyxrc.language_command_end, "$$lang",
2074                             doc_language->lang);
2075         }
2076         
2077         switch (style.latextype) {
2078         case LATEX_ITEM_ENVIRONMENT:
2079         case LATEX_LIST_ENVIRONMENT:
2080                 if (par && (depth < par->depth)) {
2081                         os << '\n';
2082                         texrow.newline();
2083                 }
2084                 break;
2085         case LATEX_ENVIRONMENT:
2086                 // if its the last paragraph of the current environment
2087                 // skip it otherwise fall through
2088                 if (par
2089                     && (par->layout != layout
2090                         || par->depth != depth
2091                         || par->pextra_type != pextra_type))
2092                         break;
2093         default:
2094                 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2095                       && footnotekind != LyXParagraph::FOOTNOTE
2096                       && footnotekind != LyXParagraph::MARGIN
2097                       && (table
2098                           || (par
2099                               && par->table)))) {
2100                         // don't insert this if we would be adding it
2101                         // before or after a table in a float.  This 
2102                         // little trick is needed in order to allow
2103                         // use of tables in \subfigures or \subtables.
2104                         os << '\n';
2105                         texrow.newline();
2106                 }
2107         }
2108         
2109         further_blank_line = false;
2110         if (line_bottom) {
2111                 os << "\\lyxline{\\" << getFont(Last() - 1).latexSize() << '}';
2112                 further_blank_line = true;
2113         }
2114
2115         if (added_space_bottom.kind() != VSpace::NONE) {
2116                 os << added_space_bottom.asLatexCommand(current_view->buffer()->params);
2117                 further_blank_line = true;
2118         }
2119       
2120         if (pagebreak_bottom) {
2121                 os << "\\newpage";
2122                 further_blank_line = true;
2123         }
2124
2125         if (further_blank_line){
2126                 os << '\n';
2127                 texrow.newline();
2128         }
2129
2130         if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2131               par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2132                 os << '\n';
2133                 texrow.newline();
2134         }
2135
2136         lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2137         return par;
2138 }
2139
2140
2141 // This one spits out the text of the paragraph
2142 bool LyXParagraph::SimpleTeXOnePar(ostream & os, TexRow & texrow)
2143 {
2144         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...     " << this << endl;
2145
2146         if (table)
2147                 return SimpleTeXOneTablePar(os, texrow);
2148
2149         bool return_value = false;
2150
2151         LyXLayout const & style =
2152                 textclasslist.Style(current_view->buffer()->params.textclass,
2153                                     GetLayout());
2154         LyXFont basefont, last_font;
2155
2156         // Maybe we have to create a optional argument.
2157         size_type main_body;
2158         if (style.labeltype != LABEL_MANUAL)
2159                 main_body = 0;
2160         else
2161                 main_body = BeginningOfMainBody();
2162
2163         if (main_body > 0) {
2164                 os << '[';
2165                 basefont = getFont(-2); // Get label font
2166         } else {
2167                 basefont = getFont(-1); // Get layout font
2168         }
2169
2170         int column = 0;
2171
2172         if (main_body >= 0
2173             && !text.size()
2174             && !IsDummy()) {
2175                 if (style.isCommand()) {
2176                         os << '{';
2177                         ++column;
2178                 } else if (align != LYX_ALIGN_LAYOUT) {
2179                         os << '{';
2180                         ++column;
2181                         return_value = true;
2182                 }
2183         }
2184  
2185         // Which font is currently active?
2186         LyXFont running_font(basefont);
2187         // Do we have an open font change?
2188         bool open_font = false;
2189
2190         texrow.start(this, 0);
2191
2192         for (size_type i = 0; i < size(); ++i) {
2193                 ++column;
2194                 // First char in paragraph or after label?
2195                 if (i == main_body && !IsDummy()) {
2196                         if (main_body > 0) {
2197                                 if (open_font) {
2198                                         column += running_font.latexWriteEndChanges(os, basefont, basefont);
2199                                         open_font = false;
2200                                 }
2201                                 basefont = getFont(-1); // Now use the layout font
2202                                 running_font = basefont;
2203                                 os << ']';
2204                                 ++column;
2205                         }
2206                         if (style.isCommand()) {
2207                                 os << '{';
2208                                 ++column;
2209                         } else if (align != LYX_ALIGN_LAYOUT) {
2210                                 os << "{\\par";
2211                                 column += 4;
2212                                 return_value = true;
2213                         }
2214
2215                         if (noindent) {
2216                                 os << "\\noindent ";
2217                                 column += 10;
2218                         }
2219                         switch (align) {
2220                         case LYX_ALIGN_NONE:
2221                         case LYX_ALIGN_BLOCK:
2222                         case LYX_ALIGN_LAYOUT:
2223                         case LYX_ALIGN_SPECIAL:
2224                                 break;
2225                         case LYX_ALIGN_LEFT:
2226                                 if (getParLanguage()->lang != "hebrew") {
2227                                         os << "\\raggedright ";
2228                                         column+= 13;
2229                                 } else {
2230                                         os << "\\raggedleft ";
2231                                         column+= 12;
2232                                 }
2233                                 break;
2234                         case LYX_ALIGN_RIGHT:
2235                                 if (getParLanguage()->lang != "hebrew") {
2236                                         os << "\\raggedleft ";
2237                                         column+= 12;
2238                                 } else {
2239                                         os << "\\raggedright ";
2240                                         column+= 13;
2241                                 }
2242                                 break;
2243                         case LYX_ALIGN_CENTER:
2244                                 os << "\\centering ";
2245                                 column+= 11;
2246                                 break;
2247                         }        
2248                 }
2249
2250                 int c = GetChar(i);
2251
2252                 // Fully instantiated font
2253                 LyXFont font = getFont(i);
2254                 LyXParagraph * p = 0;
2255                 if (i == 0 && previous && 
2256                     previous->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
2257                     (p = PreviousBeforeFootnote()) != 0)
2258                         last_font = p->getFont(p->size()-1);
2259                 else
2260                         last_font = running_font;
2261
2262                 // Spaces at end of font change are simulated to be
2263                 // outside font change, i.e. we write "\textXX{text} "
2264                 // rather than "\textXX{text }". (Asger)
2265                 if (open_font && c == ' ' && i <= size() - 2 
2266                     && !getFont(i+1).equalExceptLatex(running_font) 
2267                     && !getFont(i+1).equalExceptLatex(font)) {
2268                         font = getFont(i + 1);
2269                 }
2270                 // We end font definition before blanks
2271                 if (!font.equalExceptLatex(running_font) && open_font) {
2272                         column += running_font.latexWriteEndChanges(os,
2273                                                                     basefont,
2274                                                                     (i == main_body-1) ? basefont : font);
2275                         running_font = basefont;
2276                         open_font = false;
2277                 }
2278
2279                 // Blanks are printed before start of fontswitch
2280                 if (c == ' '){
2281                         // Do not print the separation of the optional argument
2282                         if (i != main_body - 1) {
2283                                 SimpleTeXBlanks(os, texrow, i,
2284                                                 column, font, style);
2285                         }
2286                 }
2287
2288                 // Do we need to change font?
2289                 if (!font.equalExceptLatex(running_font)
2290                     && i != main_body-1) {
2291                         column += font.latexWriteStartChanges(os, basefont,
2292                                                               last_font);
2293                         running_font = font;
2294                         open_font = true;
2295                 }
2296
2297                 if (c == LyXParagraph::META_NEWLINE) {
2298                         // newlines are handled differently here than
2299                         // the default in SimpleTeXSpecialChars().
2300                         if (!style.newline_allowed
2301                             || font.latex() == LyXFont::ON) {
2302                                 os << '\n';
2303                         } else {
2304                                 if (open_font) {
2305                                         column += running_font.latexWriteEndChanges(os, basefont, basefont);
2306                                         open_font = false;
2307                                 }
2308                                 basefont = getFont(-1);
2309                                 running_font = basefont;
2310                                 if (font.family() == 
2311                                     LyXFont::TYPEWRITER_FAMILY) {
2312                                         os << "~";
2313                                 }
2314                                 os << "\\\\\n";
2315                         }
2316                         texrow.newline();
2317                         texrow.start(this, i + 1);
2318                         column = 0;
2319                 } else {
2320                         SimpleTeXSpecialChars(os, texrow,
2321                                               font, running_font, basefont,
2322                                               open_font, style, i, column, c);
2323                 }
2324         }
2325
2326         // If we have an open font definition, we have to close it
2327         if (open_font) {
2328                 LyXParagraph * p = 0;
2329                 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE
2330                     && (p =  NextAfterFootnote()) != 0)
2331                         running_font.latexWriteEndChanges(os, basefont,
2332                                                           p->getFont(0));
2333                 else
2334                         running_font.latexWriteEndChanges(os, basefont, basefont);
2335         }
2336
2337         // Needed if there is an optional argument but no contents.
2338         if (main_body > 0 && main_body == size()) {
2339                 os << "]~";
2340                 return_value = false;
2341         }
2342
2343         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2344         return return_value;
2345 }
2346
2347
2348 // This one spits out the text of a table paragraph
2349 bool LyXParagraph::SimpleTeXOneTablePar(ostream & os, TexRow & texrow)
2350 {
2351         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...     " << this << endl;
2352    
2353         bool return_value = false;
2354
2355         LyXLayout const & style = 
2356                 textclasslist.Style(current_view->buffer()->params.textclass,
2357                                     GetLayout());
2358  
2359         int column = 0;
2360         if (!IsDummy()) { // it is dummy if it is in a float!!!
2361                 if (style.isCommand()) {
2362                         os << '{';
2363                         ++column;
2364                 } else if (align != LYX_ALIGN_LAYOUT) {
2365                         os << '{';
2366                         ++column;
2367                         return_value = true;
2368                 }
2369                 if (noindent) {
2370                         os << "\\noindent ";
2371                         column += 10;
2372                 }
2373                 switch (align) {
2374                 case LYX_ALIGN_NONE:
2375                 case LYX_ALIGN_BLOCK:
2376                 case LYX_ALIGN_LAYOUT:
2377                 case LYX_ALIGN_SPECIAL: break;
2378                 case LYX_ALIGN_LEFT:
2379                         os << "\\raggedright ";
2380                         column+= 13;
2381                         break;
2382                 case LYX_ALIGN_RIGHT:
2383                         os << "\\raggedleft ";
2384                         column+= 12;
2385                         break;
2386                 case LYX_ALIGN_CENTER:
2387                         os << "\\centering ";
2388                         column+= 11;
2389                         break;
2390                 }
2391         }
2392
2393         LyXFont basefont = getFont(-1); // Get layout font
2394         // Which font is currently active?
2395         LyXFont running_font = basefont;
2396         LyXFont last_font;
2397         // Do we have an open font change?
2398         bool open_font = false;
2399         int current_cell_number = -1;
2400         int tmp = table->TexEndOfCell(os, current_cell_number);
2401         for (; tmp > 0 ; --tmp)
2402                 texrow.newline();
2403         
2404         texrow.start(this, 0);
2405
2406         for (size_type i = 0; i < size(); ++i) {
2407                 char c = GetChar(i);
2408                 if (table->IsContRow(current_cell_number + 1)) {
2409                         if (c == LyXParagraph::META_NEWLINE)
2410                                 ++current_cell_number;
2411                         continue;
2412                 }
2413                 ++column;
2414                 
2415                 // Fully instantiated font
2416                 LyXFont font = getFont(i);
2417                 last_font = running_font;
2418
2419                 // Spaces at end of font change are simulated to be
2420                 // outside font change.
2421                 // i.e. we write "\textXX{text} " rather than
2422                 // "\textXX{text }". (Asger)
2423                 if (open_font && c == ' ' && i <= size() - 2
2424                     && getFont(i + 1) != running_font
2425                     && getFont(i + 1) != font) {
2426                         font = getFont(i + 1);
2427                 }
2428
2429                 // We end font definition before blanks
2430                 if (font != running_font && open_font) {
2431                         column += running_font.latexWriteEndChanges(os,
2432                                                                     basefont,
2433                                                                     font);
2434                         running_font = basefont;
2435                         open_font = false;
2436                 }
2437                 // Blanks are printed before start of fontswitch
2438                 if (c == ' '){
2439                         SimpleTeXBlanks(os, texrow, i, column, font, style);
2440                 }
2441                 // Do we need to change font?
2442                 if (font != running_font) {
2443                         column += font.latexWriteStartChanges(os, basefont,
2444                                                               last_font);
2445                         running_font = font;
2446                         open_font = true;
2447                 }
2448                 // Do we need to turn on LaTeX mode?
2449                 if (font.latex() != running_font.latex()) {
2450                         if (font.latex() == LyXFont::ON
2451                             && style.needprotect) {
2452                                 os << "\\protect ";
2453                                 column += 9;
2454                         }
2455                 }
2456                 if (c == LyXParagraph::META_NEWLINE) {
2457                         // special case for inside a table
2458                         // different from default case in
2459                         // SimpleTeXSpecialChars()
2460                         if (open_font) {
2461                                 column += running_font
2462                                         .latexWriteEndChanges(os, basefont,
2463                                                               basefont);
2464                                 open_font = false;
2465                         }
2466                         basefont = getFont(-1);
2467                         running_font = basefont;
2468                         ++current_cell_number;
2469                         if (table->CellHasContRow(current_cell_number) >= 0) {
2470                                 TeXContTableRows(os, i + 1,
2471                                                  current_cell_number,
2472                                                  column, texrow);
2473                         }
2474                         // if this cell follow only ContRows till end don't
2475                         // put the EndOfCell because it is put after the
2476                         // for(...)
2477                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2478                                 --current_cell_number;
2479                                 break;
2480                         }
2481                         int tmp = table->TexEndOfCell(os,
2482                                                       current_cell_number);
2483                         if (tmp > 0) {
2484                                 column = 0;
2485                         } else if (tmp < 0) {
2486                                 tmp = -tmp;
2487                         }
2488                         for (; tmp--;) {
2489                                 texrow.newline();
2490                         }
2491                         texrow.start(this, i + 1);
2492                 } else {
2493                         SimpleTeXSpecialChars(os, texrow,
2494                                               font, running_font, basefont,
2495                                               open_font, style, i, column, c);
2496                 }
2497         }
2498
2499         // If we have an open font definition, we have to close it
2500         if (open_font) {
2501                 running_font.latexWriteEndChanges(os, basefont, basefont);
2502         }
2503         ++current_cell_number;
2504         tmp = table->TexEndOfCell(os, current_cell_number);
2505         for (; tmp > 0; --tmp)
2506                 texrow.newline();
2507         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2508         return return_value;
2509 }
2510
2511
2512 // This one spits out the text off ContRows in tables
2513 bool LyXParagraph::TeXContTableRows(ostream & os,
2514                                     LyXParagraph::size_type i,
2515                                     int current_cell_number,
2516                                     int & column, TexRow & texrow)
2517 {
2518         lyxerr[Debug::LATEX] << "TeXContTableRows...     " << this << endl;
2519         if (!table)
2520                 return false;
2521     
2522         char c;
2523    
2524         bool return_value = false;
2525         LyXLayout const & style =
2526                 textclasslist.Style(current_view->buffer()->params.textclass,
2527                                     GetLayout());
2528         LyXFont basefont = getFont(-1); // Get layout font
2529         LyXFont last_font;
2530         // Which font is currently active?
2531         LyXFont running_font = basefont;
2532         // Do we have an open font change?
2533         bool open_font = false;
2534
2535         size_type lastpos = i;
2536         int cell = table->CellHasContRow(current_cell_number);
2537         ++current_cell_number;
2538         while(cell >= 0) {
2539                 // first find the right position
2540                 i = lastpos;
2541                 for (; (i < size()) && (current_cell_number<cell); ++i) {
2542                         c = GetChar(i);
2543                         if (c == LyXParagraph::META_NEWLINE)
2544                                 ++current_cell_number;
2545                 }
2546                 lastpos = i;
2547                 c = GetChar(i);
2548                 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2549                         os << " \\\\\n";
2550                         texrow.newline();
2551                         column = 0;
2552                 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2553                         os << ' ';
2554                 }
2555
2556                 for (; i < size()
2557                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2558                      ++i) {
2559                         ++column;
2560
2561                         // Fully instantiated font
2562                         LyXFont font = getFont(i);
2563                         last_font = running_font;
2564
2565                         // Spaces at end of font change are simulated to
2566                         // be outside font change. i.e. we write
2567                         // "\textXX{text} " rather than "\textXX{text }".
2568                         // (Asger)
2569                         if (open_font && c == ' ' && i <= size() - 2 
2570                             && getFont(i + 1) != running_font
2571                             && getFont(i + 1) != font) {
2572                                 font = getFont(i + 1);
2573                         }
2574
2575                         // We end font definition before blanks
2576                         if (font != running_font && open_font) {
2577                                 column += running_font.latexWriteEndChanges(os, basefont, font);
2578                                 running_font = basefont;
2579                                 open_font = false;
2580                         }
2581                         // Blanks are printed before start of fontswitch
2582                         if (c == ' '){
2583                                 SimpleTeXBlanks(os, texrow, i,
2584                                                 column, font, style);
2585                         }
2586                         // Do we need to change font?
2587                         if (font != running_font) {
2588                                 column +=
2589                                         font.latexWriteStartChanges(os,
2590                                                                     basefont,
2591                                                                     last_font);
2592                                 running_font = font;
2593                                 open_font = true;
2594                         }
2595                         // Do we need to turn on LaTeX mode?
2596                         if (font.latex() != running_font.latex()) {
2597                                 if (font.latex() == LyXFont::ON
2598                                     && style.needprotect) {
2599                                         os << "\\protect ";
2600                                         column += 9;
2601                                 }
2602                         }
2603                         SimpleTeXSpecialChars(os, texrow, font,
2604                                               running_font, basefont,
2605                                               open_font, style, i, column, c);
2606                 }
2607                 // If we have an open font definition, we have to close it
2608                 if (open_font) {
2609                         running_font.latexWriteEndChanges(os, basefont,
2610                                                           basefont);
2611                         open_font = false;
2612                 }
2613                 basefont = getFont(-1);
2614                 running_font = basefont;
2615                 cell = table->CellHasContRow(current_cell_number);
2616         }
2617         lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2618         return return_value;
2619 }
2620
2621
2622 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2623 {
2624         bool retval = false;
2625         switch (c) {
2626         case LyXParagraph::META_HFILL:
2627                 sgml_string.clear();
2628                 break;
2629 #if 0
2630         case LyXParagraph::META_PROTECTED_SEPARATOR: 
2631                 sgml_string = ' ';
2632                 break;
2633 #endif
2634         case LyXParagraph::META_NEWLINE:
2635                 sgml_string = '\n';
2636                 break;
2637         case '&': 
2638                 sgml_string = "&amp;";
2639                 break;
2640         case '<': 
2641                 sgml_string = "&lt;"; 
2642                 break;
2643         case '>':
2644                 sgml_string = "&gt;"; 
2645                 break;
2646         case '$': 
2647                 sgml_string = "&dollar;"; 
2648                 break;
2649         case '#': 
2650                 sgml_string = "&num;";
2651                 break;
2652         case '%': 
2653                 sgml_string = "&percnt;";
2654                 break;
2655         case '[': 
2656                 sgml_string = "&lsqb;";
2657                 break;
2658         case ']': 
2659                 sgml_string = "&rsqb;";
2660                 break;
2661         case '{': 
2662                 sgml_string = "&lcub;";
2663                 break;
2664         case '}': 
2665                 sgml_string = "&rcub;";
2666                 break;
2667         case '~': 
2668                 sgml_string = "&tilde;";
2669                 break;
2670         case '"': 
2671                 sgml_string = "&quot;";
2672                 break;
2673         case '\\': 
2674                 sgml_string = "&bsol;";
2675                 break;
2676         case ' ':
2677                 retval = true;
2678                 sgml_string = ' ';
2679                 break;
2680         case '\0': // Ignore :-)
2681                 sgml_string.clear();
2682                 break;
2683         default:
2684                 sgml_string = c;
2685                 break;
2686         }
2687         return retval;
2688 }
2689
2690
2691 void LyXParagraph::SimpleDocBookOneTablePar(ostream & os, string & extra,
2692                                             int & desc_on, int depth) 
2693 {
2694         if (!table) return;
2695         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2696         int column = 0;
2697         LyXFont font1, font2;
2698         char c;
2699         Inset * inset;
2700         size_type main_body;
2701         bool emph_flag = false;
2702         
2703         LyXLayout const & style =
2704                 textclasslist.Style(current_view->buffer()->params.textclass,
2705                                     GetLayout());
2706         
2707         if (style.labeltype != LABEL_MANUAL)
2708                 main_body = 0;
2709         else
2710                 main_body = BeginningOfMainBody();
2711         
2712         // Gets paragraph main font.
2713         if (main_body > 0)
2714                 font1 = style.labelfont;
2715         else
2716                 font1 = style.font;
2717         
2718         int char_line_count = depth;
2719         os << newlineAndDepth(depth);
2720         if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2721                 os << "<INFORMALTABLE>"
2722                    << newlineAndDepth(++depth);
2723         }
2724         int current_cell_number = -1;
2725         int tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2726         
2727         // Parsing main loop.
2728         for (size_type i = 0; i < size(); ++i) {
2729                 c = GetChar(i);
2730                 if (table->IsContRow(current_cell_number+1)) {
2731                         if (c == LyXParagraph::META_NEWLINE)
2732                                 ++current_cell_number;
2733                         continue;
2734                 }
2735                 ++column;
2736                 
2737                 // Fully instantiated font
2738                 font2 = getFont(i);
2739                 
2740                 // Handle <emphasis> tag.
2741                 if (font1.emph() != font2.emph() && i) {
2742                         if (font2.emph() == LyXFont::ON) {
2743                                 os << "<emphasis>";
2744                                 emph_flag= true;
2745                         } else if (emph_flag) {
2746                                 os << "</emphasis>";
2747                                 emph_flag= false;
2748                         }
2749                 }
2750                 if (c == LyXParagraph::META_NEWLINE) {
2751                         // We have only to control for emphasis open here!
2752                         if (emph_flag) {
2753                                 os << "</emphasis>";
2754                                 emph_flag= false;
2755                         }
2756                         font1 = font2 = getFont(-1);
2757                         ++current_cell_number;
2758                         if (table->CellHasContRow(current_cell_number) >= 0) {
2759                                 DocBookContTableRows(os, extra, desc_on, i + 1,
2760                                                      current_cell_number,
2761                                                      column);
2762                         }
2763                         // if this cell follow only ContRows till end don't
2764                         // put the EndOfCell because it is put after the
2765                         // for(...)
2766                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2767                                 --current_cell_number;
2768                                 break;
2769                         }
2770                         tmp = table->DocBookEndOfCell(os,
2771                                                       current_cell_number,
2772                                                       depth);
2773                         
2774                         if (tmp > 0)
2775                                 column = 0;
2776                 } else if (c == LyXParagraph::META_INSET) {
2777                         inset = GetInset(i);
2778 #ifdef HAVE_SSTREAM
2779                         ostringstream ost;
2780                         inset->DocBook(ost);
2781                         string tmp_out = ost.str().c_str();
2782 #else
2783                         ostrstream ost;
2784                         inset->DocBook(ost);
2785                         ost << '\0';
2786                         char * ctmp = ost.str();
2787                         string tmp_out(ctmp);
2788                         delete [] ctmp;
2789 #endif
2790                         //
2791                         // This code needs some explanation:
2792                         // Two insets are treated specially
2793                         //   label if it is the first element in a
2794                         //   command paragraph
2795                         //         desc_on == 3
2796                         //   graphics inside tables or figure floats
2797                         //   can't go on
2798                         //   title (the equivalente in latex for this
2799                         //   case is caption
2800                         //   and title should come first
2801                         //         desc_on == 4
2802                         //
2803                         if(desc_on != 3 || i != 0) {
2804                                 if(tmp_out[0] == '@') {
2805                                         if(desc_on == 4)
2806                                                 extra += frontStrip(tmp_out,
2807                                                                     '@');
2808                                         else
2809                                                 os << frontStrip(tmp_out,
2810                                                                  '@');
2811                                 } else
2812                                         os << tmp_out;
2813                         }
2814                 } else if (font2.latex() == LyXFont::ON) {
2815                         // "TeX"-Mode on == > SGML-Mode on.
2816                         if (c != '\0')
2817                                 os << c;
2818                         ++char_line_count;
2819                 } else {
2820                         string sgml_string;
2821                         if (linuxDocConvertChar(c, sgml_string) 
2822                             && !style.free_spacing) {
2823                                 // in freespacing mode, spaces are
2824                                 // non-breaking characters
2825                                 // char is ' '
2826                                 if (desc_on == 1) {
2827                                         ++char_line_count;
2828                                         os << '\n'
2829                                            << "</term><listitem><para>";
2830                                         desc_on = 2;
2831                                 } else  {
2832                                         os << c;
2833                                 }
2834                         } else {
2835                                 os << sgml_string;
2836                         }
2837                 }
2838                 font1 = font2;
2839         }
2840         
2841         // Needed if there is an optional argument but no contents.
2842         if (main_body > 0 && main_body == size()) {
2843                 font1 = style.font;
2844         }
2845
2846         if (emph_flag) {
2847                 os << "</emphasis>";
2848         }
2849         
2850         ++current_cell_number;
2851         tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2852         // Resets description flag correctly.
2853         switch(desc_on){
2854         case 1:
2855                 // <term> not closed...
2856                 os << "</term>";
2857                 break;
2858         }
2859         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2860                 os << "</INFORMALTABLE>";
2861         os << '\n';
2862         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
2863                              << this << endl;
2864 }
2865
2866
2867 void LyXParagraph::DocBookContTableRows(ostream & os, string & extra,
2868                                         int & desc_on,
2869                                         LyXParagraph::size_type i,
2870                                         int current_cell_number, int &column) 
2871
2872 {
2873         if (!table) return;
2874         
2875         lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
2876
2877         LyXFont font2;
2878         char c;
2879         Inset * inset;
2880         //string emph = "emphasis";
2881         bool emph_flag = false;
2882         int char_line_count = 0;
2883         
2884         LyXLayout const & style =
2885                 textclasslist.Style(current_view->buffer()->params.textclass,
2886                                     GetLayout());
2887         
2888         size_type main_body;
2889         if (style.labeltype != LABEL_MANUAL)
2890                 main_body = 0;
2891         else
2892                 main_body = BeginningOfMainBody();
2893         
2894         // Gets paragraph main font.
2895         LyXFont font1;
2896         if (main_body > 0)
2897                 font1 = style.labelfont;
2898         else
2899                 font1 = style.font;
2900         
2901         size_type lastpos = i;
2902         int cell = table->CellHasContRow(current_cell_number);
2903         ++current_cell_number;
2904         while(cell >= 0) {
2905                 // first find the right position
2906                 i = lastpos;
2907                 for (; i < size() && current_cell_number < cell; ++i) {
2908                         c = GetChar(i);
2909                         if (c == LyXParagraph::META_NEWLINE)
2910                                 ++current_cell_number;
2911                 }
2912                 lastpos = i;
2913                 c = GetChar(i);
2914                 // I don't know how to handle this so I comment it
2915                 // for the moment (Jug)
2916 //             if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2917 //                     file += " \\\\\n";
2918 //                     column = 0;
2919 //             } else
2920                 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2921                         os << ' ';
2922                 }
2923
2924                 for (; i < size()
2925                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2926                      ++i) {
2927                         ++column;
2928                         
2929                         // Fully instantiated font
2930                         font2 = getFont(i);
2931                         
2932                         // Handle <emphasis> tag.
2933                         if (font1.emph() != font2.emph() && i) {
2934                                 if (font2.emph() == LyXFont::ON) {
2935                                         os << "<emphasis>";
2936                                         emph_flag= true;
2937                                 } else if (emph_flag) {
2938                                         os << "</emphasis>";
2939                                         emph_flag= false;
2940                                 }
2941                         }
2942                         if (c == LyXParagraph::META_INSET) {
2943                                 inset = GetInset(i);
2944 #ifdef HAVE_SSTREAM
2945                                 ostringstream ost;
2946                                 inset->DocBook(ost);
2947                                 string tmp_out = ost.str().c_str();
2948 #else
2949                                 ostrstream ost;
2950                                 inset->DocBook(ost);
2951                                 ost << '\0';
2952                                 char * ctmp = ost.str();
2953                                 string tmp_out(ctmp);
2954                                 delete [] ctmp;
2955 #endif
2956                                 //
2957                                 // This code needs some explanation:
2958                                 // Two insets are treated specially
2959                                 //   label if it is the first element in a
2960                                 //   command paragraph
2961                                 //       desc_on == 3
2962                                 //   graphics inside tables or figure floats
2963                                 //   can't go on title (the equivalente in
2964                                 //   latex for this case is caption and title
2965                                 //   should come first
2966                                 //       desc_on == 4
2967                                 //
2968                                 if(desc_on != 3 || i != 0) {
2969                                         if(tmp_out[0] == '@') {
2970                                                 if(desc_on == 4)
2971                                                         extra += frontStrip(tmp_out, '@');
2972                                                 else
2973                                                         os << frontStrip(tmp_out, '@');
2974                                         } else
2975                                                 os << tmp_out;
2976                                 }
2977                         } else if (font2.latex() == LyXFont::ON) {
2978                                 // "TeX"-Mode on == > SGML-Mode on.
2979                                 if (c!= '\0')
2980                                         os << c;
2981                                 ++char_line_count;
2982                         } else {
2983                                 string sgml_string;
2984                                 if (linuxDocConvertChar(c, sgml_string) 
2985                                     && !style.free_spacing) {
2986                                         // in freespacing mode, spaces are
2987                                         // non-breaking characters
2988                                         // char is ' '
2989                                         if (desc_on == 1) {
2990                                                 ++char_line_count;
2991                                                 os << '\n'
2992                                                    << "</term><listitem><para>";
2993                                                 desc_on = 2;
2994                                         } else  {
2995                                                 os << c;
2996                                         }
2997                                 } else {
2998                                         os << sgml_string;
2999                                 }
3000                         }
3001                 }
3002                 // we have only to control for emphasis open here!
3003                 if (emph_flag) {
3004                         os << "</emphasis>";
3005                         emph_flag= false;
3006                 }
3007                 font1 = font2 = getFont(-1);
3008                 cell = table->CellHasContRow(current_cell_number);
3009         }
3010         lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3011 }
3012
3013
3014 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
3015                                    LyXParagraph::size_type const i,
3016                                    int & column, LyXFont const & font,
3017                                    LyXLayout const & style)
3018 {
3019         if (column > tex_code_break_column
3020             && i 
3021             && GetChar(i - 1) != ' '
3022             && (i < size() - 1)
3023             // In LaTeX mode, we don't want to
3024             // break lines since some commands
3025             // do not like this
3026             && ! (font.latex() == LyXFont::ON)
3027             // same in FreeSpacing mode
3028             && !style.free_spacing
3029             // In typewriter mode, we want to avoid 
3030             // ! . ? : at the end of a line
3031             && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3032                  && (GetChar(i-1) == '.'
3033                      || GetChar(i-1) == '?' 
3034                      || GetChar(i-1) == ':'
3035                      || GetChar(i-1) == '!'))) {
3036                 if (tex_code_break_column == 0) {
3037                         // in batchmode we need LaTeX to still
3038                         // see it as a space not as an extra '\n'
3039                         os << " %\n";
3040                 } else {
3041                         os << '\n';
3042                 }
3043                 texrow.newline();
3044                 texrow.start(this, i + 1);
3045                 column = 0;
3046         } else if (font.latex() == LyXFont::OFF) {
3047                 if (style.free_spacing) {
3048                         os << '~';
3049                 } else {
3050                         os << ' ';
3051                 }
3052         }
3053 }
3054
3055
3056 void LyXParagraph::SimpleTeXSpecialChars(ostream & os, TexRow & texrow,
3057                                          LyXFont & font,
3058                                          LyXFont & running_font,
3059                                          LyXFont & basefont,
3060                                          bool & open_font,
3061                                          LyXLayout const & style,
3062                                          LyXParagraph::size_type & i,
3063                                          int & column, char const c)
3064 {
3065         // Two major modes:  LaTeX or plain
3066         // Handle here those cases common to both modes
3067         // and then split to handle the two modes separately.
3068         switch (c) {
3069         case LyXParagraph::META_INSET: {
3070                 Inset * inset = GetInset(i);
3071                 if (inset) {
3072                         bool close = false;
3073                         int len = os.tellp();
3074                         if ((inset->LyxCode() == Inset::GRAPHICS_CODE
3075                              || inset->LyxCode() == Inset::MATH_CODE
3076                              || inset->LyxCode() == Inset::URL_CODE)
3077                             && running_font.isRightToLeft()) {
3078                                 os << "\\L{";
3079                                 close = true;
3080                         }
3081
3082                         int tmp = inset->Latex(os, style.isCommand(),
3083                                                style.free_spacing);
3084
3085                         if (close)
3086                                 os << "}";
3087                         
3088                         if (tmp) {
3089                                 column = 0;
3090                         } else {
3091                                 column += os.tellp() - len;
3092                         }
3093                         for (; tmp--;) {
3094                                 texrow.newline();
3095                         }
3096                 }
3097         }
3098         break;
3099
3100         case LyXParagraph::META_NEWLINE:
3101                 if (open_font) {
3102                         column += running_font.latexWriteEndChanges(os,
3103                                                                     basefont,
3104                                                                     basefont);
3105                         open_font = false;
3106                 }
3107                 basefont = getFont(-1);
3108                 running_font = basefont;
3109                 break;
3110
3111         case LyXParagraph::META_HFILL: 
3112                 os << "\\hfill{}";
3113                 column += 7;
3114                 break;
3115
3116         default:
3117                 // And now for the special cases within each mode
3118                 // Are we in LaTeX mode?
3119                 if (font.latex() == LyXFont::ON) {
3120                         // at present we only have one option
3121                         // but I'll leave it as a switch statement
3122                         // so its simpler to extend. (ARRae)
3123                         switch (c) {
3124 #if 0
3125                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
3126                                 os << ' ';
3127                                 break;
3128 #endif
3129                         default:
3130                                 // make sure that we will not print
3131                                 // error generating chars to the tex
3132                                 // file. This test would not be needed
3133                                 // if it were done in the buffer
3134                                 // itself.
3135                                 if (c != '\0') {
3136                                         os << c;
3137                                 }
3138                                 break;
3139                         }
3140                 } else {
3141                         // Plain mode (i.e. not LaTeX)
3142                         switch (c) {
3143 #if 0
3144                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
3145                                 os << '~';
3146                                 break;
3147 #endif
3148                         case '\\': 
3149                                 os << "\\textbackslash{}";
3150                                 column += 15;
3151                                 break;
3152                 
3153                         case '°': case '±': case '²': case '³':  
3154                         case '×': case '÷': case '¹': case 'ª':
3155                         case 'º': case '¬': case 'µ':
3156                                 if (current_view->buffer()->params.inputenc == "latin1") {
3157                                         os << "\\ensuremath{"
3158                                            << c
3159                                            << '}';
3160                                         column += 13;
3161                                 } else {
3162                                         os << c;
3163                                 }
3164                                 break;
3165
3166                         case '|': case '<': case '>':
3167                                 // In T1 encoding, these characters exist
3168                                 if (lyxrc.fontenc == "T1") {
3169                                         os << c;
3170                                         //... but we should avoid ligatures
3171                                         if ((c == '>' || c == '<')
3172                                             && i <= size() - 2
3173                                             && GetChar(i + 1) == c){
3174                                                 os << "\\textcompwordmark{}";
3175                                                 column += 19;
3176                                         }
3177                                         break;
3178                                 }
3179                                 // Typewriter font also has them
3180                                 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3181                                         os << c;
3182                                         break;
3183                                 } 
3184                                 // Otherwise, we use what LaTeX
3185                                 // provides us.
3186                                 switch(c) {
3187                                 case '<':
3188                                         os << "\\textless{}";
3189                                         column += 10;
3190                                         break;
3191                                 case '>':
3192                                         os << "\\textgreater{}";
3193                                         column += 13;
3194                                         break;
3195                                 case '|':
3196                                         os << "\\textbar{}";
3197                                         column += 9;
3198                                         break;
3199                                 }
3200                                 break;
3201
3202                         case '-': // "--" in Typewriter mode -> "-{}-"
3203                                 if (i <= size() - 2
3204                                     && GetChar(i + 1) == '-'
3205                                     && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3206                                         os << "-{}";
3207                                         column += 2;
3208                                 } else {
3209                                         os << '-';
3210                                 }
3211                                 break;
3212
3213                         case '\"': 
3214                                 os << "\\char`\\\"{}";
3215                                 column += 9;
3216                                 break;
3217
3218                         case '£':
3219                                 if (current_view->buffer()->params.inputenc == "default") {
3220                                         os << "\\pounds{}";
3221                                         column += 8;
3222                                 } else {
3223                                         os << c;
3224                                 }
3225                                 break;
3226
3227                         case '$': case '&':
3228                         case '%': case '#': case '{':
3229                         case '}': case '_':
3230                                 os << '\\' << c;
3231                                 column += 1;
3232                                 break;
3233
3234                         case '~':
3235                                 os << "\\textasciitilde{}";
3236                                 column += 16;
3237                                 break;
3238
3239                         case '^':
3240                                 os << "\\textasciicircum{}";
3241                                 column += 17;
3242                                 break;
3243
3244                         case '*': case '[': case ']':
3245                                 // avoid being mistaken for optional arguments
3246                                 os << '{' << c << '}';
3247                                 column += 2;
3248                                 break;
3249
3250                         case ' ':
3251                                 // Blanks are printed before font switching.
3252                                 // Sure? I am not! (try nice-latex)
3253                                 // I am sure it's correct. LyX might be smarter
3254                                 // in the future, but for now, nothing wrong is
3255                                 // written. (Asger)
3256                                 break;
3257
3258                         default:
3259                                 /* idea for labels --- begin*/
3260                                 // Check for "LyX"
3261                                 if (c ==  'L'
3262                                     && i <= size() - 3
3263                                     && font.family() != LyXFont::TYPEWRITER_FAMILY
3264                                     && GetChar(i + 1) == 'y'
3265                                     && GetChar(i + 2) == 'X') {
3266                                         os << "\\LyX{}";
3267                                         i += 2;
3268                                         column += 5;
3269                                 }
3270                                 // Check for "TeX"
3271                                 else if (c == 'T'
3272                                          && i <= size() - 3
3273                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3274                                          && GetChar(i + 1) == 'e'
3275                                          && GetChar(i + 2) == 'X') {
3276                                         os << "\\TeX{}";
3277                                         i += 2;
3278                                         column += 5;
3279                                 }
3280                                 // Check for "LaTeX2e"
3281                                 else if (c == 'L'
3282                                          && i <= size() - 7
3283                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3284                                          && GetChar(i + 1) == 'a'
3285                                          && GetChar(i + 2) == 'T'
3286                                          && GetChar(i + 3) == 'e'
3287                                          && GetChar(i + 4) == 'X'
3288                                          && GetChar(i + 5) == '2'
3289                                          && GetChar(i + 6) == 'e') {
3290                                         os << "\\LaTeXe{}";
3291                                         i += 6;
3292                                         column += 8;
3293                                 }
3294                                 // Check for "LaTeX"
3295                                 else if (c == 'L'
3296                                          && i <= size() - 5
3297                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3298                                          && GetChar(i + 1) == 'a'
3299                                          && GetChar(i + 2) == 'T'
3300                                          && GetChar(i + 3) == 'e'
3301                                          && GetChar(i + 4) == 'X') {
3302                                         os << "\\LaTeX{}";
3303                                         i += 4;
3304                                         column += 7;
3305                                         /* idea for labels --- end*/ 
3306                                 } else if (c != '\0') {
3307                                         os << c;
3308                                 }
3309                                 break;
3310                         }
3311                 }
3312         }
3313 }
3314
3315
3316 #if 0
3317 bool LyXParagraph::RoffContTableRows(ostream & os,
3318                                      LyXParagraph::size_type i,
3319                                      int actcell)
3320 {
3321         if (!table)
3322                 return false;
3323
3324         LyXFont font1(LyXFont::ALL_INHERIT);
3325         LyXFont font2;
3326         Inset * inset;
3327         char c;
3328
3329         string fname2 = TmpFileName(string(), "RAT2");
3330         int lastpos = i;
3331         int cell = table->CellHasContRow(actcell);
3332         ++actcell;
3333         while(cell >= 0) {
3334                 // first find the right position
3335                 i = lastpos;
3336                 for (; i < size() && actcell < cell; ++i) {
3337                         c = GetChar(i);
3338                         if (c == LyXParagraph::META_NEWLINE)
3339                                 ++actcell;
3340                 }
3341                 lastpos = i;
3342                 c = GetChar(i);
3343                 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3344                         os << " ";
3345                 for (; i < size()
3346                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3347                      ++i) {
3348                         font2 = GetFontSettings(i);
3349                         if (font1.latex() != font2.latex()) {
3350                                 if (font2.latex() != LyXFont::OFF)
3351                                         continue;
3352                         }
3353                         c = GetChar(i);
3354                         switch (c) {
3355                         case LyXParagraph::META_INSET:
3356                                 if ((inset = GetInset(i))) {
3357 #if 1
3358 #ifdef HAVE_SSTREAM
3359                                         stringstream ss(ios::in | ios::out);
3360                                         inset->Latex(ss, -1);
3361                                         ss.seekp(0);
3362                                         ss.get(c);
3363                                         while (!ss) {
3364                                                 if (c == '\\')
3365                                                         os << "\\\\";
3366                                                 else
3367                                                         os << c;
3368                                                 ss.get(c);
3369                                         }
3370 #else
3371                                         strstream ss;
3372                                         inset->Latex(ss, -1);
3373                                         ss.seekp(0);
3374                                         ss.get(c);
3375                                         while (!ss) {
3376                                                 if (c == '\\')
3377                                                         os << "\\\\";
3378                                                 else
3379                                                         os << c;
3380                                                 ss.get(c);
3381                                         }
3382                                         delete [] ss.str();
3383 #endif
3384 #else
3385                                         fstream fs(fname2.c_str(),
3386                                                    ios::in|ios::out);
3387                                         if (!fs) {
3388                                                 WriteAlert(_("LYX_ERROR:"),
3389                                                            _("Cannot open temporary file:"),
3390                                                            fname2);
3391                                                 return false;
3392                                         }
3393                                         inset->Latex(fs, -1);
3394                                         fs.seekp(0);
3395                                         fs.get(c);
3396                                         while (!fs) {
3397                                                 if (c == '\\')
3398                                                         os << "\\\\";
3399                                                 else
3400                                                         os << c;
3401                                                 fs.get(c);
3402                                         }
3403                                         fs.close();
3404 #endif
3405                                 }
3406                                 break;
3407                         case LyXParagraph::META_NEWLINE:
3408                                 break;
3409                         case LyXParagraph::META_HFILL: 
3410                                 break;
3411 #if 0
3412                         case LyXParagraph::META_PROTECTED_SEPARATOR:
3413                                 break;
3414 #endif
3415                         case '\\': 
3416                                 os << "\\\\";
3417                                 break;
3418                         default:
3419                                 if (c != '\0')
3420                                         os << c;
3421                                 else
3422                                         lyxerr.debug() << "RoffAsciiTable: "
3423                                                 "NULL char in structure."
3424                                                        << endl;
3425                                 break;
3426                         }
3427                 }
3428                 cell = table->CellHasContRow(actcell);
3429         }
3430         return true;
3431 }
3432 #endif
3433
3434
3435 LyXParagraph * LyXParagraph::TeXDeeper(ostream & os, TexRow & texrow,
3436                                        ostream & foot, TexRow & foot_texrow,
3437                                        int & foot_count)
3438 {
3439         lyxerr[Debug::LATEX] << "TeXDeeper...     " << this << endl;
3440         LyXParagraph * par = this;
3441
3442         while (par && par->depth == depth) {
3443                 if (par->IsDummy())
3444                         lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3445                 if (textclasslist.Style(current_view->buffer()->params.textclass, 
3446                                         par->layout).isEnvironment()
3447                     || par->pextra_type != PEXTRA_NONE) {
3448                         par = par->TeXEnvironment(os, texrow,
3449                                                   foot, foot_texrow,
3450                                                   foot_count);
3451                 } else {
3452                         par = par->TeXOnePar(os, texrow,
3453                                              foot, foot_texrow,
3454                                              foot_count);
3455                 }
3456         }
3457         lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3458
3459         return par;
3460 }
3461
3462
3463 LyXParagraph * LyXParagraph::TeXEnvironment(ostream & os, TexRow & texrow,
3464                                             ostream & foot,
3465                                             TexRow & foot_texrow,
3466                                             int & foot_count)
3467 {
3468         bool eindent_open = false;
3469         bool foot_this_level = false;
3470         // flags when footnotetext should be appended to file.
3471         static bool minipage_open = false;
3472         static int minipage_open_depth = 0;
3473         char par_sep = current_view->buffer()->params.paragraph_separation;
3474     
3475         lyxerr[Debug::LATEX] << "TeXEnvironment...     " << this << endl;
3476         if (IsDummy())
3477                 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3478
3479         LyXLayout const & style =
3480                 textclasslist.Style(current_view->buffer()->params.textclass,
3481                                     layout);
3482        
3483         if (pextra_type == PEXTRA_INDENT) {
3484                 if (!pextra_width.empty()) {
3485                         os << "\\begin{LyXParagraphIndent}{"
3486                            << pextra_width << "}\n";
3487                 } else {
3488                         //float ib = atof(pextra_widthp.c_str())/100;
3489                         // string can't handle floats at present (971109)
3490                         // so I'll do a conversion by hand knowing that
3491                         // the limits are 0.0 to 1.0. ARRae.
3492                         os << "\\begin{LyXParagraphIndent}{";
3493                         switch (pextra_widthp.length()) {
3494                         case 3:
3495                                 os << "1.00";
3496                                 break;
3497                         case 2:
3498                                 os << "0."
3499                                    << pextra_widthp;
3500                                 break;
3501                         case 1:
3502                                 os << "0.0"
3503                                    << pextra_widthp;
3504                         }
3505                         os << "\\columnwidth}\n";
3506                 }
3507                 texrow.newline();
3508                 eindent_open = true;
3509         }
3510         if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3511                 if (pextra_hfill && Previous() &&
3512                     (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3513                         os << "\\hfill{}\n";
3514                         texrow.newline();
3515                 }
3516                 if (par_sep == BufferParams::PARSEP_INDENT) {
3517                         os << "{\\setlength\\parindent{0pt}\n";
3518                         texrow.newline();
3519                 }
3520                 os << "\\begin{minipage}";
3521                 switch(pextra_alignment) {
3522                 case MINIPAGE_ALIGN_TOP:
3523                         os << "[t]";
3524                         break;
3525                 case MINIPAGE_ALIGN_MIDDLE:
3526                         os << "[m]";
3527                         break;
3528                 case MINIPAGE_ALIGN_BOTTOM:
3529                         os << "[b]";
3530                         break;
3531                 }
3532                 if (!pextra_width.empty()) {
3533                         os << '{' << pextra_width << "}\n";
3534                 } else {
3535                         //float ib = atof(par->pextra_width.c_str())/100;
3536                         // string can't handle floats at present
3537                         // so I'll do a conversion by hand knowing that
3538                         // the limits are 0.0 to 1.0. ARRae.
3539                         os << '{';
3540                         switch (pextra_widthp.length()) {
3541                         case 3:
3542                                 os << "1.00";
3543                                 break;
3544                         case 2:
3545                                 os << "0."
3546                                    << pextra_widthp;
3547                                 break;
3548                         case 1:
3549                                 os << "0.0"
3550                                    << pextra_widthp;
3551                         }
3552                         os << "\\columnwidth}\n";
3553                 }
3554                 texrow.newline();
3555                 if (par_sep == BufferParams::PARSEP_INDENT) {
3556                         os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3557                         texrow.newline();
3558                 }
3559                 minipage_open = true;
3560                 minipage_open_depth = depth;
3561         }
3562
3563 #ifdef WITH_WARNINGS
3564 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3565         //I disabled it because it breaks when lists span on several
3566         //pages (JMarc)
3567 #endif
3568         if (style.isEnvironment()){
3569                 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3570 #ifdef FANCY_FOOTNOTE_CODE
3571                         if (foot_count < 0) {
3572                                 // flag that footnote[mark][text] should be
3573                                 // used for any footnotes from now on
3574                                 foot_count = 0;
3575                                 foot_this_level = true;
3576                         }
3577 #endif
3578                         os << "\\begin{" << style.latexname() << "}{"
3579                            << labelwidthstring << "}\n";
3580                 } else if (style.labeltype == LABEL_BIBLIO) {
3581                         // ale970405
3582                         os << "\\begin{" << style.latexname() << "}{"
3583                            << bibitemWidthest(current_view->painter())
3584                            << "}\n";
3585                 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3586 #ifdef FANCY_FOOTNOTE_CODE
3587                         if (foot_count < 0) {
3588                                 // flag that footnote[mark][text] should be
3589                                 // used for any footnotes from now on
3590                                 foot_count = 0;
3591                                 foot_this_level = true;
3592                         }
3593 #endif
3594                         os << "\\begin{" << style.latexname() << '}'
3595                            << style.latexparam() << '\n';
3596                 } else 
3597                         os << "\\begin{" << style.latexname() << '}'
3598                            << style.latexparam() << '\n';
3599                 texrow.newline();
3600         }
3601         LyXParagraph * par = this;
3602         do {
3603                 par = par->TeXOnePar(os, texrow,
3604                                      foot, foot_texrow, foot_count);
3605
3606                 if (minipage_open && par && !style.isEnvironment() &&
3607                     (par->pextra_type == PEXTRA_MINIPAGE) &&
3608                     par->pextra_start_minipage) {
3609                         os << "\\end{minipage}\n";
3610                         texrow.newline();
3611                         if (par_sep == BufferParams::PARSEP_INDENT) {
3612                                 os << "}\n";
3613                                 texrow.newline();
3614                         }
3615                         minipage_open = false;
3616                 }
3617                 if (par && par->depth > depth) {
3618                         if (textclasslist.Style(current_view->buffer()->params.textclass,
3619                                                 par->layout).isParagraph()
3620                             && !par->table
3621                             // Thinko!
3622                             // How to handle this? (Lgb)
3623                             //&& !suffixIs(os, "\n\n")
3624                                 ) {
3625                                 // There should be at least one '\n' already
3626                                 // but we need there to be two for Standard 
3627                                 // paragraphs that are depth-increment'ed to be
3628                                 // output correctly.  However, tables can
3629                                 // also be paragraphs so don't adjust them.
3630                                 // ARRae
3631                                 // Thinkee:
3632                                 // Will it ever harm to have one '\n' too
3633                                 // many? i.e. that we sometimes will have
3634                                 // three in a row. (Lgb)
3635                                 os << '\n';
3636                                 texrow.newline();
3637                         }
3638                         par = par->TeXDeeper(os, texrow,
3639                                              foot, foot_texrow, foot_count);
3640                 }
3641                 if (par && par->layout == layout && par->depth == depth &&
3642                     (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3643                         if (par->pextra_hfill && par->Previous() &&
3644                             (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3645                                 os << "\\hfill{}\n";
3646                                 texrow.newline();
3647                         }
3648                         if (par_sep == BufferParams::PARSEP_INDENT) {
3649                                 os << "{\\setlength\\parindent{0pt}\n";
3650                                 texrow.newline();
3651                         }
3652                         os << "\\begin{minipage}";
3653                         switch(par->pextra_alignment) {
3654                         case MINIPAGE_ALIGN_TOP:
3655                                 os << "[t]";
3656                                 break;
3657                         case MINIPAGE_ALIGN_MIDDLE:
3658                                 os << "[m]";
3659                                 break;
3660                         case MINIPAGE_ALIGN_BOTTOM:
3661                                 os << "[b]";
3662                                 break;
3663                         }
3664                         if (!par->pextra_width.empty()) {
3665                                 os << '{' << par->pextra_width << "}\n";
3666                         } else {
3667                                 //float ib = atof(par->pextra_widthp.c_str())/100;
3668                                 // string can't handle floats at present
3669                                 // so I'll do a conversion by hand knowing that
3670                                 // the limits are 0.0 to 1.0. ARRae.
3671                                 os << '{';
3672                                 switch (par->pextra_widthp.length()) {
3673                                 case 3:
3674                                         os << "1.00";
3675                                         break;
3676                                 case 2:
3677                                         os << "0." << par->pextra_widthp;
3678                                         break;
3679                                 case 1:
3680                                         os << "0.0" << par->pextra_widthp;
3681                                 }
3682                                 os << "\\columnwidth}\n";
3683                         }
3684                         texrow.newline();
3685                         if (par_sep == BufferParams::PARSEP_INDENT) {
3686                                 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3687                                 texrow.newline();
3688                         }
3689                         minipage_open = true;
3690                         minipage_open_depth = par->depth;
3691                 }
3692         } while (par
3693                  && par->layout == layout
3694                  && par->depth == depth
3695                  && par->pextra_type == pextra_type);
3696  
3697         if (style.isEnvironment()) {
3698                 os << "\\end{" << style.latexname() << '}';
3699                 // maybe this should go after the minipage closes?
3700                 if (foot_this_level) {
3701                         if (foot_count >= 1) {
3702                                 if (foot_count > 1) {
3703                                         os << "\\addtocounter{footnote}{-"
3704                                            << foot_count - 1
3705                                            << '}';
3706                                 }
3707                                 os << foot;
3708                                 texrow += foot_texrow;
3709                                 foot.clear();
3710                                 foot_texrow.reset();
3711                                 foot_count = 0;
3712                         }
3713                 }
3714         }
3715         if (minipage_open && (minipage_open_depth == depth) &&
3716             (!par || par->pextra_start_minipage ||
3717              par->pextra_type != PEXTRA_MINIPAGE)) {
3718                 os << "\\end{minipage}\n";
3719                 texrow.newline();
3720                 if (par_sep == BufferParams::PARSEP_INDENT) {
3721                         os << "}\n";
3722                         texrow.newline();
3723                 }
3724                 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3725                         os << "\\medskip\n\n";
3726                         texrow.newline();
3727                         texrow.newline();
3728                 }
3729                 minipage_open = false;
3730         }
3731         if (eindent_open) {
3732                 os << "\\end{LyXParagraphIndent}\n";
3733                 texrow.newline();
3734         }
3735         if (!(par && (par->pextra_type == PEXTRA_MINIPAGE) 
3736               && par->pextra_hfill)) {
3737                 os << '\n';
3738                 texrow.newline();
3739         }
3740         lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3741         return par;  // ale970302
3742 }
3743
3744
3745 LyXParagraph * LyXParagraph::TeXFootnote(ostream & os, TexRow & texrow,
3746                                          ostream & foot, TexRow & foot_texrow,
3747                                          int & foot_count,
3748                                          LyXDirection parent_direction)
3749 {
3750         lyxerr[Debug::LATEX] << "TeXFootnote...  " << this << endl;
3751         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3752                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3753                         "No footnote!" << endl;
3754
3755         LyXParagraph * par = this;
3756         LyXLayout const & style =
3757                 textclasslist.Style(current_view->buffer()->params.textclass, 
3758                                     previous->GetLayout());
3759         
3760         if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3761                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3762                         "Float other than footnote in command"
3763                         " with moving argument is illegal" << endl;
3764         }
3765
3766         if (footnotekind != LyXParagraph::FOOTNOTE
3767             && footnotekind != LyXParagraph::MARGIN
3768             && os.tellp()
3769             // Thinko
3770             // How to solve this?
3771             //&& !suffixIs(file, '\n')
3772                 ) {
3773                 // we need to ensure that real floats like tables and figures
3774                 // have their \begin{} on a new line otherwise we can get
3775                 // incorrect results when using the endfloat.sty package
3776                 // especially if two floats follow one another.  ARRae 981022
3777                 // NOTE: if the file is length 0 it must have just been
3778                 //       written out so we assume it ended with a '\n'
3779                 // Thinkee:
3780                 // As far as I can see there is never any harm in writing
3781                 // a '\n' too much. Please tell me if I am wrong. (Lgb)
3782                 os << '\n';
3783                 texrow.newline();
3784         }
3785
3786         bool need_closing = false;
3787         LyXDirection direction = getParDirection();
3788         if (direction != parent_direction) {
3789                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
3790                         os << "\\L{";
3791                 else
3792                         os << "\\R{";
3793                 need_closing = true;
3794         }
3795         
3796         BufferParams * params = &current_view->buffer()->params;
3797         bool footer_in_body = true;
3798         switch (footnotekind) {
3799         case LyXParagraph::FOOTNOTE:
3800                 if (style.intitle) {
3801                         os << "\\thanks{\n";
3802                         footer_in_body = false;
3803                 } else {
3804                         if (foot_count == -1) {
3805                                 // we're at depth 0 so we can use:
3806                                 os << "\\footnote{%\n";
3807                                 footer_in_body = false;
3808                         } else {
3809                                 os << "\\footnotemark{}%\n";
3810                                 if (foot_count) {
3811                                         // we only need this when there are
3812                                         // multiple footnotes
3813                                         os << "\\stepcounter{footnote}";
3814                                 }
3815                                 os << "\\footnotetext{%\n";
3816                                 foot_texrow.start(this, 0);
3817                                 foot_texrow.newline();
3818                                 ++foot_count;
3819                         }
3820                 }
3821                 break;
3822         case LyXParagraph::MARGIN:
3823                 os << "\\marginpar{\n";
3824                 break;
3825         case LyXParagraph::FIG:
3826                 if (pextra_type == PEXTRA_FLOATFLT
3827                     && (!pextra_width.empty()
3828                         || !pextra_widthp.empty())) {
3829                         if (!pextra_width.empty())
3830                                 os << "\\begin{floatingfigure}{"
3831                                    << pextra_width << "}\n";
3832                         else
3833                                 os << "\\begin{floatingfigure}{"
3834                                    << atoi(pextra_widthp.c_str())/100.0
3835                                    << "\\textwidth}\n";
3836                 } else {
3837                         os << "\\begin{figure}";
3838                         if (!params->float_placement.empty()) { 
3839                                 os << '[' << params->float_placement << "]\n";
3840                         } else {
3841                                 os << '\n';
3842                         }
3843                 }
3844                 break;
3845         case LyXParagraph::TAB:
3846                 os << "\\begin{table}";
3847                 if (!params->float_placement.empty()) { 
3848                         os << '[' << params->float_placement << "]\n";
3849                 } else {
3850                         os << '\n';
3851                 }
3852                 break;
3853         case LyXParagraph::WIDE_FIG:
3854                 os << "\\begin{figure*}";
3855                 if (!params->float_placement.empty()) { 
3856                         os << '[' << params->float_placement << "]\n";
3857                 } else {
3858                         os << '\n';
3859                 }
3860                 break;
3861         case LyXParagraph::WIDE_TAB:
3862                 os << "\\begin{table*}";
3863                 if (!params->float_placement.empty()) { 
3864                         os << '[' << params->float_placement << "]\n";
3865                 } else {
3866                         os << '\n';
3867                 }
3868                 break;
3869         case LyXParagraph::ALGORITHM:
3870                 os << "\\begin{algorithm}\n";
3871                 break;
3872         }
3873         texrow.newline();
3874    
3875         if (footnotekind != LyXParagraph::FOOTNOTE
3876             || !footer_in_body) {
3877                 // Process text for all floats except footnotes in body
3878                 do {
3879                         LyXLayout const & style =
3880                                 textclasslist
3881                                 .Style(current_view->buffer()->params
3882                                        .textclass,
3883                                        par->layout);
3884                         if (par->IsDummy())
3885                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3886                                        << endl;
3887                         if (style.isEnvironment()
3888                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3889                                 // Allows the use of minipages within float
3890                                 // environments. Shouldn't be circular because
3891                                 // we don't support footnotes inside
3892                                 // floats (yet). ARRae
3893                                 par = par->TeXEnvironment(os, texrow,
3894                                                           foot, foot_texrow,
3895                                                           foot_count);
3896                         } else {
3897                                 par = par->TeXOnePar(os, texrow,
3898                                                      foot, foot_texrow,
3899                                                      foot_count);
3900                         }
3901                         
3902                         if (par && !par->IsDummy() && par->depth > depth) {
3903                                 par = par->TeXDeeper(os, texrow,
3904                                                      foot, foot_texrow,
3905                                                      foot_count);
3906                         }
3907                 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3908         } else {
3909                 // process footnotes > depth 0 or in environments separately
3910                 // NOTE: Currently don't support footnotes within footnotes
3911                 //       even though that is possible using the \footnotemark
3912 #ifdef HAVE_SSTREAM
3913                 ostringstream dummy;
3914 #else
3915                 ostrstream dummy;
3916 #endif
3917                 TexRow dummy_texrow;
3918                 int dummy_count = 0;
3919                 do {
3920                         LyXLayout const & style =
3921                                 textclasslist
3922                                 .Style(current_view->buffer()->params
3923                                        .textclass,
3924                                        par->layout);
3925                         if (par->IsDummy())
3926                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3927                                        << endl;
3928                         if (style.isEnvironment()
3929                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3930                                 // Allows the use of minipages within float
3931                                 // environments. Shouldn't be circular because
3932                                 // we don't support footnotes inside
3933                                 // floats (yet). ARRae
3934                                 par = par->TeXEnvironment(foot, foot_texrow,
3935                                                           dummy, dummy_texrow,
3936                                                           dummy_count);
3937                         } else {
3938                                 par = par->TeXOnePar(foot, foot_texrow,
3939                                                      dummy, dummy_texrow,
3940                                                      dummy_count);
3941                         }
3942
3943                         if (par && !par->IsDummy() && par->depth > depth) {
3944                                 par = par->TeXDeeper(foot, foot_texrow,
3945                                                      dummy, dummy_texrow,
3946                                                      dummy_count);
3947                         }
3948                 } while (par
3949                          && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3950                 if (dummy_count) {
3951                         lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3952                                 "Footnote in a Footnote -- not supported"
3953                                << endl;
3954                 }
3955 #ifndef HAVE_OSTREAM
3956                 delete [] dummy.str();
3957 #endif
3958         }
3959
3960         switch (footnotekind) {
3961         case LyXParagraph::FOOTNOTE:
3962                 if (footer_in_body) {
3963                         // This helps tell which of the multiple
3964                         // footnotetexts an error was in.
3965                         foot << "}%\n";
3966                         foot_texrow.newline();
3967                 } else {
3968                         os << '}';
3969                 }
3970                 break;
3971         case LyXParagraph::MARGIN:
3972                 os << '}';
3973                 break;
3974         case LyXParagraph::FIG:
3975                 if (pextra_type == PEXTRA_FLOATFLT
3976                     && (!pextra_width.empty()
3977                         || !pextra_widthp.empty()))
3978                         os << "\\end{floatingfigure}";
3979                 else
3980                         os << "\\end{figure}";
3981                 break;
3982         case LyXParagraph::TAB:
3983                 os << "\\end{table}";
3984                 break;
3985         case LyXParagraph::WIDE_FIG:
3986                 os << "\\end{figure*}";
3987                 break;
3988         case LyXParagraph::WIDE_TAB:
3989                 os << "\\end{table*}";
3990                 break;
3991         case LyXParagraph::ALGORITHM:
3992                 os << "\\end{algorithm}";
3993                 break;
3994         }
3995
3996         if (need_closing)
3997                 os << "}";
3998
3999         if (footnotekind != LyXParagraph::FOOTNOTE
4000             && footnotekind != LyXParagraph::MARGIN) {
4001                 // we need to ensure that real floats like tables and figures
4002                 // have their \end{} on a line of their own otherwise we can
4003                 // get incorrect results when using the endfloat.sty package.
4004                 os << "\n";
4005                 texrow.newline();
4006         }
4007
4008         lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4009         return par;
4010 }
4011
4012
4013 void LyXParagraph::SetPExtraType(int type, char const * width,
4014                                  char const * widthp)
4015 {
4016         pextra_type = type;
4017         pextra_width = width;
4018         pextra_widthp = widthp;
4019
4020         if (textclasslist.Style(current_view->buffer()->params.textclass, 
4021                                 layout).isEnvironment()) {
4022                 LyXParagraph
4023                         * par = this,
4024                         * ppar = par;
4025
4026                 while (par && (par->layout == layout)
4027                        && (par->depth == depth)) {
4028                         ppar = par;
4029                         par = par->Previous();
4030                         if (par)
4031                                 par = par->FirstPhysicalPar();
4032                         while (par && par->depth > depth) {
4033                                 par = par->Previous();
4034                                 if (par)
4035                                         par = par->FirstPhysicalPar();
4036                         }
4037                 }
4038                 par = ppar;
4039                 while (par && (par->layout == layout)
4040                        && (par->depth == depth)) {
4041                         par->pextra_type = type;
4042                         par->pextra_width = width;
4043                         par->pextra_widthp = widthp;
4044                         par = par->NextAfterFootnote();
4045                         if (par && (par->depth > depth))
4046                                 par->SetPExtraType(type, width, widthp);
4047                         while (par && ((par->depth > depth) || par->IsDummy()))
4048                                 par = par->NextAfterFootnote();
4049                 }
4050         }
4051 }
4052
4053
4054 void LyXParagraph::UnsetPExtraType()
4055 {
4056         if (pextra_type == PEXTRA_NONE)
4057                 return;
4058     
4059         pextra_type = PEXTRA_NONE;
4060         pextra_width.clear();
4061         pextra_widthp.clear();
4062
4063         if (textclasslist.Style(current_view->buffer()->params.textclass, 
4064                                 layout).isEnvironment()) {
4065                 LyXParagraph
4066                         * par = this,
4067                         * ppar = par;
4068
4069                 while (par && (par->layout == layout)
4070                        && (par->depth == depth)) {
4071                         ppar = par;
4072                         par = par->Previous();
4073                         if (par)
4074                                 par = par->FirstPhysicalPar();
4075                         while (par && par->depth > depth) {
4076                                 par = par->Previous();
4077                                 if (par)
4078                                         par = par->FirstPhysicalPar();
4079                         }
4080                 }
4081                 par = ppar;
4082                 while (par && (par->layout == layout)
4083                        && (par->depth == depth)) {
4084                         par->pextra_type = PEXTRA_NONE;
4085                         par->pextra_width.clear();
4086                         par->pextra_widthp.clear();
4087                         par = par->NextAfterFootnote();
4088                         if (par && (par->depth > depth))
4089                                 par->UnsetPExtraType();
4090                         while (par && ((par->depth > depth) || par->IsDummy()))
4091                                 par = par->NextAfterFootnote();
4092                 }
4093         }
4094 }
4095
4096
4097 bool LyXParagraph::IsHfill(size_type pos) const
4098 {
4099         return IsHfillChar(GetChar(pos));
4100 }
4101
4102
4103 bool LyXParagraph::IsInset(size_type pos) const
4104 {
4105         return IsInsetChar(GetChar(pos));
4106 }
4107
4108
4109 bool LyXParagraph::IsFloat(size_type pos) const
4110 {
4111         return IsFloatChar(GetChar(pos));
4112 }
4113
4114
4115 bool LyXParagraph::IsNewline(size_type pos) const
4116 {
4117         return pos >= 0 && IsNewlineChar(GetChar(pos));
4118 }
4119
4120
4121 bool LyXParagraph::IsSeparator(size_type pos) const
4122 {
4123         return IsSeparatorChar(GetChar(pos));
4124 }
4125
4126
4127 bool LyXParagraph::IsLineSeparator(size_type pos) const
4128 {
4129         return IsLineSeparatorChar(GetChar(pos));
4130 }
4131
4132
4133 bool LyXParagraph::IsKomma(size_type pos) const
4134 {
4135         return IsKommaChar(GetChar(pos));
4136 }
4137
4138
4139 /// Used by the spellchecker
4140 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4141 {
4142         unsigned char c = GetChar(pos);
4143         if (IsLetterChar(c))
4144                 return true;
4145         // '\0' is not a letter, allthough every string contains "" (below)
4146         if( c == '\0')
4147                 return false;
4148         // We want to pass the ' and escape chars to ispell
4149         string extra = lyxrc.isp_esc_chars + '\'';
4150         char ch[2];
4151         ch[0] = c;
4152         ch[1] = 0;
4153         return contains(extra, ch);
4154 }
4155  
4156  
4157 bool LyXParagraph::IsWord(size_type pos ) const
4158 {
4159         return IsWordChar(GetChar(pos)) ;
4160 }
4161
4162 Language const * LyXParagraph::getParLanguage() const 
4163 {
4164         if (!table && size() > 0)
4165                 return FirstPhysicalPar()->GetFirstFontSettings().language();
4166         else if (previous)
4167                 return previous->getParLanguage();
4168         else
4169                 return current_view->buffer()->params.language_info;
4170 }
4171
4172 Language const * LyXParagraph::getLetterLanguage(size_type pos) const
4173 {
4174         return GetFontSettings(pos).language();
4175 }
4176
4177 LyXDirection LyXParagraph::getParDirection() const
4178 {
4179         if (!lyxrc.rtl_support || table)
4180                 return LYX_DIR_LEFT_TO_RIGHT;
4181         else if (getParLanguage()->RightToLeft)
4182                 return LYX_DIR_RIGHT_TO_LEFT;
4183         else
4184                 return LYX_DIR_LEFT_TO_RIGHT;
4185 }
4186
4187 LyXDirection
4188 LyXParagraph::getLetterDirection(LyXParagraph::size_type pos) const
4189 {
4190         if (!lyxrc.rtl_support)
4191                 return LYX_DIR_LEFT_TO_RIGHT;
4192         else if (table && IsNewline(pos))
4193                 return LYX_DIR_LEFT_TO_RIGHT;
4194
4195         bool is_rtl =  GetFontSettings(pos).isVisibleRightToLeft();
4196         if (IsLineSeparator(pos) && 0 < pos && pos < Last() - 1
4197             && !IsLineSeparator(pos + 1)
4198             && !(table && IsNewline(pos + 1))
4199             && ( GetFontSettings(pos - 1).isVisibleRightToLeft() != is_rtl
4200                  || GetFontSettings(pos + 1).isVisibleRightToLeft() != is_rtl))
4201                 return getParDirection();
4202         else
4203                 return (is_rtl) ? LYX_DIR_RIGHT_TO_LEFT
4204                         : LYX_DIR_LEFT_TO_RIGHT;
4205 }