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