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