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