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