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