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