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