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