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