]> git.lyx.org Git - lyx.git/blob - src/paragraph.C
fix lyxalgo.h, dra pagebreak with text on line, change the math_deco_search a bit
[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 #include "support/lyxmanip.h"
37
38
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(ostream & os, TexRow & texrow,
1871                                        ostream & 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                 os << "\\appendix\n";
1886                 texrow.newline();
1887         }
1888
1889         if (tex_code_break_column && style.isCommand()){
1890                 os << '\n';
1891                 texrow.newline();
1892         }
1893
1894         if (pagebreak_top) {
1895                 os << "\\newpage";
1896                 further_blank_line = true;
1897         }
1898         if (added_space_top.kind() != VSpace::NONE) {
1899                 os << added_space_top.asLatexCommand(current_view->buffer()->params);
1900                 further_blank_line = true;
1901         }
1902       
1903         if (line_top) {
1904                 os << "\\lyxline{\\" << getFont(0).latexSize() << '}'
1905                    << "\\vspace{-1\\parskip}";
1906                 further_blank_line = true;
1907         }
1908
1909         if (further_blank_line){
1910                 os << '\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                         os << "\\unsethebrew\n";
1920                 else
1921                         os << "\\sethebrew\n";
1922                 texrow.newline();
1923         }
1924         
1925
1926         switch (style.latextype) {
1927         case LATEX_COMMAND:
1928                 os << '\\'
1929                    << style.latexname()
1930                    << style.latexparam();
1931                 break;
1932         case LATEX_ITEM_ENVIRONMENT:
1933                 if (bibkey) {
1934                         bibkey->Latex(os, false, false);
1935                 } else
1936                         os << "\\item ";
1937                 break;
1938         case LATEX_LIST_ENVIRONMENT:
1939                 os << "\\item ";
1940                 break;
1941         default:
1942                 break;
1943         }
1944
1945         bool need_par = SimpleTeXOnePar(os, texrow);
1946  
1947         // Spit out footnotes
1948         while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
1949                && par->footnoteflag != footnoteflag) {
1950                 par = par->TeXFootnote(os, texrow,
1951                                        foot, foot_texrow, foot_count,
1952                                        direction);
1953                 par->SimpleTeXOnePar(os, texrow);
1954                 par = par->next;
1955         }
1956
1957         // Make sure that \\par is done with the font of the last
1958         // character if this has another size as the default.
1959         // This is necessary because LaTeX (and LyX on the screen)
1960         // calculates the space between the baselines according
1961         // to this font. (Matthias)
1962         LyXFont font = getFont(Last() - 1);
1963         if (need_par) {
1964                 if (style.resfont.size() != font.size()) {
1965                         os << '\\'
1966                            << font.latexSize()
1967                            << ' ';
1968                 }
1969                 os << "\\par}";
1970         } else if (textclasslist.Style(current_view->buffer()->params.textclass,
1971                                        GetLayout()).isCommand()){
1972                 if (style.resfont.size() != font.size()) {
1973                         os << '\\'
1974                            << font.latexSize()
1975                            << ' ';
1976                 }
1977                 os << '}';
1978         } else if (style.resfont.size() != font.size()){
1979                 os << "{\\" << font.latexSize() << " \\par}";
1980         }
1981
1982         if (direction != global_direction)
1983                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
1984                         os << "\\sethebrew";
1985                 else
1986                         os << "\\unsethebrew";
1987         
1988         switch (style.latextype) {
1989         case LATEX_ITEM_ENVIRONMENT:
1990         case LATEX_LIST_ENVIRONMENT:
1991                 if (par && (depth < par->depth)) {
1992                         os << '\n';
1993                         texrow.newline();
1994                 }
1995                 break;
1996         case LATEX_ENVIRONMENT:
1997                 // if its the last paragraph of the current environment
1998                 // skip it otherwise fall through
1999                 if (par
2000                     && (par->layout != layout
2001                         || par->depth != depth
2002                         || par->pextra_type != pextra_type))
2003                         break;
2004         default:
2005                 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2006                       && footnotekind != LyXParagraph::FOOTNOTE
2007                       && footnotekind != LyXParagraph::MARGIN
2008                       && (table
2009                           || (par
2010                               && par->table)))) {
2011                         // don't insert this if we would be adding it
2012                         // before or after a table in a float.  This 
2013                         // little trick is needed in order to allow
2014                         // use of tables in \subfigures or \subtables.
2015                         os << '\n';
2016                         texrow.newline();
2017                 }
2018         }
2019         
2020         further_blank_line = false;
2021         if (line_bottom) {
2022                 os << "\\lyxline{\\" << getFont(Last() - 1).latexSize() << '}';
2023                 further_blank_line = true;
2024         }
2025
2026         if (added_space_bottom.kind() != VSpace::NONE) {
2027                 os << added_space_bottom.asLatexCommand(current_view->buffer()->params);
2028                 further_blank_line = true;
2029         }
2030       
2031         if (pagebreak_bottom) {
2032                 os << "\\newpage";
2033                 further_blank_line = true;
2034         }
2035
2036         if (further_blank_line){
2037                 os << '\n';
2038                 texrow.newline();
2039         }
2040
2041         if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2042               par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2043                 os << '\n';
2044                 texrow.newline();
2045         }
2046
2047         lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2048         return par;
2049 }
2050
2051
2052 // This one spits out the text of the paragraph
2053 bool LyXParagraph::SimpleTeXOnePar(ostream & os, TexRow & texrow)
2054 {
2055         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...     " << this << endl;
2056
2057         if (table)
2058                 return SimpleTeXOneTablePar(os, texrow);
2059
2060         bool return_value = false;
2061
2062         LyXLayout const & style =
2063                 textclasslist.Style(current_view->buffer()->params.textclass,
2064                                     GetLayout());
2065         LyXFont basefont, last_font;
2066
2067         // Maybe we have to create a optional argument.
2068         size_type main_body;
2069         if (style.labeltype != LABEL_MANUAL)
2070                 main_body = 0;
2071         else
2072                 main_body = BeginningOfMainBody();
2073
2074         if (main_body > 0) {
2075                 os << '[';
2076                 basefont = getFont(-2); // Get label font
2077         } else {
2078                 basefont = getFont(-1); // Get layout font
2079         }
2080
2081         int column = 0;
2082
2083         if (main_body >= 0
2084             && !text.size()
2085             && !IsDummy()) {
2086                 if (style.isCommand()) {
2087                         os << '{';
2088                         ++column;
2089                 } else if (align != LYX_ALIGN_LAYOUT) {
2090                         os << '{';
2091                         ++column;
2092                         return_value = true;
2093                 }
2094         }
2095  
2096         // Which font is currently active?
2097         LyXFont running_font(basefont);
2098         // Do we have an open font change?
2099         bool open_font = false;
2100
2101         texrow.start(this, 0);
2102
2103         for (size_type i = 0; i < size(); ++i) {
2104                 ++column;
2105                 // First char in paragraph or after label?
2106                 if (i == main_body && !IsDummy()) {
2107                         if (main_body > 0) {
2108                                 if (open_font) {
2109                                         column += running_font.latexWriteEndChanges(os, basefont, basefont);
2110                                         open_font = false;
2111                                 }
2112                                 basefont = getFont(-1); // Now use the layout font
2113                                 running_font = basefont;
2114                                 os << ']';
2115                                 ++column;
2116                         }
2117                         if (style.isCommand()) {
2118                                 os << '{';
2119                                 ++column;
2120                         } else if (align != LYX_ALIGN_LAYOUT) {
2121                                 os << "{\\par";
2122                                 column += 4;
2123                                 return_value = true;
2124                         }
2125
2126                         if (noindent) {
2127                                 os << "\\noindent ";
2128                                 column += 10;
2129                         }
2130                         switch (align) {
2131                         case LYX_ALIGN_NONE:
2132                         case LYX_ALIGN_BLOCK:
2133                         case LYX_ALIGN_LAYOUT:
2134                         case LYX_ALIGN_SPECIAL: break;
2135                         case LYX_ALIGN_LEFT:
2136                                 os << "\\raggedright ";
2137                                 column+= 13;
2138                                 break;
2139                         case LYX_ALIGN_RIGHT:
2140                                 os << "\\raggedleft ";
2141                                 column+= 12;
2142                                 break;
2143                         case LYX_ALIGN_CENTER:
2144                                 os << "\\centering ";
2145                                 column+= 11;
2146                                 break;
2147                         }        
2148                 }
2149
2150                 int c = GetChar(i);
2151
2152                 // Fully instantiated font
2153                 LyXFont font = getFont(i);
2154                 last_font = running_font;
2155
2156                 // Spaces at end of font change are simulated to be
2157                 // outside font change, i.e. we write "\textXX{text} "
2158                 // rather than "\textXX{text }". (Asger)
2159                 if (open_font && c == ' ' && i <= size() - 2 
2160                     && !getFont(i+1).equalExceptLatex(running_font) 
2161                     && !getFont(i+1).equalExceptLatex(font)) {
2162                         font = getFont(i + 1);
2163                 }
2164                 // We end font definition before blanks
2165                 if (!font.equalExceptLatex(running_font) && open_font) {
2166                         column += running_font.latexWriteEndChanges(os,
2167                                                                     basefont,
2168                                                                     (i == main_body-1) ? basefont : font);
2169                         running_font = basefont;
2170                         open_font = false;
2171                 }
2172
2173                 // Blanks are printed before start of fontswitch
2174                 if (c == ' '){
2175                         // Do not print the separation of the optional argument
2176                         if (i != main_body - 1) {
2177                                 SimpleTeXBlanks(os, texrow, i,
2178                                                 column, font, style);
2179                         }
2180                 }
2181
2182                 // Do we need to change font?
2183                 if (!font.equalExceptLatex(running_font)
2184                     && i != main_body-1) {
2185                         column += font.latexWriteStartChanges(os, basefont,
2186                                                               last_font);
2187                         running_font = font;
2188                         open_font = true;
2189                 }
2190
2191                 if (c == LyXParagraph::META_NEWLINE) {
2192                         // newlines are handled differently here than
2193                         // the default in SimpleTeXSpecialChars().
2194                         if (!style.newline_allowed
2195                             || font.latex() == LyXFont::ON) {
2196                                 os << '\n';
2197                         } else {
2198                                 if (open_font) {
2199                                         column += running_font.latexWriteEndChanges(os, basefont, basefont);
2200                                         open_font = false;
2201                                 }
2202                                 basefont = getFont(-1);
2203                                 running_font = basefont;
2204                                 if (font.family() == 
2205                                     LyXFont::TYPEWRITER_FAMILY) {
2206                                         os << "~";
2207                                 }
2208                                 os << "\\\\\n";
2209                         }
2210                         texrow.newline();
2211                         texrow.start(this, i + 1);
2212                         column = 0;
2213                 } else {
2214                         SimpleTeXSpecialChars(os, texrow,
2215                                               font, running_font, basefont,
2216                                               open_font, style, i, column, c);
2217                 }
2218         }
2219
2220         // If we have an open font definition, we have to close it
2221         if (open_font) {
2222                 running_font.latexWriteEndChanges(os, basefont, basefont);
2223         }
2224
2225         // Needed if there is an optional argument but no contents.
2226         if (main_body > 0 && main_body == size()) {
2227                 os << "]~";
2228                 return_value = false;
2229         }
2230
2231         lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2232         return return_value;
2233 }
2234
2235
2236 // This one spits out the text of a table paragraph
2237 bool LyXParagraph::SimpleTeXOneTablePar(ostream & os, TexRow & texrow)
2238 {
2239         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...     " << this << endl;
2240    
2241         bool return_value = false;
2242
2243         LyXLayout const & style = 
2244                 textclasslist.Style(current_view->buffer()->params.textclass,
2245                                     GetLayout());
2246  
2247         int column = 0;
2248         if (!IsDummy()) { // it is dummy if it is in a float!!!
2249                 if (style.isCommand()) {
2250                         os << '{';
2251                         ++column;
2252                 } else if (align != LYX_ALIGN_LAYOUT) {
2253                         os << '{';
2254                         ++column;
2255                         return_value = true;
2256                 }
2257                 if (noindent) {
2258                         os << "\\noindent ";
2259                         column += 10;
2260                 }
2261                 switch (align) {
2262                 case LYX_ALIGN_NONE:
2263                 case LYX_ALIGN_BLOCK:
2264                 case LYX_ALIGN_LAYOUT:
2265                 case LYX_ALIGN_SPECIAL: break;
2266                 case LYX_ALIGN_LEFT:
2267                         os << "\\raggedright ";
2268                         column+= 13;
2269                         break;
2270                 case LYX_ALIGN_RIGHT:
2271                         os << "\\raggedleft ";
2272                         column+= 12;
2273                         break;
2274                 case LYX_ALIGN_CENTER:
2275                         os << "\\centering ";
2276                         column+= 11;
2277                         break;
2278                 }
2279         }
2280
2281         LyXFont basefont = getFont(-1); // Get layout font
2282         // Which font is currently active?
2283         LyXFont running_font = basefont;
2284         LyXFont last_font;
2285         // Do we have an open font change?
2286         bool open_font = false;
2287         int current_cell_number = -1;
2288         int tmp = table->TexEndOfCell(os, current_cell_number);
2289         for (; tmp > 0 ; --tmp)
2290                 texrow.newline();
2291         
2292         texrow.start(this, 0);
2293
2294         for (size_type i = 0; i < size(); ++i) {
2295                 char c = GetChar(i);
2296                 if (table->IsContRow(current_cell_number + 1)) {
2297                         if (c == LyXParagraph::META_NEWLINE)
2298                                 ++current_cell_number;
2299                         continue;
2300                 }
2301                 ++column;
2302                 
2303                 // Fully instantiated font
2304                 LyXFont font = getFont(i);
2305                 last_font = running_font;
2306
2307                 // Spaces at end of font change are simulated to be
2308                 // outside font change.
2309                 // i.e. we write "\textXX{text} " rather than
2310                 // "\textXX{text }". (Asger)
2311                 if (open_font && c == ' ' && i <= size() - 2
2312                     && getFont(i + 1) != running_font
2313                     && getFont(i + 1) != font) {
2314                         font = getFont(i + 1);
2315                 }
2316
2317                 // We end font definition before blanks
2318                 if (font != running_font && open_font) {
2319                         column += running_font.latexWriteEndChanges(os,
2320                                                                     basefont,
2321                                                                     font);
2322                         running_font = basefont;
2323                         open_font = false;
2324                 }
2325                 // Blanks are printed before start of fontswitch
2326                 if (c == ' '){
2327                         SimpleTeXBlanks(os, texrow, i, column, font, style);
2328                 }
2329                 // Do we need to change font?
2330                 if (font != running_font) {
2331                         column += font.latexWriteStartChanges(os, basefont,
2332                                                               last_font);
2333                         running_font = font;
2334                         open_font = true;
2335                 }
2336                 // Do we need to turn on LaTeX mode?
2337                 if (font.latex() != running_font.latex()) {
2338                         if (font.latex() == LyXFont::ON
2339                             && style.needprotect) {
2340                                 os << "\\protect ";
2341                                 column += 9;
2342                         }
2343                 }
2344                 if (c == LyXParagraph::META_NEWLINE) {
2345                         // special case for inside a table
2346                         // different from default case in
2347                         // SimpleTeXSpecialChars()
2348                         if (open_font) {
2349                                 column += running_font
2350                                         .latexWriteEndChanges(os, basefont,
2351                                                               basefont);
2352                                 open_font = false;
2353                         }
2354                         basefont = getFont(-1);
2355                         running_font = basefont;
2356                         ++current_cell_number;
2357                         if (table->CellHasContRow(current_cell_number) >= 0) {
2358                                 TeXContTableRows(os, i + 1,
2359                                                  current_cell_number,
2360                                                  column, texrow);
2361                         }
2362                         // if this cell follow only ContRows till end don't
2363                         // put the EndOfCell because it is put after the
2364                         // for(...)
2365                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2366                                 --current_cell_number;
2367                                 break;
2368                         }
2369                         int tmp = table->TexEndOfCell(os,
2370                                                       current_cell_number);
2371                         if (tmp > 0) {
2372                                 column = 0;
2373                         } else if (tmp < 0) {
2374                                 tmp = -tmp;
2375                         }
2376                         for (; tmp--;) {
2377                                 texrow.newline();
2378                         }
2379                         texrow.start(this, i + 1);
2380                 } else {
2381                         SimpleTeXSpecialChars(os, texrow,
2382                                               font, running_font, basefont,
2383                                               open_font, style, i, column, c);
2384                 }
2385         }
2386
2387         // If we have an open font definition, we have to close it
2388         if (open_font) {
2389                 running_font.latexWriteEndChanges(os, basefont, basefont);
2390         }
2391         ++current_cell_number;
2392         tmp = table->TexEndOfCell(os, current_cell_number);
2393         for (; tmp > 0; --tmp)
2394                 texrow.newline();
2395         lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2396         return return_value;
2397 }
2398
2399
2400 // This one spits out the text off ContRows in tables
2401 bool LyXParagraph::TeXContTableRows(ostream & os,
2402                                     LyXParagraph::size_type i,
2403                                     int current_cell_number,
2404                                     int & column, TexRow & texrow)
2405 {
2406         lyxerr[Debug::LATEX] << "TeXContTableRows...     " << this << endl;
2407         if (!table)
2408                 return false;
2409     
2410         char c;
2411    
2412         bool return_value = false;
2413         LyXLayout const & style =
2414                 textclasslist.Style(current_view->buffer()->params.textclass,
2415                                     GetLayout());
2416         LyXFont basefont = getFont(-1); // Get layout font
2417         LyXFont last_font;
2418         // Which font is currently active?
2419         LyXFont running_font = basefont;
2420         // Do we have an open font change?
2421         bool open_font = false;
2422
2423         size_type lastpos = i;
2424         int cell = table->CellHasContRow(current_cell_number);
2425         ++current_cell_number;
2426         while(cell >= 0) {
2427                 // first find the right position
2428                 i = lastpos;
2429                 for (; (i < size()) && (current_cell_number<cell); ++i) {
2430                         c = GetChar(i);
2431                         if (c == LyXParagraph::META_NEWLINE)
2432                                 ++current_cell_number;
2433                 }
2434                 lastpos = i;
2435                 c = GetChar(i);
2436                 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2437                         os << " \\\\\n";
2438                         texrow.newline();
2439                         column = 0;
2440                 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2441                         os << ' ';
2442                 }
2443
2444                 for (; i < size()
2445                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2446                      ++i) {
2447                         ++column;
2448
2449                         // Fully instantiated font
2450                         LyXFont font = getFont(i);
2451                         last_font = running_font;
2452
2453                         // Spaces at end of font change are simulated to
2454                         // be outside font change. i.e. we write
2455                         // "\textXX{text} " rather than "\textXX{text }".
2456                         // (Asger)
2457                         if (open_font && c == ' ' && i <= size() - 2 
2458                             && getFont(i + 1) != running_font
2459                             && getFont(i + 1) != font) {
2460                                 font = getFont(i + 1);
2461                         }
2462
2463                         // We end font definition before blanks
2464                         if (font != running_font && open_font) {
2465                                 column += running_font.latexWriteEndChanges(os, basefont, font);
2466                                 running_font = basefont;
2467                                 open_font = false;
2468                         }
2469                         // Blanks are printed before start of fontswitch
2470                         if (c == ' '){
2471                                 SimpleTeXBlanks(os, texrow, i,
2472                                                 column, font, style);
2473                         }
2474                         // Do we need to change font?
2475                         if (font != running_font) {
2476                                 column +=
2477                                         font.latexWriteStartChanges(os,
2478                                                                     basefont,
2479                                                                     last_font);
2480                                 running_font = font;
2481                                 open_font = true;
2482                         }
2483                         // Do we need to turn on LaTeX mode?
2484                         if (font.latex() != running_font.latex()) {
2485                                 if (font.latex() == LyXFont::ON
2486                                     && style.needprotect) {
2487                                         os << "\\protect ";
2488                                         column += 9;
2489                                 }
2490                         }
2491                         SimpleTeXSpecialChars(os, texrow, font,
2492                                               running_font, basefont,
2493                                               open_font, style, i, column, c);
2494                 }
2495                 // If we have an open font definition, we have to close it
2496                 if (open_font) {
2497                         running_font.latexWriteEndChanges(os, basefont,
2498                                                           basefont);
2499                         open_font = false;
2500                 }
2501                 basefont = getFont(-1);
2502                 running_font = basefont;
2503                 cell = table->CellHasContRow(current_cell_number);
2504         }
2505         lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2506         return return_value;
2507 }
2508
2509
2510 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2511 {
2512         bool retval = false;
2513         switch (c) {
2514         case LyXParagraph::META_HFILL:
2515                 sgml_string.clear();
2516                 break;
2517 #if 0
2518         case LyXParagraph::META_PROTECTED_SEPARATOR: 
2519                 sgml_string = ' ';
2520                 break;
2521 #endif
2522         case LyXParagraph::META_NEWLINE:
2523                 sgml_string = '\n';
2524                 break;
2525         case '&': 
2526                 sgml_string = "&amp;";
2527                 break;
2528         case '<': 
2529                 sgml_string = "&lt;"; 
2530                 break;
2531         case '>':
2532                 sgml_string = "&gt;"; 
2533                 break;
2534         case '$': 
2535                 sgml_string = "&dollar;"; 
2536                 break;
2537         case '#': 
2538                 sgml_string = "&num;";
2539                 break;
2540         case '%': 
2541                 sgml_string = "&percnt;";
2542                 break;
2543         case '[': 
2544                 sgml_string = "&lsqb;";
2545                 break;
2546         case ']': 
2547                 sgml_string = "&rsqb;";
2548                 break;
2549         case '{': 
2550                 sgml_string = "&lcub;";
2551                 break;
2552         case '}': 
2553                 sgml_string = "&rcub;";
2554                 break;
2555         case '~': 
2556                 sgml_string = "&tilde;";
2557                 break;
2558         case '"': 
2559                 sgml_string = "&quot;";
2560                 break;
2561         case '\\': 
2562                 sgml_string = "&bsol;";
2563                 break;
2564         case ' ':
2565                 retval = true;
2566                 sgml_string = ' ';
2567                 break;
2568         case '\0': // Ignore :-)
2569                 sgml_string.clear();
2570                 break;
2571         default:
2572                 sgml_string = c;
2573                 break;
2574         }
2575         return retval;
2576 }
2577
2578
2579 void LyXParagraph::SimpleDocBookOneTablePar(ostream & os, string & extra,
2580                                             int & desc_on, int depth) 
2581 {
2582         if (!table) return;
2583         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2584         int column = 0;
2585         LyXFont font1, font2;
2586         char c;
2587         Inset * inset;
2588         size_type main_body;
2589         bool emph_flag = false;
2590         
2591         LyXLayout const & style =
2592                 textclasslist.Style(current_view->buffer()->params.textclass,
2593                                     GetLayout());
2594         
2595         if (style.labeltype != LABEL_MANUAL)
2596                 main_body = 0;
2597         else
2598                 main_body = BeginningOfMainBody();
2599         
2600         // Gets paragraph main font.
2601         if (main_body > 0)
2602                 font1 = style.labelfont;
2603         else
2604                 font1 = style.font;
2605         
2606         int char_line_count = depth;
2607         os << newlineAndDepth(depth);
2608         if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2609                 os << "<INFORMALTABLE>"
2610                    << newlineAndDepth(++depth);
2611         }
2612         int current_cell_number = -1;
2613         int tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2614         
2615         // Parsing main loop.
2616         for (size_type i = 0; i < size(); ++i) {
2617                 c = GetChar(i);
2618                 if (table->IsContRow(current_cell_number+1)) {
2619                         if (c == LyXParagraph::META_NEWLINE)
2620                                 ++current_cell_number;
2621                         continue;
2622                 }
2623                 ++column;
2624                 
2625                 // Fully instantiated font
2626                 font2 = getFont(i);
2627                 
2628                 // Handle <emphasis> tag.
2629                 if (font1.emph() != font2.emph() && i) {
2630                         if (font2.emph() == LyXFont::ON) {
2631                                 os << "<emphasis>";
2632                                 emph_flag= true;
2633                         } else if (emph_flag) {
2634                                 os << "</emphasis>";
2635                                 emph_flag= false;
2636                         }
2637                 }
2638                 if (c == LyXParagraph::META_NEWLINE) {
2639                         // We have only to control for emphasis open here!
2640                         if (emph_flag) {
2641                                 os << "</emphasis>";
2642                                 emph_flag= false;
2643                         }
2644                         font1 = font2 = getFont(-1);
2645                         ++current_cell_number;
2646                         if (table->CellHasContRow(current_cell_number) >= 0) {
2647                                 DocBookContTableRows(os, extra, desc_on, i + 1,
2648                                                      current_cell_number,
2649                                                      column);
2650                         }
2651                         // if this cell follow only ContRows till end don't
2652                         // put the EndOfCell because it is put after the
2653                         // for(...)
2654                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2655                                 --current_cell_number;
2656                                 break;
2657                         }
2658                         tmp = table->DocBookEndOfCell(os,
2659                                                       current_cell_number,
2660                                                       depth);
2661                         
2662                         if (tmp > 0)
2663                                 column = 0;
2664                 } else if (c == LyXParagraph::META_INSET) {
2665                         inset = GetInset(i);
2666 #ifdef HAVE_SSTREAM
2667                         ostringstream ost;
2668                         inset->DocBook(ost);
2669                         string tmp_out = ost.str().c_str();
2670 #else
2671                         ostrstream ost;
2672                         inset->DocBook(ost);
2673                         ost << '\0';
2674                         char * ctmp = ost.str();
2675                         string tmp_out(ctmp);
2676                         delete [] ctmp;
2677 #endif
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                                                 os << frontStrip(tmp_out,
2698                                                                  '@');
2699                                 } else
2700                                         os << tmp_out;
2701                         }
2702                 } else if (font2.latex() == LyXFont::ON) {
2703                         // "TeX"-Mode on == > SGML-Mode on.
2704                         if (c != '\0')
2705                                 os << 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                                         os << '\n'
2717                                            << "</term><listitem><para>";
2718                                         desc_on = 2;
2719                                 } else  {
2720                                         os << c;
2721                                 }
2722                         } else {
2723                                 os << 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                 os << "</emphasis>";
2736         }
2737         
2738         ++current_cell_number;
2739         tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
2740         // Resets description flag correctly.
2741         switch(desc_on){
2742         case 1:
2743                 // <term> not closed...
2744                 os << "</term>";
2745                 break;
2746         }
2747         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2748                 os << "</INFORMALTABLE>";
2749         os << '\n';
2750         lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
2751                              << this << endl;
2752 }
2753
2754
2755 void LyXParagraph::DocBookContTableRows(ostream & os, 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                         os << ' ';
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                                         os << "<emphasis>";
2824                                         emph_flag= true;
2825                                 } else if (emph_flag) {
2826                                         os << "</emphasis>";
2827                                         emph_flag= false;
2828                                 }
2829                         }
2830                         if (c == LyXParagraph::META_INSET) {
2831                                 inset = GetInset(i);
2832 #ifdef HAVE_SSTREAM
2833                                 ostringstream ost;
2834                                 inset->DocBook(ost);
2835                                 string tmp_out = ost.str().c_str();
2836 #else
2837                                 ostrstream ost;
2838                                 inset->DocBook(ost);
2839                                 ost << '\0';
2840                                 char * ctmp = ost.str();
2841                                 string tmp_out(ctmp);
2842                                 delete [] ctmp;
2843 #endif
2844                                 //
2845                                 // This code needs some explanation:
2846                                 // Two insets are treated specially
2847                                 //   label if it is the first element in a
2848                                 //   command paragraph
2849                                 //       desc_on == 3
2850                                 //   graphics inside tables or figure floats
2851                                 //   can't go on title (the equivalente in
2852                                 //   latex for this case is caption and title
2853                                 //   should come first
2854                                 //       desc_on == 4
2855                                 //
2856                                 if(desc_on != 3 || i != 0) {
2857                                         if(tmp_out[0] == '@') {
2858                                                 if(desc_on == 4)
2859                                                         extra += frontStrip(tmp_out, '@');
2860                                                 else
2861                                                         os << frontStrip(tmp_out, '@');
2862                                         } else
2863                                                 os << tmp_out;
2864                                 }
2865                         } else if (font2.latex() == LyXFont::ON) {
2866                                 // "TeX"-Mode on == > SGML-Mode on.
2867                                 if (c!= '\0')
2868                                         os << c;
2869                                 ++char_line_count;
2870                         } else {
2871                                 string sgml_string;
2872                                 if (linuxDocConvertChar(c, sgml_string) 
2873                                     && !style.free_spacing) {
2874                                         // in freespacing mode, spaces are
2875                                         // non-breaking characters
2876                                         // char is ' '
2877                                         if (desc_on == 1) {
2878                                                 ++char_line_count;
2879                                                 os << '\n'
2880                                                    << "</term><listitem><para>";
2881                                                 desc_on = 2;
2882                                         } else  {
2883                                                 os << c;
2884                                         }
2885                                 } else {
2886                                         os << sgml_string;
2887                                 }
2888                         }
2889                 }
2890                 // we have only to control for emphasis open here!
2891                 if (emph_flag) {
2892                         os << "</emphasis>";
2893                         emph_flag= false;
2894                 }
2895                 font1 = font2 = getFont(-1);
2896                 cell = table->CellHasContRow(current_cell_number);
2897         }
2898         lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
2899 }
2900
2901
2902 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
2903                                    LyXParagraph::size_type const i,
2904                                    int & column, LyXFont const & font,
2905                                    LyXLayout const & style)
2906 {
2907         if (column > tex_code_break_column
2908             && i 
2909             && GetChar(i - 1) != ' '
2910             && (i < size() - 1)
2911             // In LaTeX mode, we don't want to
2912             // break lines since some commands
2913             // do not like this
2914             && ! (font.latex() == LyXFont::ON)
2915             // same in FreeSpacing mode
2916             && !style.free_spacing
2917             // In typewriter mode, we want to avoid 
2918             // ! . ? : at the end of a line
2919             && !(font.family() == LyXFont::TYPEWRITER_FAMILY
2920                  && (GetChar(i-1) == '.'
2921                      || GetChar(i-1) == '?' 
2922                      || GetChar(i-1) == ':'
2923                      || GetChar(i-1) == '!'))) {
2924                 if (tex_code_break_column == 0) {
2925                         // in batchmode we need LaTeX to still
2926                         // see it as a space not as an extra '\n'
2927                         os << " %\n";
2928                 } else {
2929                         os << '\n';
2930                 }
2931                 texrow.newline();
2932                 texrow.start(this, i + 1);
2933                 column = 0;
2934         } else if (font.latex() == LyXFont::OFF) {
2935                 if (style.free_spacing) {
2936                         os << '~';
2937                 } else {
2938                         os << ' ';
2939                 }
2940         }
2941 }
2942
2943
2944 void LyXParagraph::SimpleTeXSpecialChars(ostream & os, TexRow & texrow,
2945                                          LyXFont & font,
2946                                          LyXFont & running_font,
2947                                          LyXFont & basefont,
2948                                          bool & open_font,
2949                                          LyXLayout const & style,
2950                                          LyXParagraph::size_type & i,
2951                                          int & column, char const c)
2952 {
2953         // Two major modes:  LaTeX or plain
2954         // Handle here those cases common to both modes
2955         // and then split to handle the two modes separately.
2956         switch (c) {
2957         case LyXParagraph::META_INSET: {
2958                 Inset * inset = GetInset(i);
2959                 if (inset) {
2960                         bool close = false;
2961                         int len = os.tellp();
2962                         if ((inset->LyxCode() == Inset::GRAPHICS_CODE
2963                              || inset->LyxCode() == Inset::MATH_CODE
2964                              || inset->LyxCode() == Inset::URL_CODE)
2965                             && running_font.getFontDirection()
2966                             == LYX_DIR_RIGHT_TO_LEFT) {
2967                                 os << "\\L{";
2968                                 close = true;
2969                         }
2970
2971                         int tmp = inset->Latex(os, style.isCommand(),
2972                                                style.free_spacing);
2973
2974                         if (close)
2975                                 os << "}";
2976                         
2977                         if (tmp) {
2978                                 column = 0;
2979                         } else {
2980                                 column += os.tellp() - len;
2981                         }
2982                         for (; tmp--;) {
2983                                 texrow.newline();
2984                         }
2985                 }
2986         }
2987         break;
2988
2989         case LyXParagraph::META_NEWLINE:
2990                 if (open_font) {
2991                         column += running_font.latexWriteEndChanges(os,
2992                                                                     basefont,
2993                                                                     basefont);
2994                         open_font = false;
2995                 }
2996                 basefont = getFont(-1);
2997                 running_font = basefont;
2998                 break;
2999
3000         case LyXParagraph::META_HFILL: 
3001                 os << "\\hfill{}";
3002                 column += 7;
3003                 break;
3004
3005         default:
3006                 // And now for the special cases within each mode
3007                 // Are we in LaTeX mode?
3008                 if (font.latex() == LyXFont::ON) {
3009                         // at present we only have one option
3010                         // but I'll leave it as a switch statement
3011                         // so its simpler to extend. (ARRae)
3012                         switch (c) {
3013 #if 0
3014                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
3015                                 os << ' ';
3016                                 break;
3017 #endif
3018                         default:
3019                                 // make sure that we will not print
3020                                 // error generating chars to the tex
3021                                 // file. This test would not be needed
3022                                 // if it were done in the buffer
3023                                 // itself.
3024                                 if (c != '\0') {
3025                                         os << c;
3026                                 }
3027                                 break;
3028                         }
3029                 } else {
3030                         // Plain mode (i.e. not LaTeX)
3031                         switch (c) {
3032 #if 0
3033                         case LyXParagraph::META_PROTECTED_SEPARATOR: 
3034                                 os << '~';
3035                                 break;
3036 #endif
3037                         case '\\': 
3038                                 os << "\\textbackslash{}";
3039                                 column += 15;
3040                                 break;
3041                 
3042                         case '°': case '±': case '²': case '³':  
3043                         case '×': case '÷': case '¹': case 'ª':
3044                         case 'º': case '¬': case 'µ':
3045                                 if (current_view->buffer()->params.inputenc == "latin1") {
3046                                         os << "\\ensuremath{"
3047                                            << c
3048                                            << '}';
3049                                         column += 13;
3050                                 } else {
3051                                         os << c;
3052                                 }
3053                                 break;
3054
3055                         case '|': case '<': case '>':
3056                                 // In T1 encoding, these characters exist
3057                                 if (lyxrc->fontenc == "T1") {
3058                                         os << c;
3059                                         //... but we should avoid ligatures
3060                                         if ((c == '>' || c == '<')
3061                                             && i <= size() - 2
3062                                             && GetChar(i + 1) == c){
3063                                                 os << "\\textcompwordmark{}";
3064                                                 column += 19;
3065                                         }
3066                                         break;
3067                                 }
3068                                 // Typewriter font also has them
3069                                 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3070                                         os << c;
3071                                         break;
3072                                 } 
3073                                 // Otherwise, we use what LaTeX
3074                                 // provides us.
3075                                 switch(c) {
3076                                 case '<':
3077                                         os << "\\textless{}";
3078                                         column += 10;
3079                                         break;
3080                                 case '>':
3081                                         os << "\\textgreater{}";
3082                                         column += 13;
3083                                         break;
3084                                 case '|':
3085                                         os << "\\textbar{}";
3086                                         column += 9;
3087                                         break;
3088                                 }
3089                                 break;
3090
3091                         case '-': // "--" in Typewriter mode -> "-{}-"
3092                                 if (i <= size() - 2
3093                                     && GetChar(i + 1) == '-'
3094                                     && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3095                                         os << "-{}";
3096                                         column += 2;
3097                                 } else {
3098                                         os << '-';
3099                                 }
3100                                 break;
3101
3102                         case '\"': 
3103                                 os << "\\char`\\\"{}";
3104                                 column += 9;
3105                                 break;
3106
3107                         case '£':
3108                                 if (current_view->buffer()->params.inputenc == "default") {
3109                                         os << "\\pounds{}";
3110                                         column += 8;
3111                                 } else {
3112                                         os << c;
3113                                 }
3114                                 break;
3115
3116                         case '$': case '&':
3117                         case '%': case '#': case '{':
3118                         case '}': case '_':
3119                                 os << '\\' << c;
3120                                 column += 1;
3121                                 break;
3122
3123                         case '~':
3124                                 os << "\\textasciitilde{}";
3125                                 column += 16;
3126                                 break;
3127
3128                         case '^':
3129                                 os << "\\textasciicircum{}";
3130                                 column += 17;
3131                                 break;
3132
3133                         case '*': case '[': case ']':
3134                                 // avoid being mistaken for optional arguments
3135                                 os << '{' << c << '}';
3136                                 column += 2;
3137                                 break;
3138
3139                         case ' ':
3140                                 // Blanks are printed before font switching.
3141                                 // Sure? I am not! (try nice-latex)
3142                                 // I am sure it's correct. LyX might be smarter
3143                                 // in the future, but for now, nothing wrong is
3144                                 // written. (Asger)
3145                                 break;
3146
3147                         default:
3148                                 /* idea for labels --- begin*/
3149                                 // Check for "LyX"
3150                                 if (c ==  'L'
3151                                     && i <= size() - 3
3152                                     && font.family() != LyXFont::TYPEWRITER_FAMILY
3153                                     && GetChar(i + 1) == 'y'
3154                                     && GetChar(i + 2) == 'X') {
3155                                         os << "\\LyX{}";
3156                                         i += 2;
3157                                         column += 5;
3158                                 }
3159                                 // Check for "TeX"
3160                                 else if (c == 'T'
3161                                          && i <= size() - 3
3162                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3163                                          && GetChar(i + 1) == 'e'
3164                                          && GetChar(i + 2) == 'X') {
3165                                         os << "\\TeX{}";
3166                                         i += 2;
3167                                         column += 5;
3168                                 }
3169                                 // Check for "LaTeX2e"
3170                                 else if (c == 'L'
3171                                          && i <= size() - 7
3172                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3173                                          && GetChar(i + 1) == 'a'
3174                                          && GetChar(i + 2) == 'T'
3175                                          && GetChar(i + 3) == 'e'
3176                                          && GetChar(i + 4) == 'X'
3177                                          && GetChar(i + 5) == '2'
3178                                          && GetChar(i + 6) == 'e') {
3179                                         os << "\\LaTeXe{}";
3180                                         i += 6;
3181                                         column += 8;
3182                                 }
3183                                 // Check for "LaTeX"
3184                                 else if (c == 'L'
3185                                          && i <= size() - 5
3186                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3187                                          && GetChar(i + 1) == 'a'
3188                                          && GetChar(i + 2) == 'T'
3189                                          && GetChar(i + 3) == 'e'
3190                                          && GetChar(i + 4) == 'X') {
3191                                         os << "\\LaTeX{}";
3192                                         i += 4;
3193                                         column += 7;
3194                                         /* idea for labels --- end*/ 
3195                                 } else if (c != '\0') {
3196                                         os << c;
3197                                 }
3198                                 break;
3199                         }
3200                 }
3201         }
3202 }
3203
3204
3205 #if 0
3206 bool LyXParagraph::RoffContTableRows(ostream & os,
3207                                      LyXParagraph::size_type i,
3208                                      int actcell)
3209 {
3210         if (!table)
3211                 return false;
3212
3213         LyXFont font1(LyXFont::ALL_INHERIT);
3214         LyXFont font2;
3215         Inset * inset;
3216         char c;
3217
3218         string fname2 = TmpFileName(string(), "RAT2");
3219         int lastpos = i;
3220         int cell = table->CellHasContRow(actcell);
3221         ++actcell;
3222         while(cell >= 0) {
3223                 // first find the right position
3224                 i = lastpos;
3225                 for (; i < size() && actcell < cell; ++i) {
3226                         c = GetChar(i);
3227                         if (c == LyXParagraph::META_NEWLINE)
3228                                 ++actcell;
3229                 }
3230                 lastpos = i;
3231                 c = GetChar(i);
3232                 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3233                         os << " ";
3234                 for (; i < size()
3235                              && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3236                      ++i) {
3237                         font2 = GetFontSettings(i);
3238                         if (font1.latex() != font2.latex()) {
3239                                 if (font2.latex() != LyXFont::OFF)
3240                                         continue;
3241                         }
3242                         c = GetChar(i);
3243                         switch (c) {
3244                         case LyXParagraph::META_INSET:
3245                                 if ((inset = GetInset(i))) {
3246 #if 1
3247 #ifdef HAVE_SSTREAM
3248                                         stringstream ss(ios::in | ios::out);
3249                                         inset->Latex(ss, -1);
3250                                         ss.seekp(0);
3251                                         ss.get(c);
3252                                         while (!ss) {
3253                                                 if (c == '\\')
3254                                                         os << "\\\\";
3255                                                 else
3256                                                         os << c;
3257                                                 ss.get(c);
3258                                         }
3259 #else
3260                                         strstream ss;
3261                                         inset->Latex(ss, -1);
3262                                         ss.seekp(0);
3263                                         ss.get(c);
3264                                         while (!ss) {
3265                                                 if (c == '\\')
3266                                                         os << "\\\\";
3267                                                 else
3268                                                         os << c;
3269                                                 ss.get(c);
3270                                         }
3271                                         delete [] ss.str();
3272 #endif
3273 #else
3274                                         fstream fs(fname2.c_str(),
3275                                                    ios::in|ios::out);
3276                                         if (!fs) {
3277                                                 WriteAlert(_("LYX_ERROR:"),
3278                                                            _("Cannot open temporary file:"),
3279                                                            fname2);
3280                                                 return false;
3281                                         }
3282                                         inset->Latex(fs, -1);
3283                                         fs.seekp(0);
3284                                         fs.get(c);
3285                                         while (!fs) {
3286                                                 if (c == '\\')
3287                                                         os << "\\\\";
3288                                                 else
3289                                                         os << c;
3290                                                 fs.get(c);
3291                                         }
3292                                         fs.close();
3293 #endif
3294                                 }
3295                                 break;
3296                         case LyXParagraph::META_NEWLINE:
3297                                 break;
3298                         case LyXParagraph::META_HFILL: 
3299                                 break;
3300 #if 0
3301                         case LyXParagraph::META_PROTECTED_SEPARATOR:
3302                                 break;
3303 #endif
3304                         case '\\': 
3305                                 os << "\\\\";
3306                                 break;
3307                         default:
3308                                 if (c != '\0')
3309                                         os << c;
3310                                 else
3311                                         lyxerr.debug() << "RoffAsciiTable: "
3312                                                 "NULL char in structure."
3313                                                        << endl;
3314                                 break;
3315                         }
3316                 }
3317                 cell = table->CellHasContRow(actcell);
3318         }
3319         return true;
3320 }
3321 #endif
3322
3323
3324 LyXParagraph * LyXParagraph::TeXDeeper(ostream & os, TexRow & texrow,
3325                                        ostream & foot, TexRow & foot_texrow,
3326                                        int & foot_count)
3327 {
3328         lyxerr[Debug::LATEX] << "TeXDeeper...     " << this << endl;
3329         LyXParagraph * par = this;
3330
3331         while (par && par->depth == depth) {
3332                 if (par->IsDummy())
3333                         lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3334                 if (textclasslist.Style(current_view->buffer()->params.textclass, 
3335                                         par->layout).isEnvironment()
3336                     || par->pextra_type != PEXTRA_NONE) {
3337                         par = par->TeXEnvironment(os, texrow,
3338                                                   foot, foot_texrow,
3339                                                   foot_count);
3340                 } else {
3341                         par = par->TeXOnePar(os, texrow,
3342                                              foot, foot_texrow,
3343                                              foot_count);
3344                 }
3345         }
3346         lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3347
3348         return par;
3349 }
3350
3351
3352 LyXParagraph * LyXParagraph::TeXEnvironment(ostream & os, TexRow & texrow,
3353                                             ostream & foot,
3354                                             TexRow & foot_texrow,
3355                                             int & foot_count)
3356 {
3357         bool eindent_open = false;
3358         bool foot_this_level = false;
3359         // flags when footnotetext should be appended to file.
3360         static bool minipage_open = false;
3361         static int minipage_open_depth = 0;
3362         char par_sep = current_view->buffer()->params.paragraph_separation;
3363     
3364         lyxerr[Debug::LATEX] << "TeXEnvironment...     " << this << endl;
3365         if (IsDummy())
3366                 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3367
3368         LyXLayout const & style =
3369                 textclasslist.Style(current_view->buffer()->params.textclass,
3370                                     layout);
3371        
3372         if (pextra_type == PEXTRA_INDENT) {
3373                 if (!pextra_width.empty()) {
3374                         os << "\\begin{LyXParagraphIndent}{"
3375                            << pextra_width << "}\n";
3376                 } else {
3377                         //float ib = atof(pextra_widthp.c_str())/100;
3378                         // string can't handle floats at present (971109)
3379                         // so I'll do a conversion by hand knowing that
3380                         // the limits are 0.0 to 1.0. ARRae.
3381                         os << "\\begin{LyXParagraphIndent}{";
3382                         switch (pextra_widthp.length()) {
3383                         case 3:
3384                                 os << "1.00";
3385                                 break;
3386                         case 2:
3387                                 os << "0."
3388                                    << pextra_widthp;
3389                                 break;
3390                         case 1:
3391                                 os << "0.0"
3392                                    << pextra_widthp;
3393                         }
3394                         os << "\\columnwidth}\n";
3395                 }
3396                 texrow.newline();
3397                 eindent_open = true;
3398         }
3399         if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3400                 if (pextra_hfill && Previous() &&
3401                     (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3402                         os << "\\hfill{}\n";
3403                         texrow.newline();
3404                 }
3405                 if (par_sep == BufferParams::PARSEP_INDENT) {
3406                         os << "{\\setlength\\parindent{0pt}\n";
3407                         texrow.newline();
3408                 }
3409                 os << "\\begin{minipage}";
3410                 switch(pextra_alignment) {
3411                 case MINIPAGE_ALIGN_TOP:
3412                         os << "[t]";
3413                         break;
3414                 case MINIPAGE_ALIGN_MIDDLE:
3415                         os << "[m]";
3416                         break;
3417                 case MINIPAGE_ALIGN_BOTTOM:
3418                         os << "[b]";
3419                         break;
3420                 }
3421                 if (!pextra_width.empty()) {
3422                         os << '{' << pextra_width << "}\n";
3423                 } else {
3424                         //float ib = atof(par->pextra_width.c_str())/100;
3425                         // string can't handle floats at present
3426                         // so I'll do a conversion by hand knowing that
3427                         // the limits are 0.0 to 1.0. ARRae.
3428                         os << '{';
3429                         switch (pextra_widthp.length()) {
3430                         case 3:
3431                                 os << "1.00";
3432                                 break;
3433                         case 2:
3434                                 os << "0."
3435                                    << pextra_widthp;
3436                                 break;
3437                         case 1:
3438                                 os << "0.0"
3439                                    << pextra_widthp;
3440                         }
3441                         os << "\\columnwidth}\n";
3442                 }
3443                 texrow.newline();
3444                 if (par_sep == BufferParams::PARSEP_INDENT) {
3445                         os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3446                         texrow.newline();
3447                 }
3448                 minipage_open = true;
3449                 minipage_open_depth = depth;
3450         }
3451
3452 #ifdef WITH_WARNINGS
3453 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3454         //I disabled it because it breaks when lists span on several
3455         //pages (JMarc)
3456 #endif
3457         if (style.isEnvironment()){
3458                 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3459 #ifdef FANCY_FOOTNOTE_CODE
3460                         if (foot_count < 0) {
3461                                 // flag that footnote[mark][text] should be
3462                                 // used for any footnotes from now on
3463                                 foot_count = 0;
3464                                 foot_this_level = true;
3465                         }
3466 #endif
3467                         os << "\\begin{" << style.latexname() << "}{"
3468                            << labelwidthstring << "}\n";
3469                 } else if (style.labeltype == LABEL_BIBLIO) {
3470                         // ale970405
3471                         os << "\\begin{" << style.latexname() << "}{"
3472                            << bibitemWidthest(current_view->painter())
3473                            << "}\n";
3474                 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3475 #ifdef FANCY_FOOTNOTE_CODE
3476                         if (foot_count < 0) {
3477                                 // flag that footnote[mark][text] should be
3478                                 // used for any footnotes from now on
3479                                 foot_count = 0;
3480                                 foot_this_level = true;
3481                         }
3482 #endif
3483                         os << "\\begin{" << style.latexname() << '}'
3484                            << style.latexparam() << '\n';
3485                 } else 
3486                         os << "\\begin{" << style.latexname() << '}'
3487                            << style.latexparam() << '\n';
3488                 texrow.newline();
3489         }
3490         LyXParagraph * par = this;
3491         do {
3492                 par = par->TeXOnePar(os, texrow,
3493                                      foot, foot_texrow, foot_count);
3494
3495                 if (minipage_open && par && !style.isEnvironment() &&
3496                     (par->pextra_type == PEXTRA_MINIPAGE) &&
3497                     par->pextra_start_minipage) {
3498                         os << "\\end{minipage}\n";
3499                         texrow.newline();
3500                         if (par_sep == BufferParams::PARSEP_INDENT) {
3501                                 os << "}\n";
3502                                 texrow.newline();
3503                         }
3504                         minipage_open = false;
3505                 }
3506                 if (par && par->depth > depth) {
3507                         if (textclasslist.Style(current_view->buffer()->params.textclass,
3508                                                 par->layout).isParagraph()
3509                             && !par->table
3510                             // Thinko!
3511                             // How to handle this? (Lgb)
3512                             //&& !suffixIs(os, "\n\n")
3513                                 ) {
3514                                 // There should be at least one '\n' already
3515                                 // but we need there to be two for Standard 
3516                                 // paragraphs that are depth-increment'ed to be
3517                                 // output correctly.  However, tables can
3518                                 // also be paragraphs so don't adjust them.
3519                                 // ARRae
3520                                 // Thinkee:
3521                                 // Will it ever harm to have one '\n' too
3522                                 // many? i.e. that we sometimes will have
3523                                 // three in a row. (Lgb)
3524                                 os << '\n';
3525                                 texrow.newline();
3526                         }
3527                         par = par->TeXDeeper(os, texrow,
3528                                              foot, foot_texrow, foot_count);
3529                 }
3530                 if (par && par->layout == layout && par->depth == depth &&
3531                     (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3532                         if (par->pextra_hfill && par->Previous() &&
3533                             (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3534                                 os << "\\hfill{}\n";
3535                                 texrow.newline();
3536                         }
3537                         if (par_sep == BufferParams::PARSEP_INDENT) {
3538                                 os << "{\\setlength\\parindent{0pt}\n";
3539                                 texrow.newline();
3540                         }
3541                         os << "\\begin{minipage}";
3542                         switch(par->pextra_alignment) {
3543                         case MINIPAGE_ALIGN_TOP:
3544                                 os << "[t]";
3545                                 break;
3546                         case MINIPAGE_ALIGN_MIDDLE:
3547                                 os << "[m]";
3548                                 break;
3549                         case MINIPAGE_ALIGN_BOTTOM:
3550                                 os << "[b]";
3551                                 break;
3552                         }
3553                         if (!par->pextra_width.empty()) {
3554                                 os << '{' << par->pextra_width << "}\n";
3555                         } else {
3556                                 //float ib = atof(par->pextra_widthp.c_str())/100;
3557                                 // string can't handle floats at present
3558                                 // so I'll do a conversion by hand knowing that
3559                                 // the limits are 0.0 to 1.0. ARRae.
3560                                 os << '{';
3561                                 switch (par->pextra_widthp.length()) {
3562                                 case 3:
3563                                         os << "1.00";
3564                                         break;
3565                                 case 2:
3566                                         os << "0." << par->pextra_widthp;
3567                                         break;
3568                                 case 1:
3569                                         os << "0.0" << par->pextra_widthp;
3570                                 }
3571                                 os << "\\columnwidth}\n";
3572                         }
3573                         texrow.newline();
3574                         if (par_sep == BufferParams::PARSEP_INDENT) {
3575                                 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3576                                 texrow.newline();
3577                         }
3578                         minipage_open = true;
3579                         minipage_open_depth = par->depth;
3580                 }
3581         } while (par
3582                  && par->layout == layout
3583                  && par->depth == depth
3584                  && par->pextra_type == pextra_type);
3585  
3586         if (style.isEnvironment()) {
3587                 os << "\\end{" << style.latexname() << '}';
3588                 // maybe this should go after the minipage closes?
3589                 if (foot_this_level) {
3590                         if (foot_count >= 1) {
3591                                 if (foot_count > 1) {
3592                                         os << "\\addtocounter{footnote}{-"
3593                                            << foot_count - 1
3594                                            << '}';
3595                                 }
3596                                 os << foot;
3597                                 texrow += foot_texrow;
3598                                 foot.clear();
3599                                 foot_texrow.reset();
3600                                 foot_count = 0;
3601                         }
3602                 }
3603         }
3604         if (minipage_open && (minipage_open_depth == depth) &&
3605             (!par || par->pextra_start_minipage ||
3606              par->pextra_type != PEXTRA_MINIPAGE)) {
3607                 os << "\\end{minipage}\n";
3608                 texrow.newline();
3609                 if (par_sep == BufferParams::PARSEP_INDENT) {
3610                         os << "}\n";
3611                         texrow.newline();
3612                 }
3613                 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3614                         os << "\\medskip\n\n";
3615                         texrow.newline();
3616                         texrow.newline();
3617                 }
3618                 minipage_open = false;
3619         }
3620         if (eindent_open) {
3621                 os << "\\end{LyXParagraphIndent}\n";
3622                 texrow.newline();
3623         }
3624         if (!(par && (par->pextra_type == PEXTRA_MINIPAGE) 
3625               && par->pextra_hfill)) {
3626                 os << '\n';
3627                 texrow.newline();
3628         }
3629         lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3630         return par;  // ale970302
3631 }
3632
3633
3634 LyXParagraph * LyXParagraph::TeXFootnote(ostream & os, TexRow & texrow,
3635                                          ostream & foot, TexRow & foot_texrow,
3636                                          int & foot_count,
3637                                          LyXDirection par_direction)
3638 {
3639         lyxerr[Debug::LATEX] << "TeXFootnote...  " << this << endl;
3640         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3641                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3642                         "No footnote!" << endl;
3643
3644         LyXParagraph * par = this;
3645         LyXLayout const & style =
3646                 textclasslist.Style(current_view->buffer()->params.textclass, 
3647                                     previous->GetLayout());
3648         
3649         if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3650                 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3651                         "Float other than footnote in command"
3652                         " with moving argument is illegal" << endl;
3653         }
3654
3655         if (footnotekind != LyXParagraph::FOOTNOTE
3656             && footnotekind != LyXParagraph::MARGIN
3657             && os.tellp()
3658             // Thinko
3659             // How to solve this?
3660             //&& !suffixIs(file, '\n')
3661                 ) {
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                 // Thinkee:
3669                 // As far as I can see there is never any harm in writing
3670                 // a '\n' too much. Please tell me if I am wrong. (Lgb)
3671                 os << '\n';
3672                 texrow.newline();
3673         }
3674         
3675         BufferParams * params = &current_view->buffer()->params;
3676         bool footer_in_body = true;
3677         switch (footnotekind) {
3678         case LyXParagraph::FOOTNOTE:
3679                 if (style.intitle) {
3680                         os << "\\thanks{\n";
3681                         footer_in_body = false;
3682                 } else {
3683                         if (foot_count == -1) {
3684                                 // we're at depth 0 so we can use:
3685                                 os << "\\footnote{%\n";
3686                                 footer_in_body = false;
3687                         } else {
3688                                 os << "\\footnotemark{}%\n";
3689                                 if (foot_count) {
3690                                         // we only need this when there are
3691                                         // multiple footnotes
3692                                         os << "\\stepcounter{footnote}";
3693                                 }
3694                                 os << "\\footnotetext{%\n";
3695                                 foot_texrow.start(this, 0);
3696                                 foot_texrow.newline();
3697                                 ++foot_count;
3698                         }
3699                 }
3700                 break;
3701         case LyXParagraph::MARGIN:
3702                 os << "\\marginpar{\n";
3703                 break;
3704         case LyXParagraph::FIG:
3705                 if (pextra_type == PEXTRA_FLOATFLT
3706                     && (!pextra_width.empty()
3707                         || !pextra_widthp.empty())) {
3708                         if (!pextra_width.empty())
3709                                 os << "\\begin{floatingfigure}{"
3710                                    << pextra_width << "}\n";
3711                         else
3712                                 os << "\\begin{floatingfigure}{"
3713                                    << atoi(pextra_widthp.c_str())/100.0
3714                                    << "\\textwidth}\n";
3715                 } else {
3716                         os << "\\begin{figure}";
3717                         if (!params->float_placement.empty()) { 
3718                                 os << '[' << params->float_placement << "]\n";
3719                         } else {
3720                                 os << '\n';
3721                         }
3722                 }
3723                 break;
3724         case LyXParagraph::TAB:
3725                 os << "\\begin{table}";
3726                 if (!params->float_placement.empty()) { 
3727                         os << '[' << params->float_placement << "]\n";
3728                 } else {
3729                         os << '\n';
3730                 }
3731                 break;
3732         case LyXParagraph::WIDE_FIG:
3733                 os << "\\begin{figure*}";
3734                 if (!params->float_placement.empty()) { 
3735                         os << '[' << params->float_placement << "]\n";
3736                 } else {
3737                         os << '\n';
3738                 }
3739                 break;
3740         case LyXParagraph::WIDE_TAB:
3741                 os << "\\begin{table*}";
3742                 if (!params->float_placement.empty()) { 
3743                         os << '[' << params->float_placement << "]\n";
3744                 } else {
3745                         os << '\n';
3746                 }
3747                 break;
3748         case LyXParagraph::ALGORITHM:
3749                 os << "\\begin{algorithm}\n";
3750                 break;
3751         }
3752         texrow.newline();
3753    
3754  
3755         LyXDirection direction = getParDirection();
3756         if (direction != par_direction) {
3757                 if (direction == LYX_DIR_LEFT_TO_RIGHT)
3758                         os << "\\unsethebrew\n";
3759                 else
3760                         os << "\\sethebrew\n";
3761                 texrow.newline();
3762         }
3763
3764         if (footnotekind != LyXParagraph::FOOTNOTE
3765             || !footer_in_body) {
3766                 // Process text for all floats except footnotes in body
3767                 do {
3768                         LyXLayout const & style =
3769                                 textclasslist
3770                                 .Style(current_view->buffer()->params
3771                                        .textclass,
3772                                        par->layout);
3773                         if (par->IsDummy())
3774                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3775                                        << endl;
3776                         if (style.isEnvironment()
3777                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3778                                 // Allows the use of minipages within float
3779                                 // environments. Shouldn't be circular because
3780                                 // we don't support footnotes inside
3781                                 // floats (yet). ARRae
3782                                 par = par->TeXEnvironment(os, texrow,
3783                                                           foot, foot_texrow,
3784                                                           foot_count);
3785                         } else {
3786                                 par = par->TeXOnePar(os, texrow,
3787                                                      foot, foot_texrow,
3788                                                      foot_count);
3789                         }
3790                         
3791                         if (par && !par->IsDummy() && par->depth > depth) {
3792                                 par = par->TeXDeeper(os, texrow,
3793                                                      foot, foot_texrow,
3794                                                      foot_count);
3795                         }
3796                 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3797         } else {
3798                 // process footnotes > depth 0 or in environments separately
3799                 // NOTE: Currently don't support footnotes within footnotes
3800                 //       even though that is possible using the \footnotemark
3801 #ifdef HAVE_SSTREAM
3802                 ostringstream dummy;
3803 #else
3804                 ostrstream dummy;
3805 #endif
3806                 TexRow dummy_texrow;
3807                 int dummy_count = 0;
3808                 do {
3809                         LyXLayout const & style =
3810                                 textclasslist
3811                                 .Style(current_view->buffer()->params
3812                                        .textclass,
3813                                        par->layout);
3814                         if (par->IsDummy())
3815                                 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3816                                        << endl;
3817                         if (style.isEnvironment()
3818                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3819                                 // Allows the use of minipages within float
3820                                 // environments. Shouldn't be circular because
3821                                 // we don't support footnotes inside
3822                                 // floats (yet). ARRae
3823                                 par = par->TeXEnvironment(foot, foot_texrow,
3824                                                           dummy, dummy_texrow,
3825                                                           dummy_count);
3826                         } else {
3827                                 par = par->TeXOnePar(foot, foot_texrow,
3828                                                      dummy, dummy_texrow,
3829                                                      dummy_count);
3830                         }
3831
3832                         if (par && !par->IsDummy() && par->depth > depth) {
3833                                 par = par->TeXDeeper(foot, foot_texrow,
3834                                                      dummy, dummy_texrow,
3835                                                      dummy_count);
3836                         }
3837                 } while (par
3838                          && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3839                 if (dummy_count) {
3840                         lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3841                                 "Footnote in a Footnote -- not supported"
3842                                << endl;
3843                 }
3844 #ifndef HAVE_OSTREAM
3845                 delete [] dummy.str();
3846 #endif
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                         os << '}';
3858                 }
3859                 break;
3860         case LyXParagraph::MARGIN:
3861                 os << '}';
3862                 break;
3863         case LyXParagraph::FIG:
3864                 if (pextra_type == PEXTRA_FLOATFLT
3865                     && (!pextra_width.empty()
3866                         || !pextra_widthp.empty()))
3867                         os << "\\end{floatingfigure}";
3868                 else
3869                         os << "\\end{figure}";
3870                 break;
3871         case LyXParagraph::TAB:
3872                 os << "\\end{table}";
3873                 break;
3874         case LyXParagraph::WIDE_FIG:
3875                 os << "\\end{figure*}";
3876                 break;
3877         case LyXParagraph::WIDE_TAB:
3878                 os << "\\end{table*}";
3879                 break;
3880         case LyXParagraph::ALGORITHM:
3881                 os << "\\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                 os << "\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 }