1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-1999 The LyX Team.
9 * ====================================================== */
14 #pragma implementation "lyxparagraph.h"
21 #include "lyxparagraph.h"
22 #include "support/textutils.h"
25 #include "tex-strings.h"
26 #include "bufferparams.h"
27 #include "support/FileInfo.h"
28 #include "support/LAssert.h"
30 #include "LaTeXFeatures.h"
31 #include "insets/insetinclude.h"
32 #include "support/filetools.h"
33 #include "lyx_gui_misc.h"
37 extern void addNewlineAndDepth(string & file, int const depth); // Jug 990923
38 int tex_code_break_column = 72; // needs non-zero initialization. set later.
39 // this is a bad idea, but how can LyXParagraph find its buffer to get
40 // parameters? (JMarc)
41 extern BufferView * current_view;
46 extern string bibitemWidthest();
48 // this is a minibuffer
49 static char minibuffer_char;
50 static LyXFont minibuffer_font;
51 static Inset * minibuffer_inset;
54 // Initialization of the counter for the paragraph id's,
55 // declared in lyxparagraph.h
56 unsigned int LyXParagraph::paragraph_id = 0;
59 LyXParagraph::LyXParagraph()
61 text.reserve(500); // is this number too big?
63 for (int i = 0; i < 10; ++i) setCounter(i , 0);
69 #ifndef NEW_FONTTABLE // OK
72 #ifndef NEW_INSETTABLE
75 footnoteflag = LyXParagraph::NO_FOOTNOTE;
76 footnotekind = LyXParagraph::FOOTNOTE; // should not be needed
78 align = LYX_ALIGN_BLOCK;
80 /* table stuff -- begin*/
82 /* table stuff -- end*/
84 bibkey = 0; // ale970302
89 // This konstruktor inserts the new paragraph in a list.
90 LyXParagraph::LyXParagraph(LyXParagraph * par)
93 par->text.resize(par->text.size());
95 for (int i = 0; i < 10; ++i) setCounter(i, 0);
99 // double linked list begin
102 next->previous = this;
104 previous->next = this;
106 #ifndef NEW_FONTTABLE // OK
109 #ifndef NEW_INSETTABLE
112 footnoteflag = LyXParagraph::NO_FOOTNOTE;
113 footnotekind = LyXParagraph::FOOTNOTE;
115 /* table stuff -- begin*/
117 /* table stuff -- end*/
118 id_ = paragraph_id++;
120 bibkey = 0; // ale970302
126 void LyXParagraph::writeFile(ostream & os, BufferParams & params,
127 char footflag, char dth)
129 LyXFont font1, font2;
135 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
137 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
139 // The beginning or the end of a footnote environment?
140 if (footflag != footnoteflag) {
141 footflag = footnoteflag;
143 os << "\n\\begin_float "
144 << string_footnotekinds[footnotekind]
147 os << "\n\\end_float ";
151 // The beginning or end of a deeper (i.e. nested) area?
154 while (depth > dth) {
155 os << "\n\\begin_deeper ";
159 while (depth < dth) {
160 os << "\n\\end_deeper ";
166 // First write the layout
168 << textclasslist.NameOfLayout(params.textclass, layout)
171 // Maybe some vertical spaces.
172 if (added_space_top.kind() != VSpace::NONE)
173 os << "\\added_space_top "
174 << added_space_top.asLyXCommand() << " ";
175 if (added_space_bottom.kind() != VSpace::NONE)
176 os << "\\added_space_bottom "
177 << added_space_bottom.asLyXCommand() << " ";
179 // The labelwidth string used in lists.
180 if (!labelwidthstring.empty())
181 os << "\\labelwidthstring "
182 << labelwidthstring << '\n';
184 // Lines above or below?
188 os << "\\line_bottom ";
190 // Pagebreaks above or below?
192 os << "\\pagebreak_top ";
193 if (pagebreak_bottom)
194 os << "\\pagebreak_bottom ";
196 // Start of appendix?
197 if (start_of_appendix)
198 os << "\\start_of_appendix ";
205 if (align != LYX_ALIGN_LAYOUT) {
207 case LYX_ALIGN_LEFT: h = 1; break;
208 case LYX_ALIGN_RIGHT: h = 2; break;
209 case LYX_ALIGN_CENTER: h = 3; break;
210 default: h = 0; break;
212 os << "\\align " << string_align[h] << " ";
214 if (pextra_type != PEXTRA_NONE) {
215 os << "\\pextra_type " << pextra_type;
216 if (pextra_type == PEXTRA_MINIPAGE) {
217 os << " \\pextra_alignment "
220 os << " \\pextra_hfill "
222 if (pextra_start_minipage)
223 os << " \\pextra_start_minipage "
224 << pextra_start_minipage;
226 if (!pextra_width.empty()) {
227 os << " \\pextra_width "
228 << VSpace(pextra_width).asLyXCommand();
229 } else if (!pextra_widthp.empty()) {
230 os << " \\pextra_widthp "
236 // Dummy layout. This means that a footnote ended.
237 os << "\n\\end_float ";
238 footflag = LyXParagraph::NO_FOOTNOTE;
241 // It might be a table.
243 os << "\\LyXTable\n";
251 font1 = LyXFont(LyXFont::ALL_INHERIT);
254 for (size_type i = 0; i < size(); ++i) {
260 // Write font changes
261 font2 = GetFontSettings(i);
262 if (font2 != font1) {
263 font2.lyxWriteChanges(font1, os);
273 if (inset->DirectWrite()) {
274 // international char, let it write
275 // code directly so it's shorter in
279 os << "\n\\begin_inset ";
281 os << "\n\\end_inset \n\n";
286 os << "\n\\newline \n";
290 os << "\n\\hfill \n";
293 case META_PROTECTED_SEPARATOR:
294 os << "\n\\protected_separator \n";
298 os << "\n\\backslash \n";
302 if (i + 1 < size() && GetChar(i + 1) == ' ') {
309 if ((column > 70 && c == ' ')
314 // this check is to amend a bug. LyX sometimes
315 // inserts '\0' this could cause problems.
319 lyxerr << "ERROR (LyXParagraph::writeFile):"
320 " NULL char in structure." << endl;
326 // now write the next paragraph
328 next->writeFile(os, params, footflag, dth);
332 void LyXParagraph::validate(LaTeXFeatures & features)
334 // this will be useful later
335 LyXLayout const & layout =
336 textclasslist.Style(current_view->buffer()->params.textclass,
340 if (line_top || line_bottom)
341 features.lyxline = true;
344 features.layout[GetLayout()] = true;
347 #ifdef NEW_FONTTABLE // OK, but does not affect structure anyway
348 for (FontList::const_iterator cit = fontlist.begin();
349 cit != fontlist.end(); ++cit) {
350 if ((*cit).font.noun() == LyXFont::ON) {
351 lyxerr[Debug::LATEX] << "font.noun: "
352 << (*cit).font.noun()
354 features.noun = true;
355 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
356 << (*cit).font.stateText()
359 switch ((*cit).font.color()) {
361 case LyXFont::INHERIT_COLOR:
362 case LyXFont::IGNORE_COLOR:
365 features.color = true;
366 lyxerr[Debug::LATEX] << "Color enabled. Font: "
367 << (*cit).font.stateText()
372 FontTable * tmpfonttable = fonttable;
373 while (tmpfonttable) {
374 if (tmpfonttable->font.noun() == LyXFont::ON) {
375 lyxerr[Debug::LATEX] << "font.noun: "
376 << tmpfonttable->font.noun()
378 features.noun = true;
379 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
380 << tmpfonttable->font.stateText()
383 switch (tmpfonttable->font.color()) {
385 case LyXFont::INHERIT_COLOR:
386 case LyXFont::IGNORE_COLOR:
389 features.color = true;
390 lyxerr[Debug::LATEX] << "Color enabled. Font: "
391 << tmpfonttable->font.stateText()
394 tmpfonttable = tmpfonttable->next;
398 #ifdef NEW_INSETTABLE
399 for (InsetList::const_iterator cit = insetlist.begin();
400 cit != insetlist.end(); ++cit) {
402 (*cit).inset->Validate(features);
405 InsetTable * tmpinsettable = insettable;
406 while (tmpinsettable) {
407 if (tmpinsettable->inset) {
408 tmpinsettable->inset->Validate(features);
410 tmpinsettable = tmpinsettable->next;
414 if (table && table->IsLongTable())
415 features.longtable = true;
416 if (pextra_type == PEXTRA_INDENT)
417 features.LyXParagraphIndent = true;
418 if (pextra_type == PEXTRA_FLOATFLT)
419 features.floatflt = true;
420 if (layout.needprotect
421 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
422 features.NeedLyXFootnoteCode = true;
423 if ((current_view->buffer()->params.paragraph_separation == BufferParams::PARSEP_INDENT) &&
424 (pextra_type == LyXParagraph::PEXTRA_MINIPAGE))
425 features.NeedLyXMinipageIndent = true;
426 if (table && table->NeedRotating())
427 features.rotating = true;
428 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
429 features.algorithm = true;
433 // First few functions needed for cut and paste and paragraph breaking.
434 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos) const
436 minibuffer_char = GetChar(pos);
437 minibuffer_font = GetFontSettings(pos);
438 minibuffer_inset = 0;
439 if (minibuffer_char == LyXParagraph::META_INSET) {
441 minibuffer_inset = GetInset(pos)->Clone();
443 minibuffer_inset = 0;
444 minibuffer_char = ' ';
445 // This reflects what GetInset() does (ARRae)
451 void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos)
453 minibuffer_char = GetChar(pos);
454 minibuffer_font = GetFontSettings(pos);
455 minibuffer_inset = 0;
456 if (minibuffer_char == LyXParagraph::META_INSET) {
458 minibuffer_inset = GetInset(pos);
459 // This is a little hack since I want exactly
460 // the inset, not just a clone. Otherwise
461 // the inset would be deleted when calling Erase(pos)
463 #ifdef NEW_INSETTABLE
464 for (InsetList::iterator it = insetlist.begin();
465 it != insetlist.end(); ++it) {
466 if ((*it).pos == pos) {
473 InsetTable * tmpi = insettable;
474 while (tmpi && tmpi->pos != pos) {
477 if (tmpi) { // This should always be true.
482 minibuffer_inset = 0;
483 minibuffer_char = ' ';
484 // This reflects what GetInset() does (ARRae)
489 // Erase(pos); now the caller is responsible for that.
493 void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
495 InsertChar(pos, minibuffer_char);
496 SetFont(pos, minibuffer_font);
497 if (minibuffer_char == LyXParagraph::META_INSET)
498 InsertInset(pos, minibuffer_inset);
505 void LyXParagraph::Clear()
510 pagebreak_top = false;
511 pagebreak_bottom = false;
513 added_space_top = VSpace(VSpace::NONE);
514 added_space_bottom = VSpace(VSpace::NONE);
516 align = LYX_ALIGN_LAYOUT;
520 pextra_type = PEXTRA_NONE;
521 pextra_width.clear();
522 pextra_widthp.clear();
523 pextra_alignment = MINIPAGE_ALIGN_TOP;
524 pextra_hfill = false;
525 pextra_start_minipage = false;
528 labelwidthstring.clear();
532 start_of_appendix = false;
536 // the destructor removes the new paragraph from the list
537 LyXParagraph::~LyXParagraph()
540 previous->next = next;
542 next->previous = previous;
544 #ifdef NEW_INSETTABLE
545 for (InsetList::iterator it = insetlist.begin();
546 it != insetlist.end(); ++it) {
550 InsetTable * tmpinset;
552 tmpinset = insettable;
553 insettable = insettable->next;
554 if (tmpinset->inset) // DEL LINE
555 delete tmpinset->inset;
557 if (insettable && insettable->next == insettable) {
558 // somehow this recursion appears occasionally
559 // but I can't find where. This bandaid
560 // helps but isn't the best fix. (ARRae)
561 if (insettable->inset) { // DEL LINE
562 delete insettable->inset;
569 #ifndef NEW_FONTTABLE // OK
573 fonttable = fonttable->next;
578 /* table stuff -- begin*/
579 if (table) // DEL LINE
581 /* table stuff -- end*/
584 if (bibkey) // DEL LINE
589 void LyXParagraph::Erase(LyXParagraph::size_type pos)
591 // > because last is the next unused position, and you can
592 // use it if you want
594 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
595 NextAfterFootnote()->Erase(pos - text.size() - 1);
597 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
598 "position does not exist." << endl;
601 if (pos < size()) { // last is free for insertation, but should be empty
602 // if it is an inset, delete the inset entry
603 if (text[pos] == LyXParagraph::META_INSET) {
605 #ifdef NEW_INSETTABLE
606 for (InsetList::iterator it = insetlist.begin();
607 it != insetlist.end(); ++it) {
608 if ((*it).pos == pos) {
615 InsetTable *tmpi = insettable;
616 InsetTable *tmpi2 = tmpi;
617 while (tmpi && tmpi->pos != pos) {
621 if (tmpi) { // this should always be true
622 if (tmpi->inset) // delete the inset if it exists // DEL LINE
624 if (tmpi == insettable)
625 insettable = tmpi->next;
627 tmpi2->next = tmpi->next;
632 text.erase(text.begin() + pos);
633 // Erase entries in the tables.
634 #ifdef NEW_FONTTABLE // Seems OK
635 for (FontList::iterator it = fontlist.begin();
636 it != fontlist.end(); ++it) {
637 if (pos >= (*it).pos && pos <= (*it).pos_end) {
638 if ((*it).pos == (*it).pos_end) {
639 // If it is a multi-character font
640 // entry, we just make it smaller
641 // (see update below), otherwise we
648 // Update all other entries.
649 for (FontList::iterator it = fontlist.begin();
650 it != fontlist.end(); ++it) {
653 if ((*it).pos_end >= pos)
658 FontTable * tmp = fonttable;
659 FontTable * prev = 0;
660 while (tmp && !found) {
661 if (pos >= tmp->pos && pos <= tmp->pos_end)
669 if (found && tmp->pos == tmp->pos_end) {
670 // if it is a multi-character font entry, we just make
671 // it smaller (see update below), otherwise we should
674 prev->next = tmp->next;
676 fonttable = tmp->next;
681 // Update all other entries.
687 if (tmp->pos_end >= pos)
692 // Update the inset table.
693 #ifdef NEW_INSETTABLE
694 for (InsetList::iterator it = insetlist.begin();
695 it != insetlist.end(); ++it) {
700 InsetTable * tmpi = insettable;
708 lyxerr << "ERROR (LyXParagraph::Erase): "
709 "can't erase non-existant char." << endl;
714 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
716 // > because last is the next unused position, and you can
717 // use it if you want
720 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
721 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
724 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
725 "position does not exist." << endl;
728 text.insert(text.begin() + pos, c);
729 // Update the font table.
730 #ifdef NEW_FONTTABLE // Seems OK
731 for (FontList::iterator it = fontlist.begin();
732 it != fontlist.end(); ++it) {
733 if ((*it).pos >= pos)
735 if ((*it).pos_end >= pos)
739 FontTable * tmp = fonttable;
743 if (tmp->pos_end >= pos)
749 // Update the inset table.
750 #ifdef NEW_INSETTABLE
751 for (InsetList::iterator it = insetlist.begin();
752 it != insetlist.end(); ++it) {
753 if ((*it).pos >= pos)
757 InsetTable * tmpi = insettable;
759 if (tmpi->pos >= pos)
767 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
770 // > because last is the next unused position, and you can
771 // use it if you want
774 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
776 ->InsertInset(pos - text.size() - 1, inset);
778 lyxerr << "ERROR (LyXParagraph::InsertInset): "
779 "position does not exist: " << pos << endl;
782 if (text[pos] != LyXParagraph::META_INSET) {
783 lyxerr << "ERROR (LyXParagraph::InsertInset): "
784 "there is no LyXParagraph::META_INSET" << endl;
789 // Add a new entry in the inset table.
790 #ifdef NEW_INSETTABLE
792 InsetList::iterator it =
793 insetlist.insert(insetlist.begin(), tmpi);
797 InsetTable * tmpi = new InsetTable;
800 tmpi->next = insettable;
807 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
811 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
812 return NextAfterFootnote()
813 ->GetInset(pos - text.size() - 1);
815 lyxerr << "ERROR (LyXParagraph::GetInset): "
816 "position does not exist: "
822 #ifdef NEW_INSETTABLE
823 for (InsetList::iterator it = insetlist.begin();
824 it != insetlist.end(); ++it) {
825 if ((*it).pos == pos) {
829 lyxerr << "ERROR (LyXParagraph::GetInset): "
830 "Inset does not exist: " << pos << endl;
831 text[pos] = ' '; // WHY!!! does this set the pos to ' '????
832 // Did this commenting out introduce a bug? So far I have not
833 // see any, please enlighten me. (Lgb)
834 // My guess is that since the inset does not exist, we might
835 // as well replace it with a space to prevent craches. (Asger)
838 InsetTable * tmpi = insettable;
840 while (tmpi && tmpi->pos != pos)
846 lyxerr << "ERROR (LyXParagraph::GetInset): "
847 "Inset does not exist: " << pos << endl;
848 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
849 // Did this commenting out introduce a bug? So far I have not
850 // seen any, please enlighten me. (Lgb)
851 // My guess is that since the inset does not exist, we might
852 // as well replace it with a space to prevent crashes. (Asger)
859 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
863 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
864 return NextAfterFootnote()
865 ->GetInset(pos - text.size() - 1);
867 lyxerr << "ERROR (LyXParagraph::GetInset): "
868 "position does not exist: "
874 #ifdef NEW_INSETTABLE
875 for (InsetList::const_iterator cit = insetlist.begin();
876 cit != insetlist.end(); ++cit) {
877 if ((*cit).pos == pos) {
881 lyxerr << "ERROR (LyXParagraph::GetInset): "
882 "Inset does not exist: " << pos << endl;
883 //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
884 // Did this commenting out introduce a bug? So far I have not
885 // see any, please enlighten me. (Lgb)
886 // My guess is that since the inset does not exist, we might
887 // as well replace it with a space to prevent craches. (Asger)
890 InsetTable * tmpi = insettable;
892 while (tmpi && tmpi->pos != pos)
898 lyxerr << "ERROR (LyXParagraph::GetInset): "
899 "Inset does not exist: " << pos << endl;
900 // in the const version we need to comment it out anyway...
901 //text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
902 // Did this commenting out introduce a bug? So far I have not
903 // seen any, please enlighten me. (Lgb)
904 // My guess is that since the inset does not exist, we might
905 // as well replace it with a space to prevent crashes. (Asger)
912 // Gets uninstantiated font setting at position.
913 // Optimized after profiling. (Asger)
914 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos) const
917 #ifdef NEW_FONTTABLE // Seems OK
918 for (FontList::const_iterator cit = fontlist.begin();
919 cit != fontlist.end(); ++cit) {
920 if (pos >= (*cit).pos && pos <= (*cit).pos_end)
924 FontTable * tmp = fonttable;
926 if (pos >= tmp->pos && pos <= tmp->pos_end)
932 // > because last is the next unused position, and you can
933 // use it if you want
934 else if (pos > size()) {
936 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
937 return NextAfterFootnote()
938 ->GetFontSettings(pos - text.size() - 1);
940 // Why is it an error to ask for the font of a
941 // position that does not exist? Would it be
942 // enough for this to be enabled on debug?
943 // We want strict error checking, but it's ok to only
944 // have it when debugging. (Asger)
945 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
946 "position does not exist. "
947 << pos << " (" << static_cast<int>(pos)
951 return GetFontSettings(pos - 1);
953 return LyXFont(LyXFont::ALL_INHERIT);
957 // Gets the fully instantiated font at a given position in a paragraph
958 // This is basically the same function as LyXText::GetFont() in text2.C.
959 // The difference is that this one is used for generating the LaTeX file,
960 // and thus cosmetic "improvements" are disallowed: This has to deliver
961 // the true picture of the buffer. (Asger)
962 // If position is -1, we get the layout font of the paragraph.
963 // If position is -2, we get the font of the manual label of the paragraph.
964 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos) const
967 LyXLayout const & layout =
968 textclasslist.Style(current_view->buffer()->params.textclass,
970 LyXParagraph::size_type main_body = 0;
971 if (layout.labeltype == LABEL_MANUAL)
972 main_body = BeginningOfMainBody();
977 layoutfont = layout.labelfont;
979 layoutfont = layout.font;
980 tmpfont = GetFontSettings(pos);
981 tmpfont.realize(layoutfont);
983 // process layoutfont for pos == -1 and labelfont for pos < -1
985 tmpfont = layout.font;
987 tmpfont = layout.labelfont;
990 // check for environment font information
991 char par_depth = GetDepth();
992 LyXParagraph const * par = this;
993 while (par && par_depth && !tmpfont.resolved()) {
994 par = par->DepthHook(par_depth - 1);
996 tmpfont.realize(textclasslist.
997 Style(current_view->buffer()->params.textclass,
998 par->GetLayout()).font);
999 par_depth = par->GetDepth();
1003 tmpfont.realize(textclasslist
1004 .TextClass(current_view->buffer()->params.textclass)
1010 /// Returns the height of the highest font in range
1012 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
1013 LyXParagraph::size_type endpos) const
1015 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
1016 #ifdef NEW_FONTTABLE // Seems OK
1017 for (FontList::const_iterator cit = fontlist.begin();
1018 cit != fontlist.end(); ++cit) {
1019 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
1020 LyXFont::FONT_SIZE size = (*cit).font.size();
1021 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
1026 FontTable * tmp = fonttable;
1028 if (startpos <= tmp->pos_end && endpos >= tmp->pos) {
1029 LyXFont::FONT_SIZE size = tmp->font.size();
1030 if (size > maxsize && size<= LyXFont::SIZE_HUGER)
1040 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
1047 // > because last is the next unused position, and you can
1048 // use it if you want
1049 else if (pos > size()) {
1050 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1051 return NextAfterFootnote()
1052 ->GetChar(pos - text.size() - 1);
1054 lyxerr << "ERROR (LyXParagraph::GetChar): "
1055 "position does not exist."
1056 << pos << " (" << static_cast<int>(pos)
1062 // We should have a footnote environment.
1063 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
1064 // Notice that LyX does request the
1065 // last char from time to time. (Asger)
1066 //lyxerr << "ERROR (LyXParagraph::GetChar): "
1067 // "expected footnote." << endl;
1070 switch (next->footnotekind) {
1071 case LyXParagraph::FOOTNOTE:
1072 return LyXParagraph::META_FOOTNOTE;
1073 case LyXParagraph::MARGIN:
1074 return LyXParagraph::META_MARGIN;
1075 case LyXParagraph::FIG:
1076 case LyXParagraph::WIDE_FIG:
1077 return LyXParagraph::META_FIG;
1078 case LyXParagraph::TAB:
1079 case LyXParagraph::WIDE_TAB:
1080 return LyXParagraph::META_TAB;
1081 case LyXParagraph::ALGORITHM:
1082 return LyXParagraph::META_ALGORITHM;
1084 return '\0'; // to shut up gcc
1089 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
1096 // > because last is the next unused position, and you can
1097 // use it if you want
1098 else if (pos > size()) {
1099 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1100 return NextAfterFootnote()
1101 ->GetChar(pos - text.size() - 1);
1103 lyxerr << "ERROR (LyXParagraph::GetChar const): "
1104 "position does not exist."
1105 << pos << " (" << static_cast<int>(pos)
1111 // We should have a footnote environment.
1112 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
1113 // Notice that LyX does request the
1114 // last char from time to time. (Asger)
1115 //lyxerr << "ERROR (LyXParagraph::GetChar): "
1116 // "expected footnote." << endl;
1119 switch (next->footnotekind) {
1120 case LyXParagraph::FOOTNOTE:
1121 return LyXParagraph::META_FOOTNOTE;
1122 case LyXParagraph::MARGIN:
1123 return LyXParagraph::META_MARGIN;
1124 case LyXParagraph::FIG:
1125 case LyXParagraph::WIDE_FIG:
1126 return LyXParagraph::META_FIG;
1127 case LyXParagraph::TAB:
1128 case LyXParagraph::WIDE_TAB:
1129 return LyXParagraph::META_TAB;
1130 case LyXParagraph::ALGORITHM:
1131 return LyXParagraph::META_ALGORITHM;
1133 return '\0'; // to shut up gcc
1138 // return an string of the current word, and the end of the word in lastpos.
1139 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
1143 // the current word is defined as starting at the first character
1144 // from the immediate left of lastpospos which meets the definition
1145 // of IsLetter(), continuing to the last character to the right
1146 // of this meeting IsLetter.
1152 // move back until we have a letter
1154 //there's no real reason to have firstpos & lastpos as
1155 //separate variables as this is written, but maybe someon
1156 // will want to return firstpos in the future.
1158 //since someone might have typed a punctuation first
1159 int firstpos = lastpos;
1161 while ((firstpos >= 0) && !IsLetter(firstpos))
1164 // now find the beginning by looking for a nonletter
1166 while ((firstpos>= 0) && IsLetter(firstpos))
1169 // the above is now pointing to the preceeding non-letter
1173 // so copy characters into theword until we get a nonletter
1174 // note that this can easily exceed lastpos, wich means
1175 // that if used in the middle of a word, the whole word
1178 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1185 LyXParagraph::size_type LyXParagraph::Last() const
1187 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1188 return text.size() + NextAfterFootnote()->Last() + 1;
1189 // the 1 is the symbol
1196 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
1198 // > because last is the next unused position, and you can
1199 // use it if you want
1202 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1203 return NextAfterFootnote()
1204 ->ParFromPos(pos - text.size() - 1);
1206 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1207 "position does not exist." << endl;
1214 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
1216 // > because last is the next unused position, and you can
1217 // use it if you want
1220 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1221 return NextAfterFootnote()
1222 ->PositionInParFromPos(pos - text.size() - 1);
1225 "ERROR (LyXParagraph::PositionInParFromPos): "
1226 "position does not exist." << endl;
1234 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1235 LyXFont const & font)
1237 // > because last is the next unused position, and you can
1238 // use it if you want
1241 next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1242 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1245 lyxerr << "ERROR (LyXParagraph::SetFont): "
1246 "position does not exist." << endl;
1250 LyXFont patternfont(LyXFont::ALL_INHERIT);
1252 // First, reduce font against layout/label font
1253 // Update: The SetCharFont() routine in text2.C already
1254 // reduces font, so we don't need to do that here. (Asger)
1255 // No need to simplify this because it will disappear
1256 // in a new kernel. (Asger)
1257 // Next search font table
1258 #ifdef NEW_FONTTABLE
1259 FontList::iterator tmp = fontlist.begin();
1260 for (; tmp != fontlist.end(); ++tmp) {
1261 if (pos >= (*tmp).pos && pos <= (*tmp).pos_end) {
1265 if (tmp == fontlist.end()) { // !found
1266 // if we did not find a font entry, but if the font at hand
1267 // is the same as default, we just forget it
1268 if (font == patternfont) return;
1270 // ok, we did not find a font entry. But maybe there is exactly
1271 // the needed font ientry one position left
1272 FontList::iterator tmp2 = fontlist.begin();
1273 for (; tmp2 != fontlist.end(); ++tmp2) {
1274 if (pos - 1 >= (*tmp2).pos
1275 && pos - 1 <= (*tmp2).pos_end)
1278 if (tmp2 != fontlist.end()) {
1279 // ok there is one, maybe it is exactly
1281 if ((*tmp2).font == font) {
1282 // put the position under the font
1287 // Add a new entry in the
1288 // fontlist for the position
1292 ft.font = font; // or patternfont
1293 // It seems that using font instead of patternfont here
1294 // fixes all the problems. This also surfaces a "bug" in
1296 fontlist.insert(fontlist.begin(), ft);
1297 } else if ((*tmp).pos != (*tmp).pos_end) { // we found a font entry. maybe we have to split it and create a new one.
1299 // more than one character
1300 if (pos == (*tmp).pos) {
1301 // maybe we should enlarge the left fonttable
1302 FontList::iterator tmp2 = fontlist.begin();
1303 for (; tmp2 != fontlist.end(); ++tmp2) {
1304 if (pos - 1 >= (*tmp2).pos
1305 && pos - 1 <= (*tmp2).pos_end)
1308 // Is there is one, and is it exactly
1310 if (tmp2 != fontlist.end() &&
1311 (*tmp2).font == font) {
1312 // Put the position under the font
1318 // Add a new entry in the
1319 // fontlist for the position
1322 ft.pos_end = (*tmp).pos_end;
1323 ft.font = (*tmp).font;
1324 (*tmp).pos_end = pos;
1326 fontlist.insert(fontlist.begin(), ft);
1327 } else if (pos == (*tmp).pos_end) {
1328 // Add a new entry in the
1329 // fontlist for the position
1331 ft.pos = (*tmp).pos;
1332 ft.pos_end = (*tmp).pos_end - 1;
1333 ft.font = (*tmp).font;
1334 (*tmp).pos = (*tmp).pos_end;
1336 fontlist.insert(fontlist.begin(), ft);
1338 // Add a new entry in the
1339 // fontlist for the position
1341 ft.pos = (*tmp).pos;
1342 ft.pos_end = pos - 1;
1343 ft.font = (*tmp).font;
1347 ft2.pos_end = (*tmp).pos_end;
1348 ft2.font = (*tmp).font;
1351 (*tmp).pos_end = pos;
1354 fontlist.insert(fontlist.begin(), ft);
1355 fontlist.insert(fontlist.begin(), ft2);
1365 FontTable * tmp = fonttable;
1366 while (tmp && !found) {
1367 if (pos >= tmp->pos && pos <= tmp->pos_end)
1374 // if we did not find a font entry, but if the font at hand
1375 // is the same as default, we just forget it
1376 if (font == patternfont)
1379 // ok, we did not find a font entry. But maybe there is exactly
1380 // the needed font entry one position left
1383 while (tmp2 && !found) {
1384 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1390 // ok there is one. maybe it is exactly
1392 if (tmp2->font == font) {
1393 // put the position under the font
1398 // Add a new entry in the
1399 // fonttable for the position
1400 tmp = new FontTable;
1403 tmp->font = patternfont; // It seems that is actually totally
1404 // wrong to use patternfont here, the correct should be font
1405 // lockily at the end of this function we have
1406 // tmp->font = font, so this one setting it to patternfont
1408 tmp->next = fonttable;
1411 // we found a font entry. maybe we have
1412 // to split it and create a new one
1414 if (tmp->pos != tmp->pos_end) { // more than one character
1415 if (pos == tmp->pos) {
1416 // maybe we could enlarge the left fonttable
1419 while (tmp2 && !found) {
1420 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1426 // Is there is one, and is it exactly
1428 if (found && tmp2->font == font) {
1429 // Put the position under the font
1435 // Add a new entry in the
1436 // fonttable for the position
1437 tmp2 = new FontTable;
1438 tmp2->pos = pos + 1;
1439 tmp2->pos_end = tmp->pos_end;
1440 tmp2->font = tmp->font;
1442 tmp2->next = fonttable;
1445 else if (pos == tmp->pos_end) {
1446 // Add a new entry in the
1447 // fonttable for the position
1448 tmp2 = new FontTable;
1449 tmp2->pos = tmp->pos;
1450 tmp2->pos_end = tmp->pos_end - 1;
1451 tmp2->font = tmp->font;
1452 tmp->pos = tmp->pos_end;
1453 tmp2->next = fonttable;
1457 // Add a new entry in the
1458 // fonttable for the position
1459 tmp2 = new FontTable;
1460 tmp2->pos = tmp->pos;
1461 tmp2->pos_end = pos - 1;
1462 tmp2->font = tmp->font;
1463 tmp2->next = fonttable;
1466 tmp2 = new FontTable;
1467 tmp2->pos = pos + 1;
1468 tmp2->pos_end = tmp->pos_end;
1469 tmp2->font = tmp->font;
1470 tmp2->next = fonttable;
1483 // This function is able to hide closed footnotes.
1484 LyXParagraph * LyXParagraph::Next()
1486 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1487 LyXParagraph * tmp = next;
1489 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1491 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1492 return tmp->Next(); /* there can be more than one
1493 footnote in a logical
1496 return next; // This should never happen!
1502 LyXParagraph * LyXParagraph::NextAfterFootnote()
1504 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1505 LyXParagraph * tmp = next;
1506 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1508 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1509 return tmp; /* there can be more than one footnote
1510 in a logical paragraph */
1512 return next; // This should never happen!
1518 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1520 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1521 LyXParagraph * tmp = next;
1522 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1524 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1525 return tmp; /* there can be more than one footnote
1526 in a logical paragraph */
1528 return next; // This should never happen!
1534 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1537 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1539 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1540 tmp = tmp->previous;
1541 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1542 return tmp; /* there can be more than one footnote
1543 in a logical paragraph */
1545 return previous; // This should never happen!
1551 LyXParagraph * LyXParagraph::LastPhysicalPar()
1553 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1556 LyXParagraph * tmp = this;
1558 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1559 tmp = tmp->NextAfterFootnote();
1566 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1570 LyXParagraph * tmppar = this;
1574 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1575 tmppar = tmppar->previous;
1584 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1588 LyXParagraph const * tmppar = this;
1592 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1593 tmppar = tmppar->previous;
1602 // This function is able to hide closed footnotes.
1603 LyXParagraph * LyXParagraph::Previous()
1605 LyXParagraph * tmp = previous;
1610 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1611 tmp = tmp->previous;
1613 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1614 tmp = tmp->previous;
1615 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1616 return tmp->next->Previous();
1625 // This function is able to hide closed footnotes.
1626 LyXParagraph const * LyXParagraph::Previous() const
1628 LyXParagraph * tmp = previous;
1633 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1634 tmp = tmp->previous;
1636 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1637 tmp = tmp->previous;
1638 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1639 return tmp->next->Previous();
1648 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1651 size_type i, pos_end, pos_first;
1652 // create a new paragraph
1653 LyXParagraph * par = ParFromPos(pos);
1654 LyXParagraph * firstpar = FirstPhysicalPar();
1656 LyXParagraph * tmp = new LyXParagraph(par);
1658 tmp->footnoteflag = footnoteflag;
1659 tmp->footnotekind = footnotekind;
1661 // this is an idea for a more userfriendly layout handling, I will
1662 // see what the users say
1664 // layout stays the same with latex-environments
1666 tmp->SetOnlyLayout(firstpar->layout);
1667 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1670 if (Last() > pos || !Last() || flag == 2) {
1671 tmp->SetOnlyLayout(firstpar->layout);
1672 tmp->align = firstpar->align;
1673 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1675 tmp->line_bottom = firstpar->line_bottom;
1676 firstpar->line_bottom = false;
1677 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1678 firstpar->pagebreak_bottom = false;
1679 tmp->added_space_bottom = firstpar->added_space_bottom;
1680 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1682 tmp->depth = firstpar->depth;
1683 tmp->noindent = firstpar->noindent;
1685 // copy everything behind the break-position
1686 // to the new paragraph
1688 while (ParFromPos(pos_first) != par)
1691 pos_end = pos_first + par->text.size() - 1;
1692 // The constructor has already reserved 500 elements
1693 //if (pos_end > pos)
1694 // tmp->text.reserve(pos_end - pos);
1696 for (i = pos; i <= pos_end; ++i) {
1697 par->CutIntoMinibuffer(i - pos_first);
1698 tmp->InsertFromMinibuffer(i - pos);
1700 tmp->text.resize(tmp->text.size());
1701 for (i = pos_end; i >= pos; --i)
1702 par->Erase(i - pos_first);
1704 par->text.resize(par->text.size());
1707 // just an idea of me
1709 tmp->line_top = firstpar->line_top;
1710 tmp->pagebreak_top = firstpar->pagebreak_top;
1711 tmp->added_space_top = firstpar->added_space_top;
1712 tmp->bibkey = firstpar->bibkey;
1714 // layout stays the same with latex-environments
1716 firstpar->SetOnlyLayout(tmp->layout);
1717 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1718 firstpar->depth = tmp->depth;
1724 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1726 par = par->FirstPhysicalPar();
1727 footnoteflag = par->footnoteflag;
1728 footnotekind = par->footnotekind;
1730 layout = par->layout;
1731 align = par-> align;
1732 SetLabelWidthString(par->labelwidthstring);
1734 line_bottom = par->line_bottom;
1735 pagebreak_bottom = par->pagebreak_bottom;
1736 added_space_bottom = par->added_space_bottom;
1738 line_top = par->line_top;
1739 pagebreak_top = par->pagebreak_top;
1740 added_space_top = par->added_space_top;
1742 pextra_type = par->pextra_type;
1743 pextra_width = par->pextra_width;
1744 pextra_widthp = par->pextra_widthp;
1745 pextra_alignment = par->pextra_alignment;
1746 pextra_hfill = par->pextra_hfill;
1747 pextra_start_minipage = par->pextra_start_minipage;
1749 noindent = par->noindent;
1754 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1756 LyXParagraph * tmppar = this;
1759 && tmppar->previous->footnoteflag ==
1760 LyXParagraph::CLOSED_FOOTNOTE)
1761 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1762 tmppar = tmppar->previous;
1765 return this; // This should never happen!
1771 LyXParagraph * LyXParagraph::Clone() const
1773 // create a new paragraph
1774 LyXParagraph * result = new LyXParagraph;
1776 result->MakeSameLayout(this);
1778 // this is because of the dummy layout of the paragraphs that
1780 result->layout = layout;
1782 /* table stuff -- begin*/
1784 result->table = table->Clone();
1787 /* table stuff -- end*/
1790 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1793 // copy everything behind the break-position to the new paragraph
1795 for (size_type i = 0; i < size(); ++i) {
1796 CopyIntoMinibuffer(i);
1797 result->InsertFromMinibuffer(i);
1799 result->text.resize(result->text.size());
1804 bool LyXParagraph::HasSameLayout(LyXParagraph const * par)
1806 par = par->FirstPhysicalPar();
1809 par->footnoteflag == footnoteflag &&
1810 par->footnotekind == footnotekind &&
1812 par->layout == layout &&
1814 par->align == align &&
1816 par->line_bottom == line_bottom &&
1817 par->pagebreak_bottom == pagebreak_bottom &&
1818 par->added_space_bottom == added_space_bottom &&
1820 par->line_top == line_top &&
1821 par->pagebreak_top == pagebreak_top &&
1822 par->added_space_top == added_space_top &&
1824 par->pextra_type == pextra_type &&
1825 par->pextra_width == pextra_width &&
1826 par->pextra_widthp == pextra_widthp &&
1827 par->pextra_alignment == pextra_alignment &&
1828 par->pextra_hfill == pextra_hfill &&
1829 par->pextra_start_minipage == pextra_start_minipage &&
1831 par->table == table && // what means: NO TABLE AT ALL
1833 par->noindent == noindent &&
1834 par->depth == depth);
1838 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
1840 // create a new paragraph
1841 LyXParagraph * par = ParFromPos(pos);
1843 LyXParagraph * tmp = new LyXParagraph(par);
1845 tmp->MakeSameLayout(par);
1847 // When can pos < Last()?
1848 // I guess pos == Last() is possible.
1850 // copy everything behind the break-position to the new
1852 size_type pos_first = 0;
1853 while (ParFromPos(pos_first) != par)
1855 size_type pos_end = pos_first + par->text.size() - 1;
1856 // make sure there is enough memory for the now larger
1857 // paragraph. This is not neccessary, because
1858 // InsertFromMinibuffer will enlarge the memory (it uses
1859 // InsertChar of course). But doing it by hand
1860 // is MUCH faster! (only one time, not thousend times!!)
1861 // Not needed since the constructor aleady have
1862 // reserved 500 elements in text.
1863 //if (pos_end > pos)
1864 // tmp->text.reserve(pos_end - pos);
1866 for (size_type i = pos; i <= pos_end; ++i) {
1867 par->CutIntoMinibuffer(i - pos_first);
1868 tmp->InsertFromMinibuffer(i - pos);
1870 tmp->text.resize(tmp->text.size());
1871 for (size_type i = pos_end; i >= pos; --i)
1872 par->Erase(i - pos_first);
1874 par->text.resize(par->text.size());
1879 // Be carefull, this does not make any check at all.
1880 void LyXParagraph::PasteParagraph()
1882 // copy the next paragraph to this one
1883 LyXParagraph * the_next = Next();
1885 LyXParagraph * firstpar = FirstPhysicalPar();
1887 // first the DTP-stuff
1888 firstpar->line_bottom = the_next->line_bottom;
1889 firstpar->added_space_bottom = the_next->added_space_bottom;
1890 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1892 size_type pos_end = the_next->text.size() - 1;
1893 size_type pos_insert = Last();
1895 // ok, now copy the paragraph
1896 for (size_type i = 0; i <= pos_end; ++i) {
1897 the_next->CutIntoMinibuffer(i);
1898 InsertFromMinibuffer(pos_insert + i);
1901 // delete the next paragraph
1906 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1908 LyXParagraph * par = ParFromPos(pos);
1910 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1911 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1917 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1919 LyXParagraph * par = ParFromPos(pos);
1921 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1922 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1928 LyXTextClass::LayoutList::size_type LyXParagraph::GetLayout() const
1930 return FirstPhysicalPar()->layout;
1934 char LyXParagraph::GetDepth() const
1936 return FirstPhysicalPar()->depth;
1940 char LyXParagraph::GetAlign() const
1942 return FirstPhysicalPar()->align;
1946 string LyXParagraph::GetLabestring() const
1948 return FirstPhysicalPar()->labelstring;
1952 int LyXParagraph::GetFirstCounter(int i) const
1954 return FirstPhysicalPar()->counter_[i];
1958 // the next two functions are for the manual labels
1959 string LyXParagraph::GetLabelWidthString() const
1961 if (!FirstPhysicalPar()->labelwidthstring.empty())
1962 return FirstPhysicalPar()->labelwidthstring;
1964 return _("Senseless with this layout!");
1968 void LyXParagraph::SetLabelWidthString(string const & s)
1970 LyXParagraph * par = FirstPhysicalPar();
1972 par->labelwidthstring = s;
1976 void LyXParagraph::SetOnlyLayout(LyXTextClass::LayoutList::size_type new_layout)
1978 LyXParagraph * par = FirstPhysicalPar();
1979 LyXParagraph * ppar = 0;
1980 LyXParagraph * npar = 0;
1982 par->layout = new_layout;
1983 /* table stuff -- begin*/
1986 /* table stuff -- end*/
1987 if (par->pextra_type == PEXTRA_NONE) {
1988 if (par->Previous()) {
1989 ppar = par->Previous()->FirstPhysicalPar();
1992 && (ppar->depth > par->depth))
1993 ppar = ppar->Previous()->FirstPhysicalPar();
1996 npar = par->Next()->NextAfterFootnote();
1999 && (npar->depth > par->depth))
2000 npar = npar->Next()->NextAfterFootnote();
2002 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
2004 p1 = ppar->pextra_width,
2005 p2 = ppar->pextra_widthp;
2006 ppar->SetPExtraType(ppar->pextra_type,
2007 p1.c_str(), p2.c_str());
2009 if ((par->pextra_type == PEXTRA_NONE) &&
2010 npar && (npar->pextra_type != PEXTRA_NONE)) {
2012 p1 = npar->pextra_width,
2013 p2 = npar->pextra_widthp;
2014 npar->SetPExtraType(npar->pextra_type,
2015 p1.c_str(), p2.c_str());
2021 void LyXParagraph::SetLayout(LyXTextClass::LayoutList::size_type new_layout)
2024 * par = FirstPhysicalPar(),
2028 par->layout = new_layout;
2029 par->labelwidthstring.clear();
2030 par->align = LYX_ALIGN_LAYOUT;
2031 par->added_space_top = VSpace(VSpace::NONE);
2032 par->added_space_bottom = VSpace(VSpace::NONE);
2033 /* table stuff -- begin*/
2036 /* table stuff -- end*/
2037 if (par->pextra_type == PEXTRA_NONE) {
2038 if (par->Previous()) {
2039 ppar = par->Previous()->FirstPhysicalPar();
2042 && (ppar->depth > par->depth))
2043 ppar = ppar->Previous()->FirstPhysicalPar();
2046 npar = par->Next()->NextAfterFootnote();
2049 && (npar->depth > par->depth))
2050 npar = npar->Next()->NextAfterFootnote();
2052 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
2054 p1 = ppar->pextra_width,
2055 p2 = ppar->pextra_widthp;
2056 ppar->SetPExtraType(ppar->pextra_type,
2057 p1.c_str(), p2.c_str());
2059 if ((par->pextra_type == PEXTRA_NONE) &&
2060 npar && (npar->pextra_type != PEXTRA_NONE)) {
2062 p1 = npar->pextra_width,
2063 p2 = npar->pextra_widthp;
2064 npar->SetPExtraType(npar->pextra_type,
2065 p1.c_str(), p2.c_str());
2071 // if the layout of a paragraph contains a manual label, the beginning of the
2072 // main body is the beginning of the second word. This is what the par-
2073 // function returns. If the layout does not contain a label, the main
2074 // body always starts with position 0. This differentiation is necessary,
2075 // because there cannot be a newline or a blank <= the beginning of the
2076 // main body in TeX.
2078 int LyXParagraph::BeginningOfMainBody() const
2080 if (FirstPhysicalPar() != this)
2083 // Unroll the first two cycles of the loop
2084 // and remember the previous character to
2085 // remove unnecessary GetChar() calls
2088 && GetChar(i) != LyXParagraph::META_NEWLINE) {
2090 char previous_char, temp;
2092 && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
2093 // Yes, this ^ is supposed to be "= " not "=="
2096 && previous_char != ' '
2097 && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
2099 previous_char = temp;
2104 if (i == 0 && i == size() &&
2105 !(footnoteflag == LyXParagraph::NO_FOOTNOTE
2106 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
2107 ++i; /* the cursor should not jump
2108 * to the main body if there
2114 LyXParagraph * LyXParagraph::DepthHook(int deth)
2116 LyXParagraph * newpar = this;
2121 newpar = newpar->FirstPhysicalPar()->Previous();
2122 } while (newpar && newpar->GetDepth() > deth
2123 && newpar->footnoteflag == footnoteflag);
2126 if (Previous() || GetDepth())
2127 lyxerr << "ERROR (LyXParagraph::DepthHook): "
2131 return newpar->FirstPhysicalPar();
2135 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
2137 LyXParagraph const * newpar = this;
2142 newpar = newpar->FirstPhysicalPar()->Previous();
2143 } while (newpar && newpar->GetDepth() > deth
2144 && newpar->footnoteflag == footnoteflag);
2147 if (Previous() || GetDepth())
2148 lyxerr << "ERROR (LyXParagraph::DepthHook): "
2152 return newpar->FirstPhysicalPar();
2156 int LyXParagraph::AutoDeleteInsets()
2158 #ifdef NEW_INSETTABLE
2159 vector<size_type> tmpvec;
2161 for (InsetList::iterator it = insetlist.begin();
2162 it != insetlist.end(); ++it) {
2163 if ((*it).inset && (*it).inset->AutoDelete()) {
2164 tmpvec.push_back((*it).pos);
2168 for (vector<size_type>::const_iterator cit = tmpvec.begin();
2169 cit != tmpvec.end(); ++cit) {
2174 InsetTable * tmpi = insettable;
2175 InsetTable * tmpi2 = tmpi;
2181 if (tmpi2->inset->AutoDelete()) {
2186 lyxerr << "ERROR (LyXParagraph::AutoDeleteInsets): "
2187 "cannot auto-delete insets" << endl;
2195 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
2197 #ifdef NEW_INSETTABLE
2198 InsetList::iterator it2 = insetlist.end();
2199 for (InsetList::iterator it = insetlist.begin();
2200 it != insetlist.end(); ++it) {
2201 if ((*it).pos >= pos) {
2202 if (it2 == insetlist.end() || (*it).pos < (*it2).pos)
2206 if (it2 != insetlist.end()) {
2208 return (*it2).inset;
2212 InsetTable * tmpi = insettable;
2213 InsetTable * tmpi2 = 0;
2215 if (tmpi->pos >= pos) {
2216 if (!tmpi2 || tmpi->pos < tmpi2->pos)
2223 return tmpi2->inset;
2231 // returns -1 if inset not found
2232 int LyXParagraph::GetPositionOfInset(Inset * inset) const
2235 #ifdef NEW_INSETTABLE
2236 for (InsetList::const_iterator cit = insetlist.begin();
2237 cit != insetlist.end(); ++cit) {
2238 if ((*cit).inset == inset) {
2243 InsetTable * tmpi = insettable;
2244 while (tmpi && tmpi->inset != inset) {
2247 if (tmpi && tmpi->inset)
2250 // Think about footnotes.
2251 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
2252 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2254 NextAfterFootnote()->GetPositionOfInset(inset);
2256 return text.size() + 1 + further;
2262 void LyXParagraph::readSimpleWholeFile(istream & is)
2268 InsertChar(text.size(), c);
2273 LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow,
2274 string & foot, TexRow & foot_texrow,
2277 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
2278 LyXParagraph * par = next;
2279 LyXLayout const & style =
2280 textclasslist.Style(current_view->buffer()->params.textclass,
2283 bool further_blank_line = false;
2285 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
2287 if (start_of_appendix) {
2288 file += "\\appendix\n";
2292 if (tex_code_break_column && style.isCommand()){
2297 if (pagebreak_top) {
2298 file += "\\newpage";
2299 further_blank_line = true;
2301 if (added_space_top.kind() != VSpace::NONE) {
2302 file += added_space_top.asLatexCommand();
2303 further_blank_line = true;
2307 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
2308 file += "\\vspace{-1\\parskip}";
2309 further_blank_line = true;
2312 if (further_blank_line){
2317 switch (style.latextype) {
2320 file += style.latexname();
2321 file += style.latexparam();
2323 case LATEX_ITEM_ENVIRONMENT:
2325 bibkey->Latex(file, false);
2329 case LATEX_LIST_ENVIRONMENT:
2336 bool need_par = SimpleTeXOnePar(file, texrow);
2338 // Spit out footnotes
2339 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2340 && par->footnoteflag != footnoteflag) {
2341 par = par->TeXFootnote(file, texrow,
2342 foot, foot_texrow, foot_count);
2343 par->SimpleTeXOnePar(file, texrow);
2347 // Make sure that \\par is done with the font of the last
2348 // character if this has another size as the default.
2349 // This is necessary because LaTeX (and LyX on the screen)
2350 // calculates the space between the baselines according
2351 // to this font. (Matthias)
2352 LyXFont font = getFont(Last()-1);
2354 if (style.resfont.size() != font.size()) {
2356 file += font.latexSize();
2360 } else if (textclasslist.Style(current_view->buffer()->params.textclass,
2361 GetLayout()).isCommand()){
2362 if (style.resfont.size() != font.size()) {
2364 file += font.latexSize();
2368 } else if (style.resfont.size() != font.size()){
2369 file += "{\\" + font.latexSize() + " \\par}";
2372 switch (style.latextype) {
2373 case LATEX_ITEM_ENVIRONMENT:
2374 case LATEX_LIST_ENVIRONMENT:
2375 if (par && (depth < par->depth)) {
2380 case LATEX_ENVIRONMENT:
2381 // if its the last paragraph of the current environment
2382 // skip it otherwise fall through
2384 && (par->layout != layout
2385 || par->depth != depth
2386 || par->pextra_type != pextra_type))
2389 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2390 && footnotekind != LyXParagraph::FOOTNOTE
2391 && footnotekind != LyXParagraph::MARGIN
2395 // don't insert this if we would be adding it
2396 // before or after a table in a float. This
2397 // little trick is needed in order to allow
2398 // use of tables in \subfigures or \subtables.
2404 further_blank_line = false;
2406 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2407 further_blank_line = true;
2410 if (added_space_bottom.kind() != VSpace::NONE) {
2411 file += added_space_bottom.asLatexCommand();
2412 further_blank_line = true;
2415 if (pagebreak_bottom) {
2416 file += "\\newpage";
2417 further_blank_line = true;
2420 if (further_blank_line){
2425 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2426 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2431 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2436 // This one spits out the text of the paragraph
2437 bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow)
2439 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2442 return SimpleTeXOneTablePar(file, texrow);
2445 size_type main_body;
2447 bool return_value = false;
2449 LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass, GetLayout());
2452 // Maybe we have to create a optional argument.
2453 if (style.labeltype != LABEL_MANUAL)
2456 main_body = BeginningOfMainBody();
2458 if (main_body > 0) {
2460 basefont = getFont(-2); // Get label font
2462 basefont = getFont(-1); // Get layout font
2470 if (style.isCommand()) {
2473 } else if (align != LYX_ALIGN_LAYOUT) {
2476 return_value = true;
2480 // Which font is currently active?
2481 LyXFont running_font = basefont;
2482 // Do we have an open font change?
2483 bool open_font = false;
2485 texrow.start(this, 0);
2487 for (size_type i = 0; i < size(); ++i) {
2489 // First char in paragraph or after label?
2490 if (i == main_body && !IsDummy()) {
2491 if (main_body > 0) {
2493 column += running_font.latexWriteEndChanges(file, basefont);
2496 basefont = getFont(-1); // Now use the layout font
2497 running_font = basefont;
2501 if (style.isCommand()) {
2504 } else if (align != LYX_ALIGN_LAYOUT) {
2507 return_value = true;
2511 file += "\\noindent ";
2515 case LYX_ALIGN_NONE:
2516 case LYX_ALIGN_BLOCK:
2517 case LYX_ALIGN_LAYOUT:
2518 case LYX_ALIGN_SPECIAL: break;
2519 case LYX_ALIGN_LEFT:
2520 file += "\\raggedright ";
2523 case LYX_ALIGN_RIGHT:
2524 file += "\\raggedleft ";
2527 case LYX_ALIGN_CENTER:
2528 file += "\\centering ";
2536 // Fully instantiated font
2537 LyXFont font = getFont(i);
2539 // Spaces at end of font change are simulated to be
2540 // outside font change, i.e. we write "\textXX{text} "
2541 // rather than "\textXX{text }". (Asger)
2542 if (open_font && c == ' ' && i <= size() - 2
2543 && !getFont(i+1).equalExceptLatex(running_font)
2544 && !getFont(i+1).equalExceptLatex(font)) {
2545 font = getFont(i + 1);
2547 // We end font definition before blanks
2548 if (!font.equalExceptLatex(running_font) && open_font) {
2549 column += running_font.latexWriteEndChanges(file,
2551 running_font = basefont;
2555 // Blanks are printed before start of fontswitch
2557 // Do not print the separation of the optional argument
2558 if (i != main_body - 1) {
2559 SimpleTeXBlanks(file, texrow, i,
2560 column, font, style);
2564 // Do we need to change font?
2565 if (!font.equalExceptLatex(running_font)
2566 && i != main_body-1) {
2567 column += font.latexWriteStartChanges(file, basefont);
2568 running_font = font;
2572 if (c == LyXParagraph::META_NEWLINE) {
2573 // newlines are handled differently here than
2574 // the default in SimpleTeXSpecialChars().
2575 if (!style.newline_allowed
2576 || font.latex() == LyXFont::ON) {
2580 column += running_font.latexWriteEndChanges(file, basefont);
2583 basefont = getFont(-1);
2584 running_font = basefont;
2585 if (font.family() ==
2586 LyXFont::TYPEWRITER_FAMILY) {
2592 texrow.start(this, i + 1);
2595 SimpleTeXSpecialChars(file, texrow,
2596 font, running_font, basefont,
2597 open_font, style, i, column, c);
2601 // If we have an open font definition, we have to close it
2603 running_font.latexWriteEndChanges(file, basefont);
2606 // Needed if there is an optional argument but no contents.
2607 if (main_body > 0 && main_body == size()) {
2609 return_value = false;
2612 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2613 return return_value;
2617 // This one spits out the text of a table paragraph
2618 bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow)
2620 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2622 bool return_value = false;
2624 LyXLayout const & style =
2625 textclasslist.Style(current_view->buffer()->params.textclass,
2629 if (!IsDummy()) { // it is dummy if it is in a float!!!
2630 if (style.isCommand()) {
2633 } else if (align != LYX_ALIGN_LAYOUT) {
2636 return_value = true;
2639 file += "\\noindent ";
2643 case LYX_ALIGN_NONE:
2644 case LYX_ALIGN_BLOCK:
2645 case LYX_ALIGN_LAYOUT:
2646 case LYX_ALIGN_SPECIAL: break;
2647 case LYX_ALIGN_LEFT:
2648 file += "\\raggedright ";
2651 case LYX_ALIGN_RIGHT:
2652 file += "\\raggedleft ";
2655 case LYX_ALIGN_CENTER:
2656 file += "\\centering ";
2662 LyXFont basefont = getFont(-1); // Get layout font
2663 // Which font is currently active?
2664 LyXFont running_font = basefont;
2665 // Do we have an open font change?
2666 bool open_font = false;
2667 int current_cell_number = -1;
2668 int tmp = table->TexEndOfCell(file, current_cell_number);
2669 for (; tmp > 0 ; --tmp)
2672 texrow.start(this, 0);
2674 for (size_type i = 0; i < size(); ++i) {
2675 char c = GetChar(i);
2676 if (table->IsContRow(current_cell_number + 1)) {
2677 if (c == LyXParagraph::META_NEWLINE)
2678 ++current_cell_number;
2683 // Fully instantiated font
2684 LyXFont font = getFont(i);
2686 // Spaces at end of font change are simulated to be
2687 // outside font change.
2688 // i.e. we write "\textXX{text} " rather than
2689 // "\textXX{text }". (Asger)
2690 if (open_font && c == ' ' && i <= size() - 2
2691 && getFont(i+1) != running_font && getFont(i+1) != font) {
2692 font = getFont(i+1);
2695 // We end font definition before blanks
2696 if (font != running_font && open_font) {
2697 column += running_font.latexWriteEndChanges(file,
2699 running_font = basefont;
2702 // Blanks are printed before start of fontswitch
2704 SimpleTeXBlanks(file, texrow, i, column, font, style);
2706 // Do we need to change font?
2707 if (font != running_font) {
2708 column += font.latexWriteStartChanges(file, basefont);
2709 running_font = font;
2712 // Do we need to turn on LaTeX mode?
2713 if (font.latex() != running_font.latex()) {
2714 if (font.latex() == LyXFont::ON
2715 && style.needprotect) {
2716 file += "\\protect ";
2720 if (c == LyXParagraph::META_NEWLINE) {
2721 // special case for inside a table
2722 // different from default case in
2723 // SimpleTeXSpecialChars()
2725 column += running_font
2726 .latexWriteEndChanges(file, basefont);
2729 basefont = getFont(-1);
2730 running_font = basefont;
2731 ++current_cell_number;
2732 if (table->CellHasContRow(current_cell_number) >= 0) {
2733 TeXContTableRows(file, i + 1,
2734 current_cell_number,
2737 // if this cell follow only ContRows till end don't
2738 // put the EndOfCell because it is put after the
2740 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2741 --current_cell_number;
2744 int tmp = table->TexEndOfCell(file,
2745 current_cell_number);
2748 } else if (tmp < 0) {
2754 texrow.start(this, i + 1);
2756 SimpleTeXSpecialChars(file, texrow,
2757 font, running_font, basefont,
2758 open_font, style, i, column, c);
2762 // If we have an open font definition, we have to close it
2764 running_font.latexWriteEndChanges(file, basefont);
2766 ++current_cell_number;
2767 tmp = table->TexEndOfCell(file, current_cell_number);
2768 for (; tmp > 0; --tmp)
2770 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2771 return return_value;
2775 // This one spits out the text off ContRows in tables
2776 bool LyXParagraph::TeXContTableRows(string & file,
2777 LyXParagraph::size_type i,
2778 int current_cell_number,
2779 int & column, TexRow & texrow)
2781 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2787 bool return_value = false;
2788 LyXLayout const & style =
2789 textclasslist.Style(current_view->buffer()->params.textclass,
2791 LyXFont basefont = getFont(-1); // Get layout font
2792 // Which font is currently active?
2793 LyXFont running_font = basefont;
2794 // Do we have an open font change?
2795 bool open_font = false;
2797 size_type lastpos = i;
2798 int cell = table->CellHasContRow(current_cell_number);
2799 ++current_cell_number;
2801 // first find the right position
2803 for (; (i < size()) && (current_cell_number<cell); ++i) {
2805 if (c == LyXParagraph::META_NEWLINE)
2806 ++current_cell_number;
2810 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2814 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2819 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2823 // Fully instantiated font
2824 LyXFont font = getFont(i);
2826 // Spaces at end of font change are simulated to
2827 // be outside font change. i.e. we write
2828 // "\textXX{text} " rather than "\textXX{text }".
2830 if (open_font && c == ' ' && i <= size() - 2
2831 && getFont(i + 1) != running_font
2832 && getFont(i + 1) != font) {
2833 font = getFont(i + 1);
2836 // We end font definition before blanks
2837 if (font != running_font && open_font) {
2838 column += running_font.latexWriteEndChanges(file, basefont);
2839 running_font = basefont;
2842 // Blanks are printed before start of fontswitch
2844 SimpleTeXBlanks(file, texrow, i,
2845 column, font, style);
2847 // Do we need to change font?
2848 if (font != running_font) {
2850 font.latexWriteStartChanges(file,
2852 running_font = font;
2855 // Do we need to turn on LaTeX mode?
2856 if (font.latex() != running_font.latex()) {
2857 if (font.latex() == LyXFont::ON
2858 && style.needprotect)
2860 file += "\\protect ";
2864 SimpleTeXSpecialChars(file, texrow, font,
2865 running_font, basefont,
2866 open_font, style, i, column, c);
2868 // If we have an open font definition, we have to close it
2870 running_font.latexWriteEndChanges(file, basefont);
2873 basefont = getFont(-1);
2874 running_font = basefont;
2875 cell = table->CellHasContRow(current_cell_number);
2877 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2878 return return_value;
2882 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2884 bool retval = false;
2886 case LyXParagraph::META_HFILL:
2887 sgml_string.clear();
2889 case LyXParagraph::META_PROTECTED_SEPARATOR:
2892 case LyXParagraph::META_NEWLINE:
2896 sgml_string = "&";
2899 sgml_string = "<";
2902 sgml_string = ">";
2905 sgml_string = "$";
2908 sgml_string = "#";
2911 sgml_string = "%";
2914 sgml_string = "[";
2917 sgml_string = "]";
2920 sgml_string = "{";
2923 sgml_string = "}";
2926 sgml_string = "˜";
2929 sgml_string = """;
2932 sgml_string = "\";
2938 case '\0': // Ignore :-)
2939 sgml_string.clear();
2949 void LyXParagraph::SimpleDocBookOneTablePar(string & file, string & extra,
2950 int & desc_on, int depth)
2953 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2955 LyXFont font1, font2;
2958 size_type main_body;
2959 string emph = "emphasis";
2960 bool emph_flag = false;
2962 LyXLayout const & style =
2963 textclasslist.Style(current_view->buffer()->params.textclass,
2966 if (style.labeltype != LABEL_MANUAL)
2969 main_body = BeginningOfMainBody();
2971 // Gets paragraph main font.
2973 font1 = style.labelfont;
2977 int char_line_count = depth;
2978 addNewlineAndDepth(file, depth);
2979 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2980 file += "<INFORMALTABLE>";
2981 addNewlineAndDepth(file, ++depth);
2983 int current_cell_number = -1;
2984 int tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
2986 // Parsing main loop.
2987 for (size_type i = 0; i < size(); ++i) {
2989 if (table->IsContRow(current_cell_number+1)) {
2990 if (c == LyXParagraph::META_NEWLINE)
2991 ++current_cell_number;
2996 // Fully instantiated font
2999 // Handle <emphasis> tag.
3000 if (font1.emph() != font2.emph() && i) {
3001 if (font2.emph() == LyXFont::ON) {
3002 file += "<emphasis>";
3004 } else if (emph_flag) {
3005 file += "</emphasis>";
3009 if (c == LyXParagraph::META_NEWLINE) {
3010 // We have only to control for emphasis open here!
3012 file += "</emphasis>";
3015 font1 = font2 = getFont(-1);
3016 ++current_cell_number;
3017 if (table->CellHasContRow(current_cell_number) >= 0) {
3018 DocBookContTableRows(file, extra, desc_on, i+1,
3019 current_cell_number,
3022 // if this cell follow only ContRows till end don't
3023 // put the EndOfCell because it is put after the
3025 if (table->ShouldBeVeryLastCell(current_cell_number)) {
3026 --current_cell_number;
3029 tmp = table->DocBookEndOfCell(file,
3030 current_cell_number,
3035 } else if (c == LyXParagraph::META_INSET) {
3036 inset = GetInset(i);
3038 inset->DocBook(tmp_out);
3040 // This code needs some explanation:
3041 // Two insets are treated specially
3042 // label if it is the first element in a
3043 // command paragraph
3045 // graphics inside tables or figure floats
3047 // title (the equivalente in latex for this
3049 // and title should come first
3052 if(desc_on != 3 || i != 0) {
3053 if(tmp_out[0] == '@') {
3055 extra += frontStrip(tmp_out,
3058 file += frontStrip(tmp_out,
3063 } else if (font2.latex() == LyXFont::ON) {
3064 // "TeX"-Mode on == > SGML-Mode on.
3070 if (linuxDocConvertChar(c, sgml_string)
3071 && !style.free_spacing) {
3072 // in freespacing mode, spaces are
3073 // non-breaking characters
3078 file += "</term><listitem><para>";
3084 file += sgml_string;
3090 // Needed if there is an optional argument but no contents.
3091 if (main_body > 0 && main_body == size()) {
3096 file += "</emphasis>";
3099 ++current_cell_number;
3100 tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
3101 // Resets description flag correctly.
3104 // <term> not closed...
3108 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3109 file += "</INFORMALTABLE>";
3111 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
3116 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
3118 LyXParagraph::size_type i,
3119 int current_cell_number, int &column)
3124 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
3129 string emph= "emphasis";
3130 bool emph_flag= false;
3131 int char_line_count= 0;
3133 LyXLayout const & style =
3134 textclasslist.Style(current_view->buffer()->params.textclass,
3137 size_type main_body;
3138 if (style.labeltype != LABEL_MANUAL)
3141 main_body = BeginningOfMainBody();
3143 // Gets paragraph main font.
3146 font1 = style.labelfont;
3150 size_type lastpos = i;
3151 int cell = table->CellHasContRow(current_cell_number);
3152 ++current_cell_number;
3154 // first find the right position
3156 for (; i < size() && current_cell_number < cell; ++i) {
3158 if (c == LyXParagraph::META_NEWLINE)
3159 ++current_cell_number;
3163 // I don't know how to handle this so I comment it
3164 // for the moment (Jug)
3165 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3166 // file += " \\\\\n";
3169 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
3174 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3178 // Fully instantiated font
3181 // Handle <emphasis> tag.
3182 if (font1.emph() != font2.emph() && i) {
3183 if (font2.emph() == LyXFont::ON) {
3184 file += "<emphasis>";
3186 } else if (emph_flag) {
3187 file += "</emphasis>";
3191 if (c == LyXParagraph::META_INSET) {
3192 inset = GetInset(i);
3194 inset->DocBook(tmp_out);
3196 // This code needs some explanation:
3197 // Two insets are treated specially
3198 // label if it is the first element in a
3199 // command paragraph
3201 // graphics inside tables or figure floats
3202 // can't go on title (the equivalente in
3203 // latex for this case is caption and title
3204 // should come first
3207 if(desc_on != 3 || i != 0) {
3208 if(tmp_out[0] == '@') {
3210 extra += frontStrip(tmp_out, '@');
3212 file += frontStrip(tmp_out, '@');
3216 } else if (font2.latex() == LyXFont::ON) {
3217 // "TeX"-Mode on == > SGML-Mode on.
3223 if (linuxDocConvertChar(c, sgml_string)
3224 && !style.free_spacing) {
3225 // in freespacing mode, spaces are
3226 // non-breaking characters
3231 file += "</term><listitem><para>";
3237 file += sgml_string;
3241 // we have only to control for emphasis open here!
3243 file += "</emphasis>";
3246 font1 = font2 = getFont(-1);
3247 cell = table->CellHasContRow(current_cell_number);
3249 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3253 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
3254 LyXParagraph::size_type const i,
3255 int & column, LyXFont const & font,
3256 LyXLayout const & style)
3258 if (column > tex_code_break_column
3260 && GetChar(i - 1) != ' '
3262 // In LaTeX mode, we don't want to
3263 // break lines since some commands
3265 && ! (font.latex() == LyXFont::ON)
3266 // same in FreeSpacing mode
3267 && !style.free_spacing
3268 // In typewriter mode, we want to avoid
3269 // ! . ? : at the end of a line
3270 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3271 && (GetChar(i-1) == '.'
3272 || GetChar(i-1) == '?'
3273 || GetChar(i-1) == ':'
3274 || GetChar(i-1) == '!'))) {
3275 if (tex_code_break_column == 0) {
3276 // in batchmode we need LaTeX to still
3277 // see it as a space not as an extra '\n'
3283 texrow.start(this, i+1);
3285 } else if (font.latex() == LyXFont::OFF) {
3286 if (style.free_spacing) {
3295 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
3297 LyXFont & running_font,
3300 LyXLayout const & style,
3301 LyXParagraph::size_type & i,
3302 int & column, char const c)
3304 // Two major modes: LaTeX or plain
3305 // Handle here those cases common to both modes
3306 // and then split to handle the two modes separately.
3308 case LyXParagraph::META_INSET: {
3309 Inset * inset = GetInset(i);
3311 int len = file.length();
3312 int tmp = inset->Latex(file, style.isCommand());
3317 column += file.length() - len;
3326 case LyXParagraph::META_NEWLINE:
3328 column += running_font.latexWriteEndChanges(file,
3332 basefont = getFont(-1);
3333 running_font = basefont;
3336 case LyXParagraph::META_HFILL:
3337 file += "\\hfill{}";
3342 // And now for the special cases within each mode
3343 // Are we in LaTeX mode?
3344 if (font.latex() == LyXFont::ON) {
3345 // at present we only have one option
3346 // but I'll leave it as a switch statement
3347 // so its simpler to extend. (ARRae)
3349 case LyXParagraph::META_PROTECTED_SEPARATOR:
3354 // make sure that we will not print
3355 // error generating chars to the tex
3356 // file. This test would not be needed
3357 // if it were done in the buffer
3365 // Plain mode (i.e. not LaTeX)
3367 case LyXParagraph::META_PROTECTED_SEPARATOR:
3372 file += "\\textbackslash{}";
3376 case '°': case '±': case '²': case '³':
3377 case '×': case '÷': case '¹': case 'ª':
3378 case 'º': case '¬': case 'µ':
3379 if (current_view->buffer()->params.inputenc == "latin1") {
3380 file += "\\ensuremath{";
3389 case '|': case '<': case '>':
3390 // In T1 encoding, these characters exist
3391 if (lyxrc->fontenc == "T1") {
3393 //... but we should avoid ligatures
3394 if ((c == '>' || c == '<')
3396 && GetChar(i+1) == c){
3397 file += "\\textcompwordmark{}";
3402 // Typewriter font also has them
3403 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3407 // Otherwise, we use what LaTeX
3411 file += "\\textless{}";
3415 file += "\\textgreater{}";
3419 file += "\\textbar{}";
3425 case '-': // "--" in Typewriter mode -> "-{}-"
3427 && GetChar(i + 1) == '-'
3428 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3437 file += "\\char`\\\"{}";
3442 if (current_view->buffer()->params.inputenc == "default") {
3443 file += "\\pounds{}";
3451 case '%': case '#': case '{':
3459 file += "\\textasciitilde{}";
3464 file += "\\textasciicircum{}";
3468 case '*': case '[': case ']':
3469 // avoid being mistaken for optional arguments
3477 // Blanks are printed before font switching.
3478 // Sure? I am not! (try nice-latex)
3479 // I am sure it's correct. LyX might be smarter
3480 // in the future, but for now, nothing wrong is
3485 /* idea for labels --- begin*/
3489 && font.family() != LyXFont::TYPEWRITER_FAMILY
3490 && GetChar(i + 1) == 'y'
3491 && GetChar(i + 2) == 'X') {
3499 && font.family() != LyXFont::TYPEWRITER_FAMILY
3500 && GetChar(i + 1) == 'e'
3501 && GetChar(i + 2) == 'X') {
3506 // Check for "LaTeX2e"
3509 && font.family() != LyXFont::TYPEWRITER_FAMILY
3510 && GetChar(i + 1) == 'a'
3511 && GetChar(i + 2) == 'T'
3512 && GetChar(i + 3) == 'e'
3513 && GetChar(i + 4) == 'X'
3514 && GetChar(i + 5) == '2'
3515 && GetChar(i + 6) == 'e') {
3516 file += "\\LaTeXe{}";
3520 // Check for "LaTeX"
3523 && font.family() != LyXFont::TYPEWRITER_FAMILY
3524 && GetChar(i + 1) == 'a'
3525 && GetChar(i + 2) == 'T'
3526 && GetChar(i + 3) == 'e'
3527 && GetChar(i + 4) == 'X') {
3528 file += "\\LaTeX{}";
3531 /* idea for labels --- end*/
3532 } else if (c != '\0') {
3542 bool LyXParagraph::RoffContTableRows(ostream & os,
3543 LyXParagraph::size_type i,
3549 LyXFont font1 = LyXFont(LyXFont::ALL_INHERIT);
3554 string fname2 = TmpFileName(string(), "RAT2");
3556 int cell = table->CellHasContRow(actcell);
3559 // first find the right position
3561 for (; i < size() && actcell < cell; ++i) {
3563 if (c == LyXParagraph::META_NEWLINE)
3568 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3571 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3573 font2 = GetFontSettings(i);
3574 if (font1.latex() != font2.latex()) {
3575 if (font2.latex() != LyXFont::OFF)
3580 case LyXParagraph::META_INSET:
3581 if ((inset = GetInset(i))) {
3582 fstream fs(fname2.c_str(),
3585 WriteAlert(_("LYX_ERROR:"),
3586 _("Cannot open temporary file:"),
3590 inset->Latex(fs, -1);
3603 case LyXParagraph::META_NEWLINE:
3605 case LyXParagraph::META_HFILL:
3607 case LyXParagraph::META_PROTECTED_SEPARATOR:
3616 lyxerr.debug() << "RoffAsciiTable: "
3617 "NULL char in structure."
3622 cell = table->CellHasContRow(actcell);
3628 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
3629 string & foot, TexRow & foot_texrow,
3632 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3633 LyXParagraph * par = this;
3635 while (par && par->depth == depth) {
3637 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3638 if (textclasslist.Style(current_view->buffer()->params.textclass,
3639 par->layout).isEnvironment()
3640 || par->pextra_type != PEXTRA_NONE)
3642 par = par->TeXEnvironment(file, texrow,
3646 par = par->TeXOnePar(file, texrow,
3651 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3657 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
3659 TexRow & foot_texrow,
3662 bool eindent_open = false;
3663 bool foot_this_level = false;
3664 // flags when footnotetext should be appended to file.
3665 static bool minipage_open = false;
3666 static int minipage_open_depth = 0;
3667 char par_sep = current_view->buffer()->params.paragraph_separation;
3669 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3671 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3673 LyXLayout const & style =
3674 textclasslist.Style(current_view->buffer()->params.textclass,
3677 if (pextra_type == PEXTRA_INDENT) {
3678 if (!pextra_width.empty()) {
3679 file += "\\begin{LyXParagraphIndent}{"
3680 + pextra_width + "}\n";
3682 //float ib = atof(pextra_widthp.c_str())/100;
3683 // string can't handle floats at present (971109)
3684 // so I'll do a conversion by hand knowing that
3685 // the limits are 0.0 to 1.0. ARRae.
3686 file += "\\begin{LyXParagraphIndent}{";
3687 switch (pextra_widthp.length()) {
3693 file += pextra_widthp;
3697 file += pextra_widthp;
3699 file += "\\columnwidth}\n";
3702 eindent_open = true;
3704 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3705 if (pextra_hfill && Previous() &&
3706 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3707 file += "\\hfill{}\n";
3710 if (par_sep == BufferParams::PARSEP_INDENT) {
3711 file += "{\\setlength\\parindent{0pt}\n";
3714 file += "\\begin{minipage}";
3715 switch(pextra_alignment) {
3716 case MINIPAGE_ALIGN_TOP:
3719 case MINIPAGE_ALIGN_MIDDLE:
3722 case MINIPAGE_ALIGN_BOTTOM:
3726 if (!pextra_width.empty()) {
3728 file += pextra_width + "}\n";
3730 //float ib = atof(par->pextra_width.c_str())/100;
3731 // string can't handle floats at present
3732 // so I'll do a conversion by hand knowing that
3733 // the limits are 0.0 to 1.0. ARRae.
3735 switch (pextra_widthp.length()) {
3741 file += pextra_widthp;
3745 file += pextra_widthp;
3747 file += "\\columnwidth}\n";
3750 if (par_sep == BufferParams::PARSEP_INDENT) {
3751 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3754 minipage_open = true;
3755 minipage_open_depth = depth;
3758 #ifdef WITH_WARNINGS
3759 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3760 //I disabled it because it breaks when lists span on several
3763 if (style.isEnvironment()){
3764 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3765 #ifdef FANCY_FOOTNOTE_CODE
3766 if (foot_count < 0) {
3767 // flag that footnote[mark][text] should be
3768 // used for any footnotes from now on
3770 foot_this_level = true;
3773 file += "\\begin{" + style.latexname() + "}{"
3774 + labelwidthstring + "}\n";
3775 } else if (style.labeltype == LABEL_BIBLIO) {
3777 file += "\\begin{" + style.latexname() + "}{"
3778 + bibitemWidthest() + "}\n";
3779 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3780 #ifdef FANCY_FOOTNOTE_CODE
3781 if (foot_count < 0) {
3782 // flag that footnote[mark][text] should be
3783 // used for any footnotes from now on
3785 foot_this_level = true;
3788 file += "\\begin{" + style.latexname() + '}'
3789 + style.latexparam() + '\n';
3791 file += "\\begin{" + style.latexname() + '}'
3792 + style.latexparam() + '\n';
3795 LyXParagraph * par = this;
3797 par = par->TeXOnePar(file, texrow,
3798 foot, foot_texrow, foot_count);
3800 if (minipage_open && par && !style.isEnvironment() &&
3801 (par->pextra_type == PEXTRA_MINIPAGE) &&
3802 par->pextra_start_minipage) {
3803 file += "\\end{minipage}\n";
3805 if (par_sep == BufferParams::PARSEP_INDENT) {
3809 minipage_open = false;
3811 if (par && par->depth > depth) {
3812 if (textclasslist.Style(current_view->buffer()->params.textclass,
3813 par->layout).isParagraph()
3815 && !suffixIs(file, "\n\n")) {
3816 // There should be at least one '\n' already
3817 // but we need there to be two for Standard
3818 // paragraphs that are depth-increment'ed to be
3819 // output correctly. However, tables can
3820 // also be paragraphs so don't adjust them.
3825 par = par->TeXDeeper(file, texrow,
3826 foot, foot_texrow, foot_count);
3828 if (par && par->layout == layout && par->depth == depth &&
3829 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3830 if (par->pextra_hfill && par->Previous() &&
3831 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3832 file += "\\hfill{}\n";
3835 if (par_sep == BufferParams::PARSEP_INDENT) {
3836 file += "{\\setlength\\parindent{0pt}\n";
3839 file += "\\begin{minipage}";
3840 switch(par->pextra_alignment) {
3841 case MINIPAGE_ALIGN_TOP:
3844 case MINIPAGE_ALIGN_MIDDLE:
3847 case MINIPAGE_ALIGN_BOTTOM:
3851 if (!par->pextra_width.empty()) {
3853 file += par->pextra_width;
3856 //float ib = atof(par->pextra_widthp.c_str())/100;
3857 // string can't handle floats at present
3858 // so I'll do a conversion by hand knowing that
3859 // the limits are 0.0 to 1.0. ARRae.
3861 switch (par->pextra_widthp.length()) {
3867 file += par->pextra_widthp;
3871 file += par->pextra_widthp;
3873 file += "\\columnwidth}\n";
3876 if (par_sep == BufferParams::PARSEP_INDENT) {
3877 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3880 minipage_open = true;
3881 minipage_open_depth = par->depth;
3884 && par->layout == layout
3885 && par->depth == depth
3886 && par->pextra_type == pextra_type);
3888 if (style.isEnvironment()) {
3889 file += "\\end{" + style.latexname() + '}';
3890 // maybe this should go after the minipage closes?
3891 if (foot_this_level) {
3892 if (foot_count >= 1) {
3893 if (foot_count > 1) {
3894 file += "\\addtocounter{footnote}{-";
3895 file += tostr(foot_count - 1);
3899 texrow += foot_texrow;
3901 foot_texrow.reset();
3906 if (minipage_open && (minipage_open_depth == depth) &&
3907 (!par || par->pextra_start_minipage ||
3908 par->pextra_type != PEXTRA_MINIPAGE)) {
3909 file += "\\end{minipage}\n";
3911 if (par_sep == BufferParams::PARSEP_INDENT) {
3915 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3916 file += "\\medskip\n\n";
3920 minipage_open = false;
3923 file += "\\end{LyXParagraphIndent}\n";
3926 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
3927 && par->pextra_hfill)) {
3931 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3932 return par; // ale970302
3936 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
3937 string & foot, TexRow & foot_texrow,
3940 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3941 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3942 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3943 "No footnote!" << endl;
3945 LyXParagraph * par = this;
3946 LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass,
3947 previous->GetLayout());
3949 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3950 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3951 "Float other than footnote in command"
3952 " with moving argument is illegal" << endl;
3955 if (footnotekind != LyXParagraph::FOOTNOTE
3956 && footnotekind != LyXParagraph::MARGIN
3958 && !suffixIs(file, '\n')) {
3959 // we need to ensure that real floats like tables and figures
3960 // have their \begin{} on a new line otherwise we can get
3961 // incorrect results when using the endfloat.sty package
3962 // especially if two floats follow one another. ARRae 981022
3963 // NOTE: if the file is length 0 it must have just been
3964 // written out so we assume it ended with a '\n'
3969 BufferParams * params = ¤t_view->buffer()->params;
3970 bool footer_in_body = true;
3971 switch (footnotekind) {
3972 case LyXParagraph::FOOTNOTE:
3973 if (style.intitle) {
3974 file += "\\thanks{\n";
3975 footer_in_body = false;
3977 if (foot_count == -1) {
3978 // we're at depth 0 so we can use:
3979 file += "\\footnote{%\n";
3980 footer_in_body = false;
3982 file += "\\footnotemark{}%\n";
3984 // we only need this when there are
3985 // multiple footnotes
3986 foot += "\\stepcounter{footnote}";
3988 foot += "\\footnotetext{%\n";
3989 foot_texrow.start(this, 0);
3990 foot_texrow.newline();
3995 case LyXParagraph::MARGIN:
3996 file += "\\marginpar{\n";
3998 case LyXParagraph::FIG:
3999 if (pextra_type == PEXTRA_FLOATFLT
4000 && (!pextra_width.empty()
4001 || !pextra_widthp.empty())) {
4003 if (!pextra_width.empty())
4004 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
4005 pextra_width.c_str());
4008 "\\begin{floatingfigure}{%f\\textwidth}\n",
4009 atoi(pextra_widthp.c_str())/100.0);
4012 file += "\\begin{figure}";
4013 if (!params->float_placement.empty()) {
4015 file += params->float_placement;
4022 case LyXParagraph::TAB:
4023 file += "\\begin{table}";
4024 if (!params->float_placement.empty()) {
4026 file += params->float_placement;
4032 case LyXParagraph::WIDE_FIG:
4033 file += "\\begin{figure*}";
4034 if (!params->float_placement.empty()) {
4036 file += params->float_placement;
4042 case LyXParagraph::WIDE_TAB:
4043 file += "\\begin{table*}";
4044 if (!params->float_placement.empty()) {
4046 file += params->float_placement;
4052 case LyXParagraph::ALGORITHM:
4053 file += "\\begin{algorithm}\n";
4058 if (footnotekind != LyXParagraph::FOOTNOTE
4059 || !footer_in_body) {
4060 // Process text for all floats except footnotes in body
4062 LyXLayout const & style =
4063 textclasslist.Style(current_view->buffer()->params.textclass,
4066 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4068 if (style.isEnvironment()
4069 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4070 // Allows the use of minipages within float
4071 // environments. Shouldn't be circular because
4072 // we don't support footnotes inside
4073 // floats (yet). ARRae
4074 par = par->TeXEnvironment(file, texrow,
4078 par = par->TeXOnePar(file, texrow,
4083 if (par && !par->IsDummy() && par->depth > depth) {
4084 par = par->TeXDeeper(file, texrow,
4088 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4090 // process footnotes > depth 0 or in environments separately
4091 // NOTE: Currently don't support footnotes within footnotes
4092 // even though that is possible using the \footnotemark
4094 TexRow dummy_texrow;
4095 int dummy_count = 0;
4097 LyXLayout const & style =
4098 textclasslist.Style(current_view->buffer()->params.textclass,
4101 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4103 if (style.isEnvironment()
4104 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4105 // Allows the use of minipages within float
4106 // environments. Shouldn't be circular because
4107 // we don't support footnotes inside
4108 // floats (yet). ARRae
4109 par = par->TeXEnvironment(foot, foot_texrow,
4110 dummy, dummy_texrow,
4113 par = par->TeXOnePar(foot, foot_texrow,
4114 dummy, dummy_texrow,
4118 if (par && !par->IsDummy() && par->depth > depth) {
4119 par = par->TeXDeeper(foot, foot_texrow,
4120 dummy, dummy_texrow,
4124 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4126 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4127 "Footnote in a Footnote -- not supported"
4132 switch (footnotekind) {
4133 case LyXParagraph::FOOTNOTE:
4134 if (footer_in_body) {
4135 // This helps tell which of the multiple
4136 // footnotetexts an error was in.
4138 foot_texrow.newline();
4143 case LyXParagraph::MARGIN:
4146 case LyXParagraph::FIG:
4147 if (pextra_type == PEXTRA_FLOATFLT
4148 && (!pextra_width.empty()
4149 || !pextra_widthp.empty()))
4150 file += "\\end{floatingfigure}";
4152 file += "\\end{figure}";
4154 case LyXParagraph::TAB:
4155 file += "\\end{table}";
4157 case LyXParagraph::WIDE_FIG:
4158 file += "\\end{figure*}";
4160 case LyXParagraph::WIDE_TAB:
4161 file += "\\end{table*}";
4163 case LyXParagraph::ALGORITHM:
4164 file += "\\end{algorithm}";
4168 if (footnotekind != LyXParagraph::FOOTNOTE
4169 && footnotekind != LyXParagraph::MARGIN) {
4170 // we need to ensure that real floats like tables and figures
4171 // have their \end{} on a line of their own otherwise we can
4172 // get incorrect results when using the endfloat.sty package.
4177 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4182 void LyXParagraph::SetPExtraType(int type, char const * width,
4183 char const * widthp)
4186 pextra_width = width;
4187 pextra_widthp = widthp;
4189 if (textclasslist.Style(current_view->buffer()->params.textclass,
4190 layout).isEnvironment()) {
4195 while (par && (par->layout == layout)
4196 && (par->depth == depth)) {
4198 par = par->Previous();
4200 par = par->FirstPhysicalPar();
4201 while (par && par->depth > depth) {
4202 par = par->Previous();
4204 par = par->FirstPhysicalPar();
4208 while (par && (par->layout == layout)
4209 && (par->depth == depth)) {
4210 par->pextra_type = type;
4211 par->pextra_width = width;
4212 par->pextra_widthp = widthp;
4213 par = par->NextAfterFootnote();
4214 if (par && (par->depth > depth))
4215 par->SetPExtraType(type, width, widthp);
4216 while (par && ((par->depth > depth) || par->IsDummy()))
4217 par = par->NextAfterFootnote();
4223 void LyXParagraph::UnsetPExtraType()
4225 if (pextra_type == PEXTRA_NONE)
4228 pextra_type = PEXTRA_NONE;
4229 pextra_width.clear();
4230 pextra_widthp.clear();
4232 if (textclasslist.Style(current_view->buffer()->params.textclass,
4233 layout).isEnvironment()) {
4238 while (par && (par->layout == layout)
4239 && (par->depth == depth)) {
4241 par = par->Previous();
4243 par = par->FirstPhysicalPar();
4244 while (par && par->depth > depth) {
4245 par = par->Previous();
4247 par = par->FirstPhysicalPar();
4251 while (par && (par->layout == layout)
4252 && (par->depth == depth)) {
4253 par->pextra_type = PEXTRA_NONE;
4254 par->pextra_width.clear();
4255 par->pextra_widthp.clear();
4256 par = par->NextAfterFootnote();
4257 if (par && (par->depth > depth))
4258 par->UnsetPExtraType();
4259 while (par && ((par->depth > depth) || par->IsDummy()))
4260 par = par->NextAfterFootnote();
4266 bool LyXParagraph::IsHfill(size_type pos) const
4268 return IsHfillChar(GetChar(pos));
4272 bool LyXParagraph::IsInset(size_type pos) const
4274 return IsInsetChar(GetChar(pos));
4278 bool LyXParagraph::IsFloat(size_type pos) const
4280 return IsFloatChar(GetChar(pos));
4284 bool LyXParagraph::IsNewline(size_type pos) const
4288 tmp = IsNewlineChar(GetChar(pos));
4293 bool LyXParagraph::IsSeparator(size_type pos) const
4295 return IsSeparatorChar(GetChar(pos));
4299 bool LyXParagraph::IsLineSeparator(size_type pos) const
4301 return IsLineSeparatorChar(GetChar(pos));
4305 bool LyXParagraph::IsKomma(size_type pos) const
4307 return IsKommaChar(GetChar(pos));
4311 /// Used by the spellchecker
4312 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4314 unsigned char c = GetChar(pos);
4315 if (IsLetterChar(c))
4317 // '\0' is not a letter, allthough every string contains "" (below)
4320 // We want to pass the ' and escape chars to ispell
4321 string extra = lyxrc->isp_esc_chars + '\'';
4325 return contains(extra, ch);
4329 bool LyXParagraph::IsWord(size_type pos ) const
4331 return IsWordChar(GetChar(pos)) ;