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;
77 align = LYX_ALIGN_BLOCK;
79 /* table stuff -- begin*/
81 /* table stuff -- end*/
83 bibkey = 0; // ale970302
88 // This konstruktor inserts the new paragraph in a list.
89 LyXParagraph::LyXParagraph(LyXParagraph * par)
92 par->text.resize(par->text.size());
94 for (int i = 0; i < 10; ++i) setCounter(i, 0);
98 // double linked list begin
101 next->previous = this;
103 previous->next = this;
105 #ifndef NEW_FONTTABLE // OK
108 #ifndef NEW_INSETTABLE
111 footnoteflag = LyXParagraph::NO_FOOTNOTE;
112 footnotekind = LyXParagraph::FOOTNOTE;
114 /* table stuff -- begin*/
116 /* table stuff -- end*/
117 id_ = paragraph_id++;
119 bibkey = 0; // ale970302
125 void LyXParagraph::writeFile(ostream & os, BufferParams & params,
126 char footflag, char dth)
128 LyXFont font1, font2;
134 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
136 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
138 // The beginning or the end of a footnote environment?
139 if (footflag != footnoteflag) {
140 footflag = footnoteflag;
142 os << "\n\\begin_float "
143 << 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 ";
160 while (depth < dth) {
161 os << "\n\\end_deeper ";
167 // First write the layout
169 << textclasslist.NameOfLayout(params.textclass, layout)
172 // Maybe some vertical spaces.
173 if (added_space_top.kind() != VSpace::NONE)
174 os << "\\added_space_top "
175 << added_space_top.asLyXCommand() << " ";
176 if (added_space_bottom.kind() != VSpace::NONE)
177 os << "\\added_space_bottom "
178 << added_space_bottom.asLyXCommand() << " ";
180 // The labelwidth string used in lists.
181 if (!labelwidthstring.empty())
182 os << "\\labelwidthstring "
183 << labelwidthstring << '\n';
185 // Lines above or below?
189 os << "\\line_bottom ";
191 // Pagebreaks above or below?
193 os << "\\pagebreak_top ";
194 if (pagebreak_bottom)
195 os << "\\pagebreak_bottom ";
197 // Start of appendix?
198 if (start_of_appendix)
199 os << "\\start_of_appendix ";
206 if (align != LYX_ALIGN_LAYOUT) {
208 case LYX_ALIGN_LEFT: h = 1; break;
209 case LYX_ALIGN_RIGHT: h = 2; break;
210 case LYX_ALIGN_CENTER: h = 3; break;
211 default: h = 0; break;
213 os << "\\align " << string_align[h] << " ";
215 if (pextra_type != PEXTRA_NONE) {
216 os << "\\pextra_type " << pextra_type;
217 if (pextra_type == PEXTRA_MINIPAGE) {
218 os << " \\pextra_alignment "
221 os << " \\pextra_hfill "
223 if (pextra_start_minipage)
224 os << " \\pextra_start_minipage "
225 << pextra_start_minipage;
227 if (!pextra_width.empty()) {
228 os << " \\pextra_width "
229 << VSpace(pextra_width).asLyXCommand();
230 } else if (!pextra_widthp.empty()) {
231 os << " \\pextra_widthp "
238 // Dummy layout. This means that a footnote ended.
239 os << "\n\\end_float ";
240 footflag = LyXParagraph::NO_FOOTNOTE;
243 // It might be a table.
245 os << "\\LyXTable\n";
253 font1 = LyXFont(LyXFont::ALL_INHERIT);
256 for (size_type i = 0; i < size(); i++) {
262 // Write font changes
263 font2 = GetFontSettings(i);
264 if (font2 != font1) {
265 font2.lyxWriteChanges(font1, os);
275 if (inset->DirectWrite()) {
276 // international char, let it write
277 // code directly so it's shorter in
281 os << "\n\\begin_inset ";
283 os << "\n\\end_inset \n\n";
288 os << "\n\\newline \n";
292 os << "\n\\hfill \n";
295 case META_PROTECTED_SEPARATOR:
296 os << "\n\\protected_separator \n";
300 os << "\n\\backslash \n";
304 if (i + 1 < size() && GetChar(i + 1) == ' ') {
311 if ((column > 70 && c == ' ')
316 // this check is to amend a bug. LyX sometimes
317 // inserts '\0' this could cause problems.
321 lyxerr << "ERROR (LyXParagraph::writeFile):"
322 " NULL char in structure." << endl;
328 // now write the next paragraph
330 next->writeFile(os, params, footflag, dth);
334 void LyXParagraph::validate(LaTeXFeatures & features)
336 // this will be useful later
337 LyXLayout const & layout = textclasslist.Style(current_view->buffer()->params.textclass,
341 if (line_top || line_bottom)
342 features.lyxline = true;
345 features.layout[GetLayout()] = true;
348 #ifdef NEW_FONTTABLE // OK, but does not affect structure anyway
349 for (FontList::const_iterator cit = fontlist.begin();
350 cit != fontlist.end(); ++cit) {
351 if ((*cit).font.noun() == LyXFont::ON) {
352 lyxerr[Debug::LATEX] << "font.noun: "
353 << (*cit).font.noun()
355 features.noun = true;
356 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
357 << (*cit).font.stateText()
360 switch ((*cit).font.color()) {
362 case LyXFont::INHERIT_COLOR:
363 case LyXFont::IGNORE_COLOR:
366 features.color = true;
367 lyxerr[Debug::LATEX] << "Color enabled. Font: "
368 << (*cit).font.stateText()
373 FontTable * tmpfonttable = fonttable;
374 while (tmpfonttable) {
375 if (tmpfonttable->font.noun() == LyXFont::ON) {
376 lyxerr[Debug::LATEX] << "font.noun: "
377 << tmpfonttable->font.noun()
379 features.noun = true;
380 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
381 << tmpfonttable->font.stateText()
384 switch (tmpfonttable->font.color()) {
386 case LyXFont::INHERIT_COLOR:
387 case LyXFont::IGNORE_COLOR:
390 features.color = true;
391 lyxerr[Debug::LATEX] << "Color enabled. Font: "
392 << tmpfonttable->font.stateText()
395 tmpfonttable = tmpfonttable->next;
399 #ifdef NEW_INSETTABLE
400 for (InsetList::const_iterator cit = insetlist.begin();
401 cit != insetlist.end(); ++cit) {
403 (*cit).inset->Validate(features);
406 InsetTable * tmpinsettable = insettable;
407 while (tmpinsettable) {
408 if (tmpinsettable->inset) {
409 tmpinsettable->inset->Validate(features);
411 tmpinsettable = tmpinsettable->next;
415 if (table && table->IsLongTable())
416 features.longtable = true;
417 if (pextra_type == PEXTRA_INDENT)
418 features.LyXParagraphIndent = true;
419 if (pextra_type == PEXTRA_FLOATFLT)
420 features.floatflt = true;
421 if (layout.needprotect
422 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
423 features.NeedLyXFootnoteCode = true;
424 if ((current_view->buffer()->params.paragraph_separation == BufferParams::PARSEP_INDENT) &&
425 (pextra_type == LyXParagraph::PEXTRA_MINIPAGE))
426 features.NeedLyXMinipageIndent = true;
427 if (table && table->NeedRotating())
428 features.rotating = true;
429 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
430 features.algorithm = true;
434 // First few functions needed for cut and paste and paragraph breaking.
435 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos) const
437 minibuffer_char = GetChar(pos);
438 minibuffer_font = GetFontSettings(pos);
439 minibuffer_inset = 0;
440 if (minibuffer_char == LyXParagraph::META_INSET) {
442 minibuffer_inset = GetInset(pos)->Clone();
444 minibuffer_inset = 0;
445 minibuffer_char = ' ';
446 // 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;
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) {
562 delete insettable->inset;
569 #ifndef NEW_FONTTABLE // OK
573 fonttable = fonttable->next;
578 /* table stuff -- begin*/
581 /* table stuff -- end*/
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
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.TextClass(current_view->buffer()->params.textclass).defaultfont());
1008 /// Returns the height of the highest font in range
1010 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
1011 LyXParagraph::size_type endpos) const
1013 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
1014 #ifdef NEW_FONTTABLE // Seems OK
1015 for (FontList::const_iterator cit = fontlist.begin();
1016 cit != fontlist.end(); ++cit) {
1017 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
1018 LyXFont::FONT_SIZE size = (*cit).font.size();
1019 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
1024 FontTable * tmp = fonttable;
1026 if (startpos <= tmp->pos_end && endpos >= tmp->pos) {
1027 LyXFont::FONT_SIZE size = tmp->font.size();
1028 if (size > maxsize && size<= LyXFont::SIZE_HUGER)
1038 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
1045 // > because last is the next unused position, and you can
1046 // use it if you want
1047 else if (pos > size()) {
1048 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1049 return NextAfterFootnote()
1050 ->GetChar(pos - text.size() - 1);
1052 lyxerr << "ERROR (LyXParagraph::GetChar): "
1053 "position does not exist."
1054 << pos << " (" << static_cast<int>(pos)
1060 // We should have a footnote environment.
1061 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
1062 // Notice that LyX does request the
1063 // last char from time to time. (Asger)
1064 //lyxerr << "ERROR (LyXParagraph::GetChar): "
1065 // "expected footnote." << endl;
1068 switch (next->footnotekind) {
1069 case LyXParagraph::FOOTNOTE:
1070 return LyXParagraph::META_FOOTNOTE;
1071 case LyXParagraph::MARGIN:
1072 return LyXParagraph::META_MARGIN;
1073 case LyXParagraph::FIG:
1074 case LyXParagraph::WIDE_FIG:
1075 return LyXParagraph::META_FIG;
1076 case LyXParagraph::TAB:
1077 case LyXParagraph::WIDE_TAB:
1078 return LyXParagraph::META_TAB;
1079 case LyXParagraph::ALGORITHM:
1080 return LyXParagraph::META_ALGORITHM;
1082 return '\0'; // to shut up gcc
1087 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
1094 // > because last is the next unused position, and you can
1095 // use it if you want
1096 else if (pos > size()) {
1097 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1098 return NextAfterFootnote()
1099 ->GetChar(pos - text.size() - 1);
1101 lyxerr << "ERROR (LyXParagraph::GetChar const): "
1102 "position does not exist."
1103 << pos << " (" << static_cast<int>(pos)
1109 // We should have a footnote environment.
1110 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
1111 // Notice that LyX does request the
1112 // last char from time to time. (Asger)
1113 //lyxerr << "ERROR (LyXParagraph::GetChar): "
1114 // "expected footnote." << endl;
1117 switch (next->footnotekind) {
1118 case LyXParagraph::FOOTNOTE:
1119 return LyXParagraph::META_FOOTNOTE;
1120 case LyXParagraph::MARGIN:
1121 return LyXParagraph::META_MARGIN;
1122 case LyXParagraph::FIG:
1123 case LyXParagraph::WIDE_FIG:
1124 return LyXParagraph::META_FIG;
1125 case LyXParagraph::TAB:
1126 case LyXParagraph::WIDE_TAB:
1127 return LyXParagraph::META_TAB;
1128 case LyXParagraph::ALGORITHM:
1129 return LyXParagraph::META_ALGORITHM;
1131 return '\0'; // to shut up gcc
1136 // return an string of the current word, and the end of the word in lastpos.
1137 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
1141 // the current word is defined as starting at the first character
1142 // from the immediate left of lastpospos which meets the definition
1143 // of IsLetter(), continuing to the last character to the right
1144 // of this meeting IsLetter.
1150 // move back until we have a letter
1152 //there's no real reason to have firstpos & lastpos as
1153 //separate variables as this is written, but maybe someon
1154 // will want to return firstpos in the future.
1156 //since someone might have typed a punctuation first
1157 int firstpos = lastpos;
1159 while ((firstpos >= 0) && !IsLetter(firstpos))
1162 // now find the beginning by looking for a nonletter
1164 while ((firstpos>= 0) && IsLetter(firstpos))
1167 // the above is now pointing to the preceeding non-letter
1171 // so copy characters into theword until we get a nonletter
1172 // note that this can easily exceed lastpos, wich means
1173 // that if used in the middle of a word, the whole word
1176 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1183 LyXParagraph::size_type LyXParagraph::Last() const
1185 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1186 return text.size() + NextAfterFootnote()->Last() + 1;
1187 // the 1 is the symbol
1194 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
1196 // > because last is the next unused position, and you can
1197 // use it if you want
1200 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1201 return NextAfterFootnote()
1202 ->ParFromPos(pos - text.size() - 1);
1204 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1205 "position does not exist." << endl;
1212 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
1214 // > because last is the next unused position, and you can
1215 // use it if you want
1218 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1219 return NextAfterFootnote()
1220 ->PositionInParFromPos(pos - text.size() - 1);
1223 "ERROR (LyXParagraph::PositionInParFromPos): "
1224 "position does not exist." << endl;
1232 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1233 LyXFont const & font)
1235 // > because last is the next unused position, and you can
1236 // use it if you want
1239 next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1240 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1243 lyxerr << "ERROR (LyXParagraph::SetFont): "
1244 "position does not exist." << endl;
1248 LyXFont patternfont(LyXFont::ALL_INHERIT);
1250 // First, reduce font against layout/label font
1251 // Update: The SetCharFont() routine in text2.C already
1252 // reduces font, so we don't need to do that here. (Asger)
1253 // No need to simplify this because it will disappear
1254 // in a new kernel. (Asger)
1255 // Next search font table
1256 #ifdef NEW_FONTTABLE
1257 FontList::iterator tmp = fontlist.begin();
1258 for (; tmp != fontlist.end(); ++tmp) {
1259 if (pos >= (*tmp).pos && pos <= (*tmp).pos_end) {
1263 if (tmp == fontlist.end()) { // !found
1264 // if we did not find a font entry, but if the font at hand
1265 // is the same as default, we just forget it
1266 if (font == patternfont) return;
1268 // ok, we did not find a font entry. But maybe there is exactly
1269 // the needed font ientry one position left
1270 FontList::iterator tmp2 = fontlist.begin();
1271 for (; tmp2 != fontlist.end(); ++tmp2) {
1272 if (pos - 1 >= (*tmp2).pos
1273 && pos - 1 <= (*tmp2).pos_end)
1276 if (tmp2 != fontlist.end()) {
1277 // ok there is one, maybe it is exactly
1279 if ((*tmp2).font == font) {
1280 // put the position under the font
1285 // Add a new entry in the
1286 // fontlist for the position
1290 ft.font = font; // or patternfont
1291 // It seems that using font instead of patternfont here
1292 // fixes all the problems. This also surfaces a "bug" in
1294 fontlist.insert(fontlist.begin(), ft);
1295 } else if ((*tmp).pos != (*tmp).pos_end) { // we found a font entry. maybe we have to split it and create a new one.
1297 // more than one character
1298 if (pos == (*tmp).pos) {
1299 // maybe we should enlarge the left fonttable
1300 FontList::iterator tmp2 = fontlist.begin();
1301 for (; tmp2 != fontlist.end(); ++tmp2) {
1302 if (pos - 1 >= (*tmp2).pos
1303 && pos - 1 <= (*tmp2).pos_end)
1306 // Is there is one, and is it exactly
1308 if (tmp2 != fontlist.end() &&
1309 (*tmp2).font == font) {
1310 // Put the position under the font
1316 // Add a new entry in the
1317 // fontlist for the position
1320 ft.pos_end = (*tmp).pos_end;
1321 ft.font = (*tmp).font;
1322 (*tmp).pos_end = pos;
1324 fontlist.insert(fontlist.begin(), ft);
1325 } else if (pos == (*tmp).pos_end) {
1326 // Add a new entry in the
1327 // fontlist for the position
1329 ft.pos = (*tmp).pos;
1330 ft.pos_end = (*tmp).pos_end - 1;
1331 ft.font = (*tmp).font;
1332 (*tmp).pos = (*tmp).pos_end;
1334 fontlist.insert(fontlist.begin(), ft);
1336 // Add a new entry in the
1337 // fontlist for the position
1339 ft.pos = (*tmp).pos;
1340 ft.pos_end = pos - 1;
1341 ft.font = (*tmp).font;
1345 ft2.pos_end = (*tmp).pos_end;
1346 ft2.font = (*tmp).font;
1349 (*tmp).pos_end = pos;
1352 fontlist.insert(fontlist.begin(), ft);
1353 fontlist.insert(fontlist.begin(), ft2);
1363 FontTable * tmp = fonttable;
1364 while (tmp && !found) {
1365 if (pos >= tmp->pos && pos <= tmp->pos_end)
1372 // if we did not find a font entry, but if the font at hand
1373 // is the same as default, we just forget it
1374 if (font == patternfont)
1377 // ok, we did not find a font entry. But maybe there is exactly
1378 // the needed font entry one position left
1381 while (tmp2 && !found) {
1382 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1388 // ok there is one. maybe it is exactly
1390 if (tmp2->font == font) {
1391 // put the position under the font
1396 // Add a new entry in the
1397 // fonttable for the position
1398 tmp = new FontTable;
1401 tmp->font = patternfont; // It seems that is actually totally
1402 // wrong to use patternfont here, the correct should be font
1403 // lockily at the end of this function we have
1404 // tmp->font = font, so this one setting it to patternfont
1406 tmp->next = fonttable;
1409 // we found a font entry. maybe we have
1410 // to split it and create a new one
1412 if (tmp->pos != tmp->pos_end) { // more than one character
1413 if (pos == tmp->pos) {
1414 // maybe we could enlarge the left fonttable
1417 while (tmp2 && !found) {
1418 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1424 // Is there is one, and is it exactly
1426 if (found && tmp2->font == font) {
1427 // Put the position under the font
1433 // Add a new entry in the
1434 // fonttable for the position
1435 tmp2 = new FontTable;
1436 tmp2->pos = pos + 1;
1437 tmp2->pos_end = tmp->pos_end;
1438 tmp2->font = tmp->font;
1440 tmp2->next = fonttable;
1443 else if (pos == tmp->pos_end) {
1444 // Add a new entry in the
1445 // fonttable for the position
1446 tmp2 = new FontTable;
1447 tmp2->pos = tmp->pos;
1448 tmp2->pos_end = tmp->pos_end - 1;
1449 tmp2->font = tmp->font;
1450 tmp->pos = tmp->pos_end;
1451 tmp2->next = fonttable;
1455 // Add a new entry in the
1456 // fonttable for the position
1457 tmp2 = new FontTable;
1458 tmp2->pos = tmp->pos;
1459 tmp2->pos_end = pos - 1;
1460 tmp2->font = tmp->font;
1461 tmp2->next = fonttable;
1464 tmp2 = new FontTable;
1465 tmp2->pos = pos + 1;
1466 tmp2->pos_end = tmp->pos_end;
1467 tmp2->font = tmp->font;
1468 tmp2->next = fonttable;
1481 // This function is able to hide closed footnotes.
1482 LyXParagraph * LyXParagraph::Next()
1484 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1485 LyXParagraph * tmp = next;
1487 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1489 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1490 return tmp->Next(); /* there can be more than one
1491 footnote in a logical
1494 return next; // This should never happen!
1500 LyXParagraph * LyXParagraph::NextAfterFootnote()
1502 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1503 LyXParagraph * tmp = next;
1504 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1506 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1507 return tmp; /* there can be more than one footnote
1508 in a logical paragraph */
1510 return next; // This should never happen!
1516 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1518 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1519 LyXParagraph * tmp = next;
1520 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1522 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1523 return tmp; /* there can be more than one footnote
1524 in a logical paragraph */
1526 return next; // This should never happen!
1532 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1535 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1537 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1538 tmp = tmp->previous;
1539 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1540 return tmp; /* there can be more than one footnote
1541 in a logical paragraph */
1543 return previous; // This should never happen!
1549 LyXParagraph * LyXParagraph::LastPhysicalPar()
1551 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1554 LyXParagraph * tmp = this;
1556 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1557 tmp = tmp->NextAfterFootnote();
1564 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1568 LyXParagraph * tmppar = this;
1572 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1573 tmppar = tmppar->previous;
1576 Assert(false); // let's get an abort then
1577 return this; // This should never happen!
1583 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1587 LyXParagraph const * tmppar = this;
1589 while (tmppar && (tmppar->IsDummy()
1590 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1591 tmppar = tmppar->previous;
1594 Assert(false); // let's get an abort then
1595 return this; // This should never happen!
1601 // This function is able to hide closed footnotes.
1602 LyXParagraph * LyXParagraph::Previous()
1604 LyXParagraph * tmp = previous;
1609 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1610 tmp = tmp->previous;
1612 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1613 tmp = tmp->previous;
1614 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1615 return tmp->next->Previous();
1624 // This function is able to hide closed footnotes.
1625 LyXParagraph const * LyXParagraph::Previous() const
1627 LyXParagraph * tmp = previous;
1632 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1633 tmp = tmp->previous;
1635 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1636 tmp = tmp->previous;
1637 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1638 return tmp->next->Previous();
1647 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1650 size_type i, pos_end, pos_first;
1651 // create a new paragraph
1652 LyXParagraph * par = ParFromPos(pos);
1653 LyXParagraph * firstpar = FirstPhysicalPar();
1655 LyXParagraph * tmp = new LyXParagraph(par);
1657 tmp->footnoteflag = footnoteflag;
1658 tmp->footnotekind = footnotekind;
1660 // this is an idea for a more userfriendly layout handling, I will
1661 // see what the users say
1663 // layout stays the same with latex-environments
1665 tmp->SetOnlyLayout(firstpar->layout);
1666 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1669 if (Last() > pos || !Last() || flag == 2) {
1670 tmp->SetOnlyLayout(firstpar->layout);
1671 tmp->align = firstpar->align;
1672 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1674 tmp->line_bottom = firstpar->line_bottom;
1675 firstpar->line_bottom = false;
1676 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1677 firstpar->pagebreak_bottom = false;
1678 tmp->added_space_bottom = firstpar->added_space_bottom;
1679 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1681 tmp->depth = firstpar->depth;
1682 tmp->noindent = firstpar->noindent;
1684 // copy everything behind the break-position
1685 // to the new paragraph
1687 while (ParFromPos(pos_first) != par)
1690 pos_end = pos_first + par->text.size() - 1;
1691 // The constructor has already reserved 500 elements
1692 //if (pos_end > pos)
1693 // tmp->text.reserve(pos_end - pos);
1695 for (i = pos; i <= pos_end; i++) {
1696 par->CutIntoMinibuffer(i - pos_first);
1697 tmp->InsertFromMinibuffer(i - pos);
1699 tmp->text.resize(tmp->text.size());
1700 for (i = pos_end; i >= pos; i--)
1701 par->Erase(i - pos_first);
1703 par->text.resize(par->text.size());
1706 // just an idea of me
1708 tmp->line_top = firstpar->line_top;
1709 tmp->pagebreak_top = firstpar->pagebreak_top;
1710 tmp->added_space_top = firstpar->added_space_top;
1711 tmp->bibkey = firstpar->bibkey;
1713 // layout stays the same with latex-environments
1715 firstpar->SetOnlyLayout(tmp->layout);
1716 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1717 firstpar->depth = tmp->depth;
1723 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1725 par = par->FirstPhysicalPar();
1726 footnoteflag = par->footnoteflag;
1727 footnotekind = par->footnotekind;
1729 layout = par->layout;
1730 align = par-> align;
1731 SetLabelWidthString(par->labelwidthstring);
1733 line_bottom = par->line_bottom;
1734 pagebreak_bottom = par->pagebreak_bottom;
1735 added_space_bottom = par->added_space_bottom;
1737 line_top = par->line_top;
1738 pagebreak_top = par->pagebreak_top;
1739 added_space_top = par->added_space_top;
1741 pextra_type = par->pextra_type;
1742 pextra_width = par->pextra_width;
1743 pextra_widthp = par->pextra_widthp;
1744 pextra_alignment = par->pextra_alignment;
1745 pextra_hfill = par->pextra_hfill;
1746 pextra_start_minipage = par->pextra_start_minipage;
1748 noindent = par->noindent;
1753 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1755 LyXParagraph * tmppar = this;
1758 && tmppar->previous->footnoteflag ==
1759 LyXParagraph::CLOSED_FOOTNOTE)
1760 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1761 tmppar = tmppar->previous;
1764 return this; // This should never happen!
1770 LyXParagraph * LyXParagraph::Clone() const
1772 // create a new paragraph
1773 LyXParagraph * result = new LyXParagraph;
1775 result->MakeSameLayout(this);
1777 // this is because of the dummy layout of the paragraphs that
1779 result->layout = layout;
1781 /* table stuff -- begin*/
1783 result->table = table->Clone();
1786 /* table stuff -- end*/
1789 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1792 // copy everything behind the break-position to the new paragraph
1794 for (size_type i = 0; i < size(); i++) {
1795 CopyIntoMinibuffer(i);
1796 result->InsertFromMinibuffer(i);
1798 result->text.resize(result->text.size());
1803 bool LyXParagraph::HasSameLayout(LyXParagraph const * par)
1805 par = par->FirstPhysicalPar();
1808 par->footnoteflag == footnoteflag &&
1809 par->footnotekind == footnotekind &&
1811 par->layout == layout &&
1813 par->align == align &&
1815 par->line_bottom == line_bottom &&
1816 par->pagebreak_bottom == pagebreak_bottom &&
1817 par->added_space_bottom == added_space_bottom &&
1819 par->line_top == line_top &&
1820 par->pagebreak_top == pagebreak_top &&
1821 par->added_space_top == added_space_top &&
1823 par->pextra_type == pextra_type &&
1824 par->pextra_width == pextra_width &&
1825 par->pextra_widthp == pextra_widthp &&
1826 par->pextra_alignment == pextra_alignment &&
1827 par->pextra_hfill == pextra_hfill &&
1828 par->pextra_start_minipage == pextra_start_minipage &&
1830 par->table == table && // what means: NO TABLE AT ALL
1832 par->noindent == noindent &&
1833 par->depth == depth);
1837 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
1839 // create a new paragraph
1840 LyXParagraph * par = ParFromPos(pos);
1842 LyXParagraph * tmp = new LyXParagraph(par);
1844 tmp->MakeSameLayout(par);
1846 // When can pos < Last()?
1847 // I guess pos == Last() is possible.
1849 // copy everything behind the break-position to the new
1851 size_type pos_first = 0;
1852 while (ParFromPos(pos_first) != par)
1854 size_type pos_end = pos_first + par->text.size() - 1;
1855 // make sure there is enough memory for the now larger
1856 // paragraph. This is not neccessary, because
1857 // InsertFromMinibuffer will enlarge the memory (it uses
1858 // InsertChar of course). But doing it by hand
1859 // is MUCH faster! (only one time, not thousend times!!)
1860 // Not needed since the constructor aleady have
1861 // reserved 500 elements in text.
1862 //if (pos_end > pos)
1863 // tmp->text.reserve(pos_end - pos);
1865 for (size_type i = pos; i <= pos_end; ++i) {
1866 par->CutIntoMinibuffer(i - pos_first);
1867 tmp->InsertFromMinibuffer(i - pos);
1869 tmp->text.resize(tmp->text.size());
1870 for (size_type i = pos_end; i >= pos; --i)
1871 par->Erase(i - pos_first);
1873 par->text.resize(par->text.size());
1878 // Be carefull, this does not make any check at all.
1879 void LyXParagraph::PasteParagraph()
1881 // copy the next paragraph to this one
1882 LyXParagraph * the_next = Next();
1884 LyXParagraph * firstpar = FirstPhysicalPar();
1886 // first the DTP-stuff
1887 firstpar->line_bottom = the_next->line_bottom;
1888 firstpar->added_space_bottom = the_next->added_space_bottom;
1889 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1891 size_type pos_end = the_next->text.size() - 1;
1892 size_type pos_insert = Last();
1895 // ok, now copy the paragraph
1896 for (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;
2624 bool return_value = false;
2625 int current_cell_number = -1;
2627 LyXLayout const & style =
2628 textclasslist.Style(current_view->buffer()->params.textclass, GetLayout());
2629 LyXFont basefont = getFont(-1); // Get layout font
2630 // Which font is currently active?
2631 LyXFont running_font = basefont;
2632 // Do we have an open font change?
2633 bool open_font = false;
2636 if (!IsDummy()) { // it is dummy if it is in a float!!!
2637 if (style.isCommand()) {
2640 } else if (align != LYX_ALIGN_LAYOUT) {
2643 return_value = true;
2646 file += "\\noindent ";
2650 case LYX_ALIGN_NONE:
2651 case LYX_ALIGN_BLOCK:
2652 case LYX_ALIGN_LAYOUT:
2653 case LYX_ALIGN_SPECIAL: break;
2654 case LYX_ALIGN_LEFT:
2655 file += "\\raggedright ";
2658 case LYX_ALIGN_RIGHT:
2659 file += "\\raggedleft ";
2662 case LYX_ALIGN_CENTER:
2663 file += "\\centering ";
2668 current_cell_number = -1;
2669 tmp = table->TexEndOfCell(file, current_cell_number);
2670 for (; tmp > 0 ; --tmp)
2673 texrow.start(this, 0);
2675 for (size_type i = 0; i < size(); ++i) {
2677 if (table->IsContRow(current_cell_number+1)) {
2678 if (c == LyXParagraph::META_NEWLINE)
2679 current_cell_number++;
2684 // Fully instantiated font
2685 LyXFont font = getFont(i);
2687 // Spaces at end of font change are simulated to be
2688 // outside font change.
2689 // i.e. we write "\textXX{text} " rather than
2690 // "\textXX{text }". (Asger)
2691 if (open_font && c == ' ' && i <= size() - 2
2692 && getFont(i+1) != running_font && getFont(i+1) != font) {
2693 font = getFont(i+1);
2696 // We end font definition before blanks
2697 if (font != running_font && open_font) {
2698 column += running_font.latexWriteEndChanges(file,
2700 running_font = basefont;
2703 // Blanks are printed before start of fontswitch
2705 SimpleTeXBlanks(file, texrow, i, column, font, style);
2707 // Do we need to change font?
2708 if (font != running_font) {
2709 column += font.latexWriteStartChanges(file, basefont);
2710 running_font = font;
2713 // Do we need to turn on LaTeX mode?
2714 if (font.latex() != running_font.latex()) {
2715 if (font.latex() == LyXFont::ON
2716 && style.needprotect) {
2717 file += "\\protect ";
2721 if (c == LyXParagraph::META_NEWLINE) {
2722 // special case for inside a table
2723 // different from default case in
2724 // SimpleTeXSpecialChars()
2726 column += running_font
2727 .latexWriteEndChanges(file, basefont);
2730 basefont = getFont(-1);
2731 running_font = basefont;
2732 current_cell_number++;
2733 if (table->CellHasContRow(current_cell_number) >= 0) {
2734 TeXContTableRows(file, i+1,
2735 current_cell_number,
2738 // if this cell follow only ContRows till end don't
2739 // put the EndOfCell because it is put after the
2741 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2742 current_cell_number--;
2745 int tmp = table->TexEndOfCell(file,
2746 current_cell_number);
2749 } else if (tmp < 0) {
2755 texrow.start(this, i+1);
2757 SimpleTeXSpecialChars(file, texrow,
2758 font, running_font, basefont,
2759 open_font, style, i, column, c);
2763 // If we have an open font definition, we have to close it
2765 running_font.latexWriteEndChanges(file, basefont);
2767 current_cell_number++;
2768 tmp = table->TexEndOfCell(file, current_cell_number);
2769 for (; tmp > 0; --tmp)
2771 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2772 return return_value;
2776 // This one spits out the text off ContRows in tables
2777 bool LyXParagraph::TeXContTableRows(string & file,
2778 LyXParagraph::size_type i,
2779 int current_cell_number,
2780 int & column, TexRow & texrow)
2782 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2788 bool return_value = false;
2789 LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass,
2793 basefont = getFont(-1); // Get layout font
2794 // Which font is currently active?
2795 LyXFont running_font = basefont;
2796 // Do we have an open font change?
2797 bool open_font = false;
2799 size_type lastpos = i;
2800 int cell = table->CellHasContRow(current_cell_number);
2801 ++current_cell_number;
2803 // first find the right position
2805 for (; (i < size()) && (current_cell_number<cell); ++i) {
2807 if (c == LyXParagraph::META_NEWLINE)
2808 current_cell_number++;
2812 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2816 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2821 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2825 // Fully instantiated font
2826 LyXFont font = getFont(i);
2828 // Spaces at end of font change are simulated to
2829 // be outside font change. i.e. we write
2830 // "\textXX{text} " rather than "\textXX{text }".
2832 if (open_font && c == ' ' && i <= size() - 2
2833 && getFont(i + 1) != running_font
2834 && getFont(i + 1) != font) {
2835 font = getFont(i + 1);
2838 // We end font definition before blanks
2839 if (font != running_font && open_font) {
2840 column += running_font.latexWriteEndChanges(file, basefont);
2841 running_font = basefont;
2844 // Blanks are printed before start of fontswitch
2846 SimpleTeXBlanks(file, texrow, i,
2847 column, font, style);
2849 // Do we need to change font?
2850 if (font != running_font) {
2852 font.latexWriteStartChanges(file,
2854 running_font = font;
2857 // Do we need to turn on LaTeX mode?
2858 if (font.latex() != running_font.latex()) {
2859 if (font.latex() == LyXFont::ON
2860 && style.needprotect)
2862 file += "\\protect ";
2866 SimpleTeXSpecialChars(file, texrow, font,
2867 running_font, basefont,
2868 open_font, style, i, column, c);
2870 // If we have an open font definition, we have to close it
2872 running_font.latexWriteEndChanges(file, basefont);
2875 basefont = getFont(-1);
2876 running_font = basefont;
2877 cell = table->CellHasContRow(current_cell_number);
2879 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2880 return return_value;
2884 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2886 bool retval = false;
2888 case LyXParagraph::META_HFILL:
2889 sgml_string.clear();
2891 case LyXParagraph::META_PROTECTED_SEPARATOR:
2894 case LyXParagraph::META_NEWLINE:
2898 sgml_string = "&";
2901 sgml_string = "<";
2904 sgml_string = ">";
2907 sgml_string = "$";
2910 sgml_string = "#";
2913 sgml_string = "%";
2916 sgml_string = "[";
2919 sgml_string = "]";
2922 sgml_string = "{";
2925 sgml_string = "}";
2928 sgml_string = "˜";
2931 sgml_string = """;
2934 sgml_string = "\";
2940 case '\0': // Ignore :-)
2941 sgml_string.clear();
2951 void LyXParagraph::SimpleDocBookOneTablePar(string & file, string & extra,
2952 int & desc_on, int depth)
2955 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2957 LyXFont font1, font2;
2960 size_type main_body;
2961 string emph = "emphasis";
2962 bool emph_flag = false;
2964 LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass,
2967 if (style.labeltype != LABEL_MANUAL)
2970 main_body = BeginningOfMainBody();
2972 // Gets paragraph main font.
2974 font1 = style.labelfont;
2978 int char_line_count = depth;
2979 addNewlineAndDepth(file, depth);
2980 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2981 file += "<INFORMALTABLE>";
2982 addNewlineAndDepth(file, ++depth);
2984 int current_cell_number = -1;
2985 int tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
2987 // Parsing main loop.
2988 for (size_type i = 0; i < size(); ++i) {
2990 if (table->IsContRow(current_cell_number+1)) {
2991 if (c == LyXParagraph::META_NEWLINE)
2992 ++current_cell_number;
2997 // Fully instantiated font
3000 // Handle <emphasis> tag.
3001 if (font1.emph() != font2.emph() && i) {
3002 if (font2.emph() == LyXFont::ON) {
3003 file += "<emphasis>";
3005 } else if (emph_flag) {
3006 file += "</emphasis>";
3010 if (c == LyXParagraph::META_NEWLINE) {
3011 // We have only to control for emphasis open here!
3013 file += "</emphasis>";
3016 font1 = font2 = getFont(-1);
3017 current_cell_number++;
3018 if (table->CellHasContRow(current_cell_number) >= 0) {
3019 DocBookContTableRows(file, extra, desc_on, i+1,
3020 current_cell_number,
3023 // if this cell follow only ContRows till end don't
3024 // put the EndOfCell because it is put after the
3026 if (table->ShouldBeVeryLastCell(current_cell_number)) {
3027 current_cell_number--;
3030 tmp= table->DocBookEndOfCell(file, 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;
3127 LyXFont font1, font2;
3130 size_type main_body;
3132 string emph= "emphasis";
3133 bool emph_flag= false;
3134 int char_line_count= 0;
3136 LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass,
3139 if (style.labeltype != LABEL_MANUAL)
3142 main_body = BeginningOfMainBody();
3144 // Gets paragraph main font.
3146 font1 = style.labelfont;
3151 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 command paragraph
3200 // graphics inside tables or figure floats can't go on
3201 // title (the equivalente in latex for this case is caption
3202 // and title should come first
3205 if(desc_on != 3 || i != 0) {
3206 if(tmp_out[0] == '@') {
3208 extra += frontStrip(tmp_out, '@');
3210 file += frontStrip(tmp_out, '@');
3214 } else if (font2.latex() == LyXFont::ON) {
3215 // "TeX"-Mode on == > SGML-Mode on.
3221 if (linuxDocConvertChar(c, sgml_string)
3222 && !style.free_spacing) {
3223 // in freespacing mode, spaces are
3224 // non-breaking characters
3229 file += "</term><listitem><para>";
3235 file += sgml_string;
3239 // we have only to control for emphasis open here!
3241 file += "</emphasis>";
3244 font1 = font2 = getFont(-1);
3245 cell = table->CellHasContRow(current_cell_number);
3247 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3251 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
3252 LyXParagraph::size_type const i,
3253 int & column, LyXFont const & font,
3254 LyXLayout const & style)
3256 if (column > tex_code_break_column
3258 && GetChar(i - 1) != ' '
3260 // In LaTeX mode, we don't want to
3261 // break lines since some commands
3263 && ! (font.latex() == LyXFont::ON)
3264 // same in FreeSpacing mode
3265 && !style.free_spacing
3266 // In typewriter mode, we want to avoid
3267 // ! . ? : at the end of a line
3268 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3269 && (GetChar(i-1) == '.'
3270 || GetChar(i-1) == '?'
3271 || GetChar(i-1) == ':'
3272 || GetChar(i-1) == '!'))) {
3273 if (tex_code_break_column == 0) {
3274 // in batchmode we need LaTeX to still
3275 // see it as a space not as an extra '\n'
3281 texrow.start(this, i+1);
3283 } else if (font.latex() == LyXFont::OFF) {
3284 if (style.free_spacing) {
3293 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
3295 LyXFont & running_font,
3298 LyXLayout const & style,
3299 LyXParagraph::size_type & i,
3300 int & column, char const c)
3302 // Two major modes: LaTeX or plain
3303 // Handle here those cases common to both modes
3304 // and then split to handle the two modes separately.
3306 case LyXParagraph::META_INSET: {
3307 Inset * inset = GetInset(i);
3309 int len = file.length();
3310 int tmp = inset->Latex(file, style.isCommand());
3315 column += file.length() - len;
3324 case LyXParagraph::META_NEWLINE:
3326 column += running_font.latexWriteEndChanges(file,
3330 basefont = getFont(-1);
3331 running_font = basefont;
3334 case LyXParagraph::META_HFILL:
3335 file += "\\hfill{}";
3340 // And now for the special cases within each mode
3341 // Are we in LaTeX mode?
3342 if (font.latex() == LyXFont::ON) {
3343 // at present we only have one option
3344 // but I'll leave it as a switch statement
3345 // so its simpler to extend. (ARRae)
3347 case LyXParagraph::META_PROTECTED_SEPARATOR:
3352 // make sure that we will not print
3353 // error generating chars to the tex
3354 // file. This test would not be needed
3355 // if it were done in the buffer
3363 // Plain mode (i.e. not LaTeX)
3365 case LyXParagraph::META_PROTECTED_SEPARATOR:
3370 file += "\\textbackslash{}";
3374 case '°': case '±': case '²': case '³':
3375 case '×': case '÷': case '¹': case 'ª':
3376 case 'º': case '¬': case 'µ':
3377 if (current_view->buffer()->params.inputenc == "latin1") {
3378 file += "\\ensuremath{";
3387 case '|': case '<': case '>':
3388 // In T1 encoding, these characters exist
3389 if (lyxrc->fontenc == "T1") {
3391 //... but we should avoid ligatures
3392 if ((c == '>' || c == '<')
3394 && GetChar(i+1) == c){
3395 file += "\\textcompwordmark{}";
3400 // Typewriter font also has them
3401 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3405 // Otherwise, we use what LaTeX
3409 file += "\\textless{}";
3413 file += "\\textgreater{}";
3417 file += "\\textbar{}";
3423 case '-': // "--" in Typewriter mode -> "-{}-"
3425 && GetChar(i + 1) == '-'
3426 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3435 file += "\\char`\\\"{}";
3440 if (current_view->buffer()->params.inputenc == "default") {
3441 file += "\\pounds{}";
3449 case '%': case '#': case '{':
3457 file += "\\textasciitilde{}";
3462 file += "\\textasciicircum{}";
3466 case '*': case '[': case ']':
3467 // avoid being mistaken for optional arguments
3475 // Blanks are printed before font switching.
3476 // Sure? I am not! (try nice-latex)
3477 // I am sure it's correct. LyX might be smarter
3478 // in the future, but for now, nothing wrong is
3483 /* idea for labels --- begin*/
3487 && font.family() != LyXFont::TYPEWRITER_FAMILY
3488 && GetChar(i + 1) == 'y'
3489 && GetChar(i + 2) == 'X') {
3497 && font.family() != LyXFont::TYPEWRITER_FAMILY
3498 && GetChar(i + 1) == 'e'
3499 && GetChar(i + 2) == 'X') {
3504 // Check for "LaTeX2e"
3507 && font.family() != LyXFont::TYPEWRITER_FAMILY
3508 && GetChar(i + 1) == 'a'
3509 && GetChar(i + 2) == 'T'
3510 && GetChar(i + 3) == 'e'
3511 && GetChar(i + 4) == 'X'
3512 && GetChar(i + 5) == '2'
3513 && GetChar(i + 6) == 'e') {
3514 file += "\\LaTeXe{}";
3518 // Check for "LaTeX"
3521 && font.family() != LyXFont::TYPEWRITER_FAMILY
3522 && GetChar(i + 1) == 'a'
3523 && GetChar(i + 2) == 'T'
3524 && GetChar(i + 3) == 'e'
3525 && GetChar(i + 4) == 'X') {
3526 file += "\\LaTeX{}";
3529 /* idea for labels --- end*/
3530 } else if (c != '\0') {
3540 bool LyXParagraph::RoffContTableRows(ostream & os,
3541 LyXParagraph::size_type i,
3547 LyXFont font1 = LyXFont(LyXFont::ALL_INHERIT);
3552 string fname2 = TmpFileName(string(), "RAT2");
3554 int cell = table->CellHasContRow(actcell);
3557 // first find the right position
3559 for (; i < size() && actcell < cell; ++i) {
3561 if (c == LyXParagraph::META_NEWLINE)
3566 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3569 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3571 font2 = GetFontSettings(i);
3572 if (font1.latex() != font2.latex()) {
3573 if (font2.latex() != LyXFont::OFF)
3578 case LyXParagraph::META_INSET:
3579 if ((inset = GetInset(i))) {
3580 fstream fs(fname2.c_str(),
3583 WriteAlert(_("LYX_ERROR:"),
3584 _("Cannot open temporary file:"),
3588 inset->Latex(fs, -1);
3601 case LyXParagraph::META_NEWLINE:
3603 case LyXParagraph::META_HFILL:
3605 case LyXParagraph::META_PROTECTED_SEPARATOR:
3614 lyxerr.debug() << "RoffAsciiTable: "
3615 "NULL char in structure."
3620 cell = table->CellHasContRow(actcell);
3626 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
3627 string & foot, TexRow & foot_texrow,
3630 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3631 LyXParagraph * par = this;
3633 while (par && par->depth == depth) {
3635 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3636 if (textclasslist.Style(current_view->buffer()->params.textclass,
3637 par->layout).isEnvironment()
3638 || par->pextra_type != PEXTRA_NONE)
3640 par = par->TeXEnvironment(file, texrow,
3644 par = par->TeXOnePar(file, texrow,
3649 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3655 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
3656 string & foot, TexRow & foot_texrow,
3659 bool eindent_open = false;
3660 bool foot_this_level = false;
3661 // flags when footnotetext should be appended to file.
3662 static bool minipage_open = false;
3663 static int minipage_open_depth = 0;
3664 char par_sep = current_view->buffer()->params.paragraph_separation;
3666 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3668 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3670 LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass,
3673 if (pextra_type == PEXTRA_INDENT) {
3674 if (!pextra_width.empty()) {
3675 file += "\\begin{LyXParagraphIndent}{"
3676 + pextra_width + "}\n";
3678 //float ib = atof(pextra_widthp.c_str())/100;
3679 // string can't handle floats at present (971109)
3680 // so I'll do a conversion by hand knowing that
3681 // the limits are 0.0 to 1.0. ARRae.
3682 file += "\\begin{LyXParagraphIndent}{";
3683 switch (pextra_widthp.length()) {
3689 file += pextra_widthp;
3693 file += pextra_widthp;
3695 file += "\\columnwidth}\n";
3698 eindent_open = true;
3700 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3701 if (pextra_hfill && Previous() &&
3702 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3703 file += "\\hfill{}\n";
3706 if (par_sep == BufferParams::PARSEP_INDENT) {
3707 file += "{\\setlength\\parindent{0pt}\n";
3710 file += "\\begin{minipage}";
3711 switch(pextra_alignment) {
3712 case MINIPAGE_ALIGN_TOP:
3715 case MINIPAGE_ALIGN_MIDDLE:
3718 case MINIPAGE_ALIGN_BOTTOM:
3722 if (!pextra_width.empty()) {
3724 file += pextra_width + "}\n";
3726 //float ib = atof(par->pextra_width.c_str())/100;
3727 // string can't handle floats at present
3728 // so I'll do a conversion by hand knowing that
3729 // the limits are 0.0 to 1.0. ARRae.
3731 switch (pextra_widthp.length()) {
3737 file += pextra_widthp;
3741 file += pextra_widthp;
3743 file += "\\columnwidth}\n";
3746 if (par_sep == BufferParams::PARSEP_INDENT) {
3747 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3750 minipage_open = true;
3751 minipage_open_depth = depth;
3754 #ifdef WITH_WARNINGS
3755 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3756 //I disabled it because it breaks when lists span on several
3759 if (style.isEnvironment()){
3760 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3761 #ifdef FANCY_FOOTNOTE_CODE
3762 if (foot_count < 0) {
3763 // flag that footnote[mark][text] should be
3764 // used for any footnotes from now on
3766 foot_this_level = true;
3769 file += "\\begin{" + style.latexname() + "}{"
3770 + labelwidthstring + "}\n";
3771 } else if (style.labeltype == LABEL_BIBLIO) {
3773 file += "\\begin{" + style.latexname() + "}{"
3774 + bibitemWidthest() + "}\n";
3775 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3776 #ifdef FANCY_FOOTNOTE_CODE
3777 if (foot_count < 0) {
3778 // flag that footnote[mark][text] should be
3779 // used for any footnotes from now on
3781 foot_this_level = true;
3784 file += "\\begin{" + style.latexname() + '}'
3785 + style.latexparam() + '\n';
3787 file += "\\begin{" + style.latexname() + '}'
3788 + style.latexparam() + '\n';
3791 LyXParagraph * par = this;
3793 par = par->TeXOnePar(file, texrow,
3794 foot, foot_texrow, foot_count);
3796 if (minipage_open && par && !style.isEnvironment() &&
3797 (par->pextra_type == PEXTRA_MINIPAGE) &&
3798 par->pextra_start_minipage) {
3799 file += "\\end{minipage}\n";
3801 if (par_sep == BufferParams::PARSEP_INDENT) {
3805 minipage_open = false;
3807 if (par && par->depth > depth) {
3808 if (textclasslist.Style(current_view->buffer()->params.textclass,
3809 par->layout).isParagraph()
3811 && !suffixIs(file, "\n\n")) {
3812 // There should be at least one '\n' already
3813 // but we need there to be two for Standard
3814 // paragraphs that are depth-increment'ed to be
3815 // output correctly. However, tables can
3816 // also be paragraphs so don't adjust them.
3821 par = par->TeXDeeper(file, texrow,
3822 foot, foot_texrow, foot_count);
3824 if (par && par->layout == layout && par->depth == depth &&
3825 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3826 if (par->pextra_hfill && par->Previous() &&
3827 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3828 file += "\\hfill{}\n";
3831 if (par_sep == BufferParams::PARSEP_INDENT) {
3832 file += "{\\setlength\\parindent{0pt}\n";
3835 file += "\\begin{minipage}";
3836 switch(par->pextra_alignment) {
3837 case MINIPAGE_ALIGN_TOP:
3840 case MINIPAGE_ALIGN_MIDDLE:
3843 case MINIPAGE_ALIGN_BOTTOM:
3847 if (!par->pextra_width.empty()) {
3849 file += par->pextra_width;
3852 //float ib = atof(par->pextra_widthp.c_str())/100;
3853 // string can't handle floats at present
3854 // so I'll do a conversion by hand knowing that
3855 // the limits are 0.0 to 1.0. ARRae.
3857 switch (par->pextra_widthp.length()) {
3863 file += par->pextra_widthp;
3867 file += par->pextra_widthp;
3869 file += "\\columnwidth}\n";
3872 if (par_sep == BufferParams::PARSEP_INDENT) {
3873 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3876 minipage_open = true;
3877 minipage_open_depth = par->depth;
3880 && par->layout == layout
3881 && par->depth == depth
3882 && par->pextra_type == pextra_type);
3884 if (style.isEnvironment()) {
3885 file += "\\end{" + style.latexname() + '}';
3886 // maybe this should go after the minipage closes?
3887 if (foot_this_level) {
3888 if (foot_count >= 1) {
3889 if (foot_count > 1) {
3890 file += "\\addtocounter{footnote}{-";
3891 file += tostr(foot_count - 1);
3895 texrow += foot_texrow;
3897 foot_texrow.reset();
3902 if (minipage_open && (minipage_open_depth == depth) &&
3903 (!par || par->pextra_start_minipage ||
3904 par->pextra_type != PEXTRA_MINIPAGE)) {
3905 file += "\\end{minipage}\n";
3907 if (par_sep == BufferParams::PARSEP_INDENT) {
3911 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3912 file += "\\medskip\n\n";
3916 minipage_open = false;
3919 file += "\\end{LyXParagraphIndent}\n";
3922 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
3923 && par->pextra_hfill)) {
3927 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3928 return par; // ale970302
3932 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
3933 string & foot, TexRow & foot_texrow,
3936 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3937 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3938 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3939 "No footnote!" << endl;
3941 LyXParagraph * par = this;
3942 LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass,
3943 previous->GetLayout());
3945 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3946 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3947 "Float other than footnote in command"
3948 " with moving argument is illegal" << endl;
3951 if (footnotekind != LyXParagraph::FOOTNOTE
3952 && footnotekind != LyXParagraph::MARGIN
3954 && !suffixIs(file, '\n')) {
3955 // we need to ensure that real floats like tables and figures
3956 // have their \begin{} on a new line otherwise we can get
3957 // incorrect results when using the endfloat.sty package
3958 // especially if two floats follow one another. ARRae 981022
3959 // NOTE: if the file is length 0 it must have just been
3960 // written out so we assume it ended with a '\n'
3965 BufferParams * params = ¤t_view->buffer()->params;
3966 bool footer_in_body = true;
3967 switch (footnotekind) {
3968 case LyXParagraph::FOOTNOTE:
3969 if (style.intitle) {
3970 file += "\\thanks{\n";
3971 footer_in_body = false;
3973 if (foot_count == -1) {
3974 // we're at depth 0 so we can use:
3975 file += "\\footnote{%\n";
3976 footer_in_body = false;
3978 file += "\\footnotemark{}%\n";
3980 // we only need this when there are
3981 // multiple footnotes
3982 foot += "\\stepcounter{footnote}";
3984 foot += "\\footnotetext{%\n";
3985 foot_texrow.start(this, 0);
3986 foot_texrow.newline();
3991 case LyXParagraph::MARGIN:
3992 file += "\\marginpar{\n";
3994 case LyXParagraph::FIG:
3995 if (pextra_type == PEXTRA_FLOATFLT
3996 && (!pextra_width.empty()
3997 || !pextra_widthp.empty())) {
3999 if (!pextra_width.empty())
4000 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
4001 pextra_width.c_str());
4004 "\\begin{floatingfigure}{%f\\textwidth}\n",
4005 atoi(pextra_widthp.c_str())/100.0);
4008 file += "\\begin{figure}";
4009 if (!params->float_placement.empty()) {
4011 file += params->float_placement;
4018 case LyXParagraph::TAB:
4019 file += "\\begin{table}";
4020 if (!params->float_placement.empty()) {
4022 file += params->float_placement;
4028 case LyXParagraph::WIDE_FIG:
4029 file += "\\begin{figure*}";
4030 if (!params->float_placement.empty()) {
4032 file += params->float_placement;
4038 case LyXParagraph::WIDE_TAB:
4039 file += "\\begin{table*}";
4040 if (!params->float_placement.empty()) {
4042 file += params->float_placement;
4048 case LyXParagraph::ALGORITHM:
4049 file += "\\begin{algorithm}\n";
4054 if (footnotekind != LyXParagraph::FOOTNOTE
4055 || !footer_in_body) {
4056 // Process text for all floats except footnotes in body
4058 LyXLayout const & style =
4059 textclasslist.Style(current_view->buffer()->params.textclass,
4062 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4064 if (style.isEnvironment()
4065 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4066 // Allows the use of minipages within float
4067 // environments. Shouldn't be circular because
4068 // we don't support footnotes inside
4069 // floats (yet). ARRae
4070 par = par->TeXEnvironment(file, texrow,
4074 par = par->TeXOnePar(file, texrow,
4079 if (par && !par->IsDummy() && par->depth > depth) {
4080 par = par->TeXDeeper(file, texrow,
4084 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4086 // process footnotes > depth 0 or in environments separately
4087 // NOTE: Currently don't support footnotes within footnotes
4088 // even though that is possible using the \footnotemark
4090 TexRow dummy_texrow;
4091 int dummy_count = 0;
4093 LyXLayout const & style =
4094 textclasslist.Style(current_view->buffer()->params.textclass,
4097 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4099 if (style.isEnvironment()
4100 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4101 // Allows the use of minipages within float
4102 // environments. Shouldn't be circular because
4103 // we don't support footnotes inside
4104 // floats (yet). ARRae
4105 par = par->TeXEnvironment(foot, foot_texrow,
4106 dummy, dummy_texrow,
4109 par = par->TeXOnePar(foot, foot_texrow,
4110 dummy, dummy_texrow,
4114 if (par && !par->IsDummy() && par->depth > depth) {
4115 par = par->TeXDeeper(foot, foot_texrow,
4116 dummy, dummy_texrow,
4120 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4122 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4123 "Footnote in a Footnote -- not supported"
4128 switch (footnotekind) {
4129 case LyXParagraph::FOOTNOTE:
4130 if (footer_in_body) {
4131 // This helps tell which of the multiple
4132 // footnotetexts an error was in.
4134 foot_texrow.newline();
4139 case LyXParagraph::MARGIN:
4142 case LyXParagraph::FIG:
4143 if (pextra_type == PEXTRA_FLOATFLT
4144 && (!pextra_width.empty()
4145 || !pextra_widthp.empty()))
4146 file += "\\end{floatingfigure}";
4148 file += "\\end{figure}";
4150 case LyXParagraph::TAB:
4151 file += "\\end{table}";
4153 case LyXParagraph::WIDE_FIG:
4154 file += "\\end{figure*}";
4156 case LyXParagraph::WIDE_TAB:
4157 file += "\\end{table*}";
4159 case LyXParagraph::ALGORITHM:
4160 file += "\\end{algorithm}";
4164 if (footnotekind != LyXParagraph::FOOTNOTE
4165 && footnotekind != LyXParagraph::MARGIN) {
4166 // we need to ensure that real floats like tables and figures
4167 // have their \end{} on a line of their own otherwise we can
4168 // get incorrect results when using the endfloat.sty package.
4173 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4178 void LyXParagraph::SetPExtraType(int type, char const * width,
4179 char const * widthp)
4182 pextra_width = width;
4183 pextra_widthp = widthp;
4185 if (textclasslist.Style(current_view->buffer()->params.textclass,
4186 layout).isEnvironment()) {
4191 while (par && (par->layout == layout)
4192 && (par->depth == depth)) {
4194 par = par->Previous();
4196 par = par->FirstPhysicalPar();
4197 while (par && par->depth > depth) {
4198 par = par->Previous();
4200 par = par->FirstPhysicalPar();
4204 while (par && (par->layout == layout)
4205 && (par->depth == depth)) {
4206 par->pextra_type = type;
4207 par->pextra_width = width;
4208 par->pextra_widthp = widthp;
4209 par = par->NextAfterFootnote();
4210 if (par && (par->depth > depth))
4211 par->SetPExtraType(type, width, widthp);
4212 while (par && ((par->depth > depth) || par->IsDummy()))
4213 par = par->NextAfterFootnote();
4219 void LyXParagraph::UnsetPExtraType()
4221 if (pextra_type == PEXTRA_NONE)
4224 pextra_type = PEXTRA_NONE;
4225 pextra_width.clear();
4226 pextra_widthp.clear();
4228 if (textclasslist.Style(current_view->buffer()->params.textclass,
4229 layout).isEnvironment()) {
4234 while (par && (par->layout == layout)
4235 && (par->depth == depth)) {
4237 par = par->Previous();
4239 par = par->FirstPhysicalPar();
4240 while (par && par->depth > depth) {
4241 par = par->Previous();
4243 par = par->FirstPhysicalPar();
4247 while (par && (par->layout == layout)
4248 && (par->depth == depth)) {
4249 par->pextra_type = PEXTRA_NONE;
4250 par->pextra_width.clear();
4251 par->pextra_widthp.clear();
4252 par = par->NextAfterFootnote();
4253 if (par && (par->depth > depth))
4254 par->UnsetPExtraType();
4255 while (par && ((par->depth > depth) || par->IsDummy()))
4256 par = par->NextAfterFootnote();
4262 bool LyXParagraph::IsHfill(size_type pos) const
4264 return IsHfillChar(GetChar(pos));
4268 bool LyXParagraph::IsInset(size_type pos) const
4270 return IsInsetChar(GetChar(pos));
4274 bool LyXParagraph::IsFloat(size_type pos) const
4276 return IsFloatChar(GetChar(pos));
4280 bool LyXParagraph::IsNewline(size_type pos) const
4284 tmp = IsNewlineChar(GetChar(pos));
4289 bool LyXParagraph::IsSeparator(size_type pos) const
4291 return IsSeparatorChar(GetChar(pos));
4295 bool LyXParagraph::IsLineSeparator(size_type pos) const
4297 return IsLineSeparatorChar(GetChar(pos));
4301 bool LyXParagraph::IsKomma(size_type pos) const
4303 return IsKommaChar(GetChar(pos));
4307 /// Used by the spellchecker
4308 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4310 unsigned char c = GetChar(pos);
4311 if (IsLetterChar(c))
4313 // '\0' is not a letter, allthough every string contains "" (below)
4316 // We want to pass the ' and escape chars to ispell
4317 string extra = lyxrc->isp_esc_chars + '\'';
4321 return contains(extra, ch);
4325 bool LyXParagraph::IsWord(size_type pos ) const
4327 return IsWordChar(GetChar(pos)) ;