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]
146 os << "\n\\end_float ";
150 // The beginning or end of a deeper (i.e. nested) area?
153 while (depth > dth) {
154 os << "\n\\begin_deeper ";
158 while (depth < dth) {
159 os << "\n\\end_deeper ";
165 // First write the layout
167 << textclasslist.NameOfLayout(params.textclass, layout)
170 // Maybe some vertical spaces.
171 if (added_space_top.kind() != VSpace::NONE)
172 os << "\\added_space_top "
173 << added_space_top.asLyXCommand() << " ";
174 if (added_space_bottom.kind() != VSpace::NONE)
175 os << "\\added_space_bottom "
176 << added_space_bottom.asLyXCommand() << " ";
178 // The labelwidth string used in lists.
179 if (!labelwidthstring.empty())
180 os << "\\labelwidthstring "
181 << labelwidthstring << '\n';
183 // Lines above or below?
187 os << "\\line_bottom ";
189 // Pagebreaks above or below?
191 os << "\\pagebreak_top ";
192 if (pagebreak_bottom)
193 os << "\\pagebreak_bottom ";
195 // Start of appendix?
196 if (start_of_appendix)
197 os << "\\start_of_appendix ";
204 if (align != LYX_ALIGN_LAYOUT) {
206 case LYX_ALIGN_LEFT: h = 1; break;
207 case LYX_ALIGN_RIGHT: h = 2; break;
208 case LYX_ALIGN_CENTER: h = 3; break;
209 default: h = 0; break;
211 os << "\\align " << string_align[h] << " ";
213 if (pextra_type != PEXTRA_NONE) {
214 os << "\\pextra_type " << pextra_type;
215 if (pextra_type == PEXTRA_MINIPAGE) {
216 os << " \\pextra_alignment "
219 os << " \\pextra_hfill "
221 if (pextra_start_minipage)
222 os << " \\pextra_start_minipage "
223 << pextra_start_minipage;
225 if (!pextra_width.empty()) {
226 os << " \\pextra_width "
227 << VSpace(pextra_width).asLyXCommand();
228 } else if (!pextra_widthp.empty()) {
229 os << " \\pextra_widthp "
235 // Dummy layout. This means that a footnote ended.
236 os << "\n\\end_float ";
237 footflag = LyXParagraph::NO_FOOTNOTE;
240 // It might be a table.
242 os << "\\LyXTable\n";
250 font1 = LyXFont(LyXFont::ALL_INHERIT);
253 for (size_type i = 0; i < size(); ++i) {
259 // Write font changes
260 font2 = GetFontSettings(i);
261 if (font2 != font1) {
262 font2.lyxWriteChanges(font1, os);
272 if (inset->DirectWrite()) {
273 // international char, let it write
274 // code directly so it's shorter in
278 os << "\n\\begin_inset ";
280 os << "\n\\end_inset \n\n";
285 os << "\n\\newline \n";
289 os << "\n\\hfill \n";
292 case META_PROTECTED_SEPARATOR:
293 os << "\n\\protected_separator \n";
297 os << "\n\\backslash \n";
301 if (i + 1 < size() && GetChar(i + 1) == ' ') {
308 if ((column > 70 && c == ' ')
313 // this check is to amend a bug. LyX sometimes
314 // inserts '\0' this could cause problems.
318 lyxerr << "ERROR (LyXParagraph::writeFile):"
319 " NULL char in structure." << endl;
325 // now write the next paragraph
327 next->writeFile(os, params, footflag, dth);
331 void LyXParagraph::validate(LaTeXFeatures & features)
333 // this will be useful later
334 LyXLayout const & layout =
335 textclasslist.Style(current_view->buffer()->params.textclass,
339 if (line_top || line_bottom)
340 features.lyxline = true;
343 features.layout[GetLayout()] = true;
346 #ifdef NEW_FONTTABLE // OK, but does not affect structure anyway
347 for (FontList::const_iterator cit = fontlist.begin();
348 cit != fontlist.end(); ++cit) {
349 if ((*cit).font.noun() == LyXFont::ON) {
350 lyxerr[Debug::LATEX] << "font.noun: "
351 << (*cit).font.noun()
353 features.noun = true;
354 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
355 << (*cit).font.stateText()
358 switch ((*cit).font.color()) {
360 case LyXFont::INHERIT_COLOR:
361 case LyXFont::IGNORE_COLOR:
364 features.color = true;
365 lyxerr[Debug::LATEX] << "Color enabled. Font: "
366 << (*cit).font.stateText()
371 FontTable * tmpfonttable = fonttable;
372 while (tmpfonttable) {
373 if (tmpfonttable->font.noun() == LyXFont::ON) {
374 lyxerr[Debug::LATEX] << "font.noun: "
375 << tmpfonttable->font.noun()
377 features.noun = true;
378 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
379 << tmpfonttable->font.stateText()
382 switch (tmpfonttable->font.color()) {
384 case LyXFont::INHERIT_COLOR:
385 case LyXFont::IGNORE_COLOR:
388 features.color = true;
389 lyxerr[Debug::LATEX] << "Color enabled. Font: "
390 << tmpfonttable->font.stateText()
393 tmpfonttable = tmpfonttable->next;
397 #ifdef NEW_INSETTABLE
398 for (InsetList::const_iterator cit = insetlist.begin();
399 cit != insetlist.end(); ++cit) {
401 (*cit).inset->Validate(features);
404 InsetTable * tmpinsettable = insettable;
405 while (tmpinsettable) {
406 if (tmpinsettable->inset) {
407 tmpinsettable->inset->Validate(features);
409 tmpinsettable = tmpinsettable->next;
413 if (table && table->IsLongTable())
414 features.longtable = true;
415 if (pextra_type == PEXTRA_INDENT)
416 features.LyXParagraphIndent = true;
417 if (pextra_type == PEXTRA_FLOATFLT)
418 features.floatflt = true;
419 if (layout.needprotect
420 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
421 features.NeedLyXFootnoteCode = true;
422 if ((current_view->buffer()->params.paragraph_separation == BufferParams::PARSEP_INDENT) &&
423 (pextra_type == LyXParagraph::PEXTRA_MINIPAGE))
424 features.NeedLyXMinipageIndent = true;
425 if (table && table->NeedRotating())
426 features.rotating = true;
427 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
428 features.algorithm = true;
432 // First few functions needed for cut and paste and paragraph breaking.
433 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos) const
435 minibuffer_char = GetChar(pos);
436 minibuffer_font = GetFontSettings(pos);
437 minibuffer_inset = 0;
438 if (minibuffer_char == LyXParagraph::META_INSET) {
440 minibuffer_inset = GetInset(pos)->Clone();
442 minibuffer_inset = 0;
443 minibuffer_char = ' ';
444 // This reflects what GetInset() does (ARRae)
450 void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos)
452 minibuffer_char = GetChar(pos);
453 minibuffer_font = GetFontSettings(pos);
454 minibuffer_inset = 0;
455 if (minibuffer_char == LyXParagraph::META_INSET) {
457 minibuffer_inset = GetInset(pos);
458 // This is a little hack since I want exactly
459 // the inset, not just a clone. Otherwise
460 // the inset would be deleted when calling Erase(pos)
462 #ifdef NEW_INSETTABLE
463 for (InsetList::iterator it = insetlist.begin();
464 it != insetlist.end(); ++it) {
465 if ((*it).pos == pos) {
472 InsetTable * tmpi = insettable;
473 while (tmpi && tmpi->pos != pos) {
476 if (tmpi) { // This should always be true.
481 minibuffer_inset = 0;
482 minibuffer_char = ' ';
483 // This reflects what GetInset() does (ARRae)
488 // Erase(pos); now the caller is responsible for that.
492 void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
494 InsertChar(pos, minibuffer_char);
495 SetFont(pos, minibuffer_font);
496 if (minibuffer_char == LyXParagraph::META_INSET)
497 InsertInset(pos, minibuffer_inset);
504 void LyXParagraph::Clear()
509 pagebreak_top = false;
510 pagebreak_bottom = false;
512 added_space_top = VSpace(VSpace::NONE);
513 added_space_bottom = VSpace(VSpace::NONE);
515 align = LYX_ALIGN_LAYOUT;
519 pextra_type = PEXTRA_NONE;
520 pextra_width.clear();
521 pextra_widthp.clear();
522 pextra_alignment = MINIPAGE_ALIGN_TOP;
523 pextra_hfill = false;
524 pextra_start_minipage = false;
527 labelwidthstring.clear();
531 start_of_appendix = false;
535 // the destructor removes the new paragraph from the list
536 LyXParagraph::~LyXParagraph()
539 previous->next = next;
541 next->previous = previous;
543 #ifdef NEW_INSETTABLE
544 for (InsetList::iterator it = insetlist.begin();
545 it != insetlist.end(); ++it) {
549 InsetTable * tmpinset;
551 tmpinset = insettable;
552 insettable = insettable->next;
553 if (tmpinset->inset) // DEL LINE
554 delete tmpinset->inset;
556 if (insettable && insettable->next == insettable) {
557 // somehow this recursion appears occasionally
558 // but I can't find where. This bandaid
559 // helps but isn't the best fix. (ARRae)
560 if (insettable->inset) { // DEL LINE
561 delete insettable->inset;
568 #ifndef NEW_FONTTABLE // OK
572 fonttable = fonttable->next;
577 /* table stuff -- begin*/
578 if (table) // DEL LINE
580 /* table stuff -- end*/
583 if (bibkey) // DEL LINE
588 void LyXParagraph::Erase(LyXParagraph::size_type pos)
590 // > because last is the next unused position, and you can
591 // use it if you want
593 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
594 NextAfterFootnote()->Erase(pos - text.size() - 1);
596 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
597 "position does not exist." << endl;
600 if (pos < size()) { // last is free for insertation, but should be empty
601 // if it is an inset, delete the inset entry
602 if (text[pos] == LyXParagraph::META_INSET) {
604 #ifdef NEW_INSETTABLE
605 for (InsetList::iterator it = insetlist.begin();
606 it != insetlist.end(); ++it) {
607 if ((*it).pos == pos) {
614 InsetTable *tmpi = insettable;
615 InsetTable *tmpi2 = tmpi;
616 while (tmpi && tmpi->pos != pos) {
620 if (tmpi) { // this should always be true
621 if (tmpi->inset) // delete the inset if it exists // DEL LINE
623 if (tmpi == insettable)
624 insettable = tmpi->next;
626 tmpi2->next = tmpi->next;
631 text.erase(text.begin() + pos);
632 // Erase entries in the tables.
633 #ifdef NEW_FONTTABLE // Seems OK
634 for (FontList::iterator it = fontlist.begin();
635 it != fontlist.end(); ++it) {
636 if (pos >= (*it).pos && pos <= (*it).pos_end) {
637 if ((*it).pos == (*it).pos_end) {
638 // If it is a multi-character font
639 // entry, we just make it smaller
640 // (see update below), otherwise we
647 // Update all other entries.
648 for (FontList::iterator it = fontlist.begin();
649 it != fontlist.end(); ++it) {
652 if ((*it).pos_end >= pos)
657 FontTable * tmp = fonttable;
658 FontTable * prev = 0;
659 while (tmp && !found) {
660 if (pos >= tmp->pos && pos <= tmp->pos_end)
668 if (found && tmp->pos == tmp->pos_end) {
669 // if it is a multi-character font entry, we just make
670 // it smaller (see update below), otherwise we should
673 prev->next = tmp->next;
675 fonttable = tmp->next;
680 // Update all other entries.
686 if (tmp->pos_end >= pos)
691 // Update the inset table.
692 #ifdef NEW_INSETTABLE
693 for (InsetList::iterator it = insetlist.begin();
694 it != insetlist.end(); ++it) {
699 InsetTable * tmpi = insettable;
707 lyxerr << "ERROR (LyXParagraph::Erase): "
708 "can't erase non-existant char." << endl;
713 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
715 // > because last is the next unused position, and you can
716 // use it if you want
719 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
720 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
723 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
724 "position does not exist." << endl;
727 text.insert(text.begin() + pos, c);
728 // Update the font table.
729 #ifdef NEW_FONTTABLE // Seems OK
730 for (FontList::iterator it = fontlist.begin();
731 it != fontlist.end(); ++it) {
732 if ((*it).pos >= pos)
734 if ((*it).pos_end >= pos)
738 FontTable * tmp = fonttable;
742 if (tmp->pos_end >= pos)
748 // Update the inset table.
749 #ifdef NEW_INSETTABLE
750 for (InsetList::iterator it = insetlist.begin();
751 it != insetlist.end(); ++it) {
752 if ((*it).pos >= pos)
756 InsetTable * tmpi = insettable;
758 if (tmpi->pos >= pos)
766 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
769 // > because last is the next unused position, and you can
770 // use it if you want
773 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
775 ->InsertInset(pos - text.size() - 1, inset);
777 lyxerr << "ERROR (LyXParagraph::InsertInset): "
778 "position does not exist: " << pos << endl;
781 if (text[pos] != LyXParagraph::META_INSET) {
782 lyxerr << "ERROR (LyXParagraph::InsertInset): "
783 "there is no LyXParagraph::META_INSET" << endl;
788 // Add a new entry in the inset table.
789 #ifdef NEW_INSETTABLE
791 InsetList::iterator it =
792 insetlist.insert(insetlist.begin(), tmpi);
796 InsetTable * tmpi = new InsetTable;
799 tmpi->next = insettable;
806 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
810 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
811 return NextAfterFootnote()
812 ->GetInset(pos - text.size() - 1);
814 lyxerr << "ERROR (LyXParagraph::GetInset): "
815 "position does not exist: "
821 #ifdef NEW_INSETTABLE
822 for (InsetList::iterator it = insetlist.begin();
823 it != insetlist.end(); ++it) {
824 if ((*it).pos == pos) {
828 lyxerr << "ERROR (LyXParagraph::GetInset): "
829 "Inset does not exist: " << pos << endl;
830 text[pos] = ' '; // WHY!!! does this set the pos to ' '????
831 // Did this commenting out introduce a bug? So far I have not
832 // see any, please enlighten me. (Lgb)
833 // My guess is that since the inset does not exist, we might
834 // as well replace it with a space to prevent craches. (Asger)
837 InsetTable * tmpi = insettable;
839 while (tmpi && tmpi->pos != pos)
845 lyxerr << "ERROR (LyXParagraph::GetInset): "
846 "Inset does not exist: " << pos << endl;
847 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
848 // Did this commenting out introduce a bug? So far I have not
849 // seen any, please enlighten me. (Lgb)
850 // My guess is that since the inset does not exist, we might
851 // as well replace it with a space to prevent crashes. (Asger)
858 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
862 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
863 return NextAfterFootnote()
864 ->GetInset(pos - text.size() - 1);
866 lyxerr << "ERROR (LyXParagraph::GetInset): "
867 "position does not exist: "
873 #ifdef NEW_INSETTABLE
874 for (InsetList::const_iterator cit = insetlist.begin();
875 cit != insetlist.end(); ++cit) {
876 if ((*cit).pos == pos) {
880 lyxerr << "ERROR (LyXParagraph::GetInset): "
881 "Inset does not exist: " << pos << endl;
882 //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
883 // Did this commenting out introduce a bug? So far I have not
884 // see any, please enlighten me. (Lgb)
885 // My guess is that since the inset does not exist, we might
886 // as well replace it with a space to prevent craches. (Asger)
889 InsetTable * tmpi = insettable;
891 while (tmpi && tmpi->pos != pos)
897 lyxerr << "ERROR (LyXParagraph::GetInset): "
898 "Inset does not exist: " << pos << endl;
899 // in the const version we need to comment it out anyway...
900 //text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
901 // Did this commenting out introduce a bug? So far I have not
902 // seen any, please enlighten me. (Lgb)
903 // My guess is that since the inset does not exist, we might
904 // as well replace it with a space to prevent crashes. (Asger)
911 // Gets uninstantiated font setting at position.
912 // Optimized after profiling. (Asger)
913 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos) const
916 #ifdef NEW_FONTTABLE // Seems OK
917 for (FontList::const_iterator cit = fontlist.begin();
918 cit != fontlist.end(); ++cit) {
919 if (pos >= (*cit).pos && pos <= (*cit).pos_end)
923 FontTable * tmp = fonttable;
925 if (pos >= tmp->pos && pos <= tmp->pos_end)
931 // > because last is the next unused position, and you can
932 // use it if you want
933 else if (pos > size()) {
935 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
936 return NextAfterFootnote()
937 ->GetFontSettings(pos - text.size() - 1);
939 // Why is it an error to ask for the font of a
940 // position that does not exist? Would it be
941 // enough for this to be enabled on debug?
942 // We want strict error checking, but it's ok to only
943 // have it when debugging. (Asger)
944 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
945 "position does not exist. "
946 << pos << " (" << static_cast<int>(pos)
950 return GetFontSettings(pos - 1);
952 return LyXFont(LyXFont::ALL_INHERIT);
956 // Gets the fully instantiated font at a given position in a paragraph
957 // This is basically the same function as LyXText::GetFont() in text2.C.
958 // The difference is that this one is used for generating the LaTeX file,
959 // and thus cosmetic "improvements" are disallowed: This has to deliver
960 // the true picture of the buffer. (Asger)
961 // If position is -1, we get the layout font of the paragraph.
962 // If position is -2, we get the font of the manual label of the paragraph.
963 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos) const
966 LyXLayout const & layout =
967 textclasslist.Style(current_view->buffer()->params.textclass,
969 LyXParagraph::size_type main_body = 0;
970 if (layout.labeltype == LABEL_MANUAL)
971 main_body = BeginningOfMainBody();
976 layoutfont = layout.labelfont;
978 layoutfont = layout.font;
979 tmpfont = GetFontSettings(pos);
980 tmpfont.realize(layoutfont);
982 // process layoutfont for pos == -1 and labelfont for pos < -1
984 tmpfont = layout.font;
986 tmpfont = layout.labelfont;
989 // check for environment font information
990 char par_depth = GetDepth();
991 LyXParagraph const * par = this;
992 while (par && par_depth && !tmpfont.resolved()) {
993 par = par->DepthHook(par_depth - 1);
995 tmpfont.realize(textclasslist.
996 Style(current_view->buffer()->params.textclass,
997 par->GetLayout()).font);
998 par_depth = par->GetDepth();
1002 tmpfont.realize(textclasslist
1003 .TextClass(current_view->buffer()->params.textclass)
1009 /// Returns the height of the highest font in range
1011 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
1012 LyXParagraph::size_type endpos) const
1014 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
1015 #ifdef NEW_FONTTABLE // Seems OK
1016 for (FontList::const_iterator cit = fontlist.begin();
1017 cit != fontlist.end(); ++cit) {
1018 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
1019 LyXFont::FONT_SIZE size = (*cit).font.size();
1020 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
1025 FontTable * tmp = fonttable;
1027 if (startpos <= tmp->pos_end && endpos >= tmp->pos) {
1028 LyXFont::FONT_SIZE size = tmp->font.size();
1029 if (size > maxsize && size<= LyXFont::SIZE_HUGER)
1039 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
1046 // > because last is the next unused position, and you can
1047 // use it if you want
1048 else if (pos > size()) {
1049 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1050 return NextAfterFootnote()
1051 ->GetChar(pos - text.size() - 1);
1053 lyxerr << "ERROR (LyXParagraph::GetChar): "
1054 "position does not exist."
1055 << pos << " (" << static_cast<int>(pos)
1061 // We should have a footnote environment.
1062 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
1063 // Notice that LyX does request the
1064 // last char from time to time. (Asger)
1065 //lyxerr << "ERROR (LyXParagraph::GetChar): "
1066 // "expected footnote." << endl;
1069 switch (next->footnotekind) {
1070 case LyXParagraph::FOOTNOTE:
1071 return LyXParagraph::META_FOOTNOTE;
1072 case LyXParagraph::MARGIN:
1073 return LyXParagraph::META_MARGIN;
1074 case LyXParagraph::FIG:
1075 case LyXParagraph::WIDE_FIG:
1076 return LyXParagraph::META_FIG;
1077 case LyXParagraph::TAB:
1078 case LyXParagraph::WIDE_TAB:
1079 return LyXParagraph::META_TAB;
1080 case LyXParagraph::ALGORITHM:
1081 return LyXParagraph::META_ALGORITHM;
1083 return '\0'; // to shut up gcc
1088 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
1095 // > because last is the next unused position, and you can
1096 // use it if you want
1097 else if (pos > size()) {
1098 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1099 return NextAfterFootnote()
1100 ->GetChar(pos - text.size() - 1);
1102 lyxerr << "ERROR (LyXParagraph::GetChar const): "
1103 "position does not exist."
1104 << pos << " (" << static_cast<int>(pos)
1110 // We should have a footnote environment.
1111 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
1112 // Notice that LyX does request the
1113 // last char from time to time. (Asger)
1114 //lyxerr << "ERROR (LyXParagraph::GetChar): "
1115 // "expected footnote." << endl;
1118 switch (next->footnotekind) {
1119 case LyXParagraph::FOOTNOTE:
1120 return LyXParagraph::META_FOOTNOTE;
1121 case LyXParagraph::MARGIN:
1122 return LyXParagraph::META_MARGIN;
1123 case LyXParagraph::FIG:
1124 case LyXParagraph::WIDE_FIG:
1125 return LyXParagraph::META_FIG;
1126 case LyXParagraph::TAB:
1127 case LyXParagraph::WIDE_TAB:
1128 return LyXParagraph::META_TAB;
1129 case LyXParagraph::ALGORITHM:
1130 return LyXParagraph::META_ALGORITHM;
1132 return '\0'; // to shut up gcc
1137 // return an string of the current word, and the end of the word in lastpos.
1138 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
1142 // the current word is defined as starting at the first character
1143 // from the immediate left of lastpospos which meets the definition
1144 // of IsLetter(), continuing to the last character to the right
1145 // of this meeting IsLetter.
1151 // move back until we have a letter
1153 //there's no real reason to have firstpos & lastpos as
1154 //separate variables as this is written, but maybe someon
1155 // will want to return firstpos in the future.
1157 //since someone might have typed a punctuation first
1158 int firstpos = lastpos;
1160 while ((firstpos >= 0) && !IsLetter(firstpos))
1163 // now find the beginning by looking for a nonletter
1165 while ((firstpos>= 0) && IsLetter(firstpos))
1168 // the above is now pointing to the preceeding non-letter
1172 // so copy characters into theword until we get a nonletter
1173 // note that this can easily exceed lastpos, wich means
1174 // that if used in the middle of a word, the whole word
1177 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1184 LyXParagraph::size_type LyXParagraph::Last() const
1186 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1187 return text.size() + NextAfterFootnote()->Last() + 1;
1188 // the 1 is the symbol
1195 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
1197 // > because last is the next unused position, and you can
1198 // use it if you want
1201 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1202 return NextAfterFootnote()
1203 ->ParFromPos(pos - text.size() - 1);
1205 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1206 "position does not exist." << endl;
1213 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
1215 // > because last is the next unused position, and you can
1216 // use it if you want
1219 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1220 return NextAfterFootnote()
1221 ->PositionInParFromPos(pos - text.size() - 1);
1224 "ERROR (LyXParagraph::PositionInParFromPos): "
1225 "position does not exist." << endl;
1233 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1234 LyXFont const & font)
1236 // > because last is the next unused position, and you can
1237 // use it if you want
1240 next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1241 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1244 lyxerr << "ERROR (LyXParagraph::SetFont): "
1245 "position does not exist." << endl;
1249 LyXFont patternfont(LyXFont::ALL_INHERIT);
1251 // First, reduce font against layout/label font
1252 // Update: The SetCharFont() routine in text2.C already
1253 // reduces font, so we don't need to do that here. (Asger)
1254 // No need to simplify this because it will disappear
1255 // in a new kernel. (Asger)
1256 // Next search font table
1257 #ifdef NEW_FONTTABLE
1258 FontList::iterator tmp = fontlist.begin();
1259 for (; tmp != fontlist.end(); ++tmp) {
1260 if (pos >= (*tmp).pos && pos <= (*tmp).pos_end) {
1264 if (tmp == fontlist.end()) { // !found
1265 // if we did not find a font entry, but if the font at hand
1266 // is the same as default, we just forget it
1267 if (font == patternfont) return;
1269 // ok, we did not find a font entry. But maybe there is exactly
1270 // the needed font ientry one position left
1271 FontList::iterator tmp2 = fontlist.begin();
1272 for (; tmp2 != fontlist.end(); ++tmp2) {
1273 if (pos - 1 >= (*tmp2).pos
1274 && pos - 1 <= (*tmp2).pos_end)
1277 if (tmp2 != fontlist.end()) {
1278 // ok there is one, maybe it is exactly
1280 if ((*tmp2).font == font) {
1281 // put the position under the font
1286 // Add a new entry in the
1287 // fontlist for the position
1291 ft.font = font; // or patternfont
1292 // It seems that using font instead of patternfont here
1293 // fixes all the problems. This also surfaces a "bug" in
1295 fontlist.insert(fontlist.begin(), ft);
1296 } else if ((*tmp).pos != (*tmp).pos_end) { // we found a font entry. maybe we have to split it and create a new one.
1298 // more than one character
1299 if (pos == (*tmp).pos) {
1300 // maybe we should enlarge the left fonttable
1301 FontList::iterator tmp2 = fontlist.begin();
1302 for (; tmp2 != fontlist.end(); ++tmp2) {
1303 if (pos - 1 >= (*tmp2).pos
1304 && pos - 1 <= (*tmp2).pos_end)
1307 // Is there is one, and is it exactly
1309 if (tmp2 != fontlist.end() &&
1310 (*tmp2).font == font) {
1311 // Put the position under the font
1317 // Add a new entry in the
1318 // fontlist for the position
1321 ft.pos_end = (*tmp).pos_end;
1322 ft.font = (*tmp).font;
1323 (*tmp).pos_end = pos;
1325 fontlist.insert(fontlist.begin(), ft);
1326 } else if (pos == (*tmp).pos_end) {
1327 // Add a new entry in the
1328 // fontlist for the position
1330 ft.pos = (*tmp).pos;
1331 ft.pos_end = (*tmp).pos_end - 1;
1332 ft.font = (*tmp).font;
1333 (*tmp).pos = (*tmp).pos_end;
1335 fontlist.insert(fontlist.begin(), ft);
1337 // Add a new entry in the
1338 // fontlist for the position
1340 ft.pos = (*tmp).pos;
1341 ft.pos_end = pos - 1;
1342 ft.font = (*tmp).font;
1346 ft2.pos_end = (*tmp).pos_end;
1347 ft2.font = (*tmp).font;
1350 (*tmp).pos_end = pos;
1353 fontlist.insert(fontlist.begin(), ft);
1354 fontlist.insert(fontlist.begin(), ft2);
1364 FontTable * tmp = fonttable;
1365 while (tmp && !found) {
1366 if (pos >= tmp->pos && pos <= tmp->pos_end)
1373 // if we did not find a font entry, but if the font at hand
1374 // is the same as default, we just forget it
1375 if (font == patternfont)
1378 // ok, we did not find a font entry. But maybe there is exactly
1379 // the needed font entry one position left
1382 while (tmp2 && !found) {
1383 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1389 // ok there is one. maybe it is exactly
1391 if (tmp2->font == font) {
1392 // put the position under the font
1397 // Add a new entry in the
1398 // fonttable for the position
1399 tmp = new FontTable;
1402 tmp->font = patternfont; // It seems that is actually totally
1403 // wrong to use patternfont here, the correct should be font
1404 // lockily at the end of this function we have
1405 // tmp->font = font, so this one setting it to patternfont
1407 tmp->next = fonttable;
1410 // we found a font entry. maybe we have
1411 // to split it and create a new one
1413 if (tmp->pos != tmp->pos_end) { // more than one character
1414 if (pos == tmp->pos) {
1415 // maybe we could enlarge the left fonttable
1418 while (tmp2 && !found) {
1419 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1425 // Is there is one, and is it exactly
1427 if (found && tmp2->font == font) {
1428 // Put the position under the font
1434 // Add a new entry in the
1435 // fonttable for the position
1436 tmp2 = new FontTable;
1437 tmp2->pos = pos + 1;
1438 tmp2->pos_end = tmp->pos_end;
1439 tmp2->font = tmp->font;
1441 tmp2->next = fonttable;
1444 else if (pos == tmp->pos_end) {
1445 // Add a new entry in the
1446 // fonttable for the position
1447 tmp2 = new FontTable;
1448 tmp2->pos = tmp->pos;
1449 tmp2->pos_end = tmp->pos_end - 1;
1450 tmp2->font = tmp->font;
1451 tmp->pos = tmp->pos_end;
1452 tmp2->next = fonttable;
1456 // Add a new entry in the
1457 // fonttable for the position
1458 tmp2 = new FontTable;
1459 tmp2->pos = tmp->pos;
1460 tmp2->pos_end = pos - 1;
1461 tmp2->font = tmp->font;
1462 tmp2->next = fonttable;
1465 tmp2 = new FontTable;
1466 tmp2->pos = pos + 1;
1467 tmp2->pos_end = tmp->pos_end;
1468 tmp2->font = tmp->font;
1469 tmp2->next = fonttable;
1482 // This function is able to hide closed footnotes.
1483 LyXParagraph * LyXParagraph::Next()
1485 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1486 LyXParagraph * tmp = next;
1488 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1490 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1491 return tmp->Next(); /* there can be more than one
1492 footnote in a logical
1495 return next; // This should never happen!
1501 LyXParagraph * LyXParagraph::NextAfterFootnote()
1503 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1504 LyXParagraph * tmp = next;
1505 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1507 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1508 return tmp; /* there can be more than one footnote
1509 in a logical paragraph */
1511 return next; // This should never happen!
1517 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1519 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1520 LyXParagraph * tmp = next;
1521 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1523 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1524 return tmp; /* there can be more than one footnote
1525 in a logical paragraph */
1527 return next; // This should never happen!
1533 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1536 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1538 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1539 tmp = tmp->previous;
1540 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1541 return tmp; /* there can be more than one footnote
1542 in a logical paragraph */
1544 return previous; // This should never happen!
1550 LyXParagraph * LyXParagraph::LastPhysicalPar()
1552 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1555 LyXParagraph * tmp = this;
1557 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1558 tmp = tmp->NextAfterFootnote();
1565 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1569 LyXParagraph * tmppar = this;
1573 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1574 tmppar = tmppar->previous;
1583 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1587 LyXParagraph const * tmppar = this;
1591 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1592 tmppar = tmppar->previous;
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();
1894 // ok, now copy the paragraph
1895 for (size_type i = 0; i <= pos_end; ++i) {
1896 the_next->CutIntoMinibuffer(i);
1897 InsertFromMinibuffer(pos_insert + i);
1900 // delete the next paragraph
1905 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1907 LyXParagraph * par = ParFromPos(pos);
1909 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1910 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1916 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1918 LyXParagraph * par = ParFromPos(pos);
1920 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1921 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1927 LyXTextClass::LayoutList::size_type LyXParagraph::GetLayout() const
1929 return FirstPhysicalPar()->layout;
1933 char LyXParagraph::GetDepth() const
1935 return FirstPhysicalPar()->depth;
1939 char LyXParagraph::GetAlign() const
1941 return FirstPhysicalPar()->align;
1945 string LyXParagraph::GetLabestring() const
1947 return FirstPhysicalPar()->labelstring;
1951 int LyXParagraph::GetFirstCounter(int i) const
1953 return FirstPhysicalPar()->counter_[i];
1957 // the next two functions are for the manual labels
1958 string LyXParagraph::GetLabelWidthString() const
1960 if (!FirstPhysicalPar()->labelwidthstring.empty())
1961 return FirstPhysicalPar()->labelwidthstring;
1963 return _("Senseless with this layout!");
1967 void LyXParagraph::SetLabelWidthString(string const & s)
1969 LyXParagraph * par = FirstPhysicalPar();
1971 par->labelwidthstring = s;
1975 void LyXParagraph::SetOnlyLayout(LyXTextClass::LayoutList::size_type new_layout)
1977 LyXParagraph * par = FirstPhysicalPar();
1978 LyXParagraph * ppar = 0;
1979 LyXParagraph * npar = 0;
1981 par->layout = new_layout;
1982 /* table stuff -- begin*/
1985 /* table stuff -- end*/
1986 if (par->pextra_type == PEXTRA_NONE) {
1987 if (par->Previous()) {
1988 ppar = par->Previous()->FirstPhysicalPar();
1991 && (ppar->depth > par->depth))
1992 ppar = ppar->Previous()->FirstPhysicalPar();
1995 npar = par->Next()->NextAfterFootnote();
1998 && (npar->depth > par->depth))
1999 npar = npar->Next()->NextAfterFootnote();
2001 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
2003 p1 = ppar->pextra_width,
2004 p2 = ppar->pextra_widthp;
2005 ppar->SetPExtraType(ppar->pextra_type,
2006 p1.c_str(), p2.c_str());
2008 if ((par->pextra_type == PEXTRA_NONE) &&
2009 npar && (npar->pextra_type != PEXTRA_NONE)) {
2011 p1 = npar->pextra_width,
2012 p2 = npar->pextra_widthp;
2013 npar->SetPExtraType(npar->pextra_type,
2014 p1.c_str(), p2.c_str());
2020 void LyXParagraph::SetLayout(LyXTextClass::LayoutList::size_type new_layout)
2023 * par = FirstPhysicalPar(),
2027 par->layout = new_layout;
2028 par->labelwidthstring.clear();
2029 par->align = LYX_ALIGN_LAYOUT;
2030 par->added_space_top = VSpace(VSpace::NONE);
2031 par->added_space_bottom = VSpace(VSpace::NONE);
2032 /* table stuff -- begin*/
2035 /* table stuff -- end*/
2036 if (par->pextra_type == PEXTRA_NONE) {
2037 if (par->Previous()) {
2038 ppar = par->Previous()->FirstPhysicalPar();
2041 && (ppar->depth > par->depth))
2042 ppar = ppar->Previous()->FirstPhysicalPar();
2045 npar = par->Next()->NextAfterFootnote();
2048 && (npar->depth > par->depth))
2049 npar = npar->Next()->NextAfterFootnote();
2051 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
2053 p1 = ppar->pextra_width,
2054 p2 = ppar->pextra_widthp;
2055 ppar->SetPExtraType(ppar->pextra_type,
2056 p1.c_str(), p2.c_str());
2058 if ((par->pextra_type == PEXTRA_NONE) &&
2059 npar && (npar->pextra_type != PEXTRA_NONE)) {
2061 p1 = npar->pextra_width,
2062 p2 = npar->pextra_widthp;
2063 npar->SetPExtraType(npar->pextra_type,
2064 p1.c_str(), p2.c_str());
2070 // if the layout of a paragraph contains a manual label, the beginning of the
2071 // main body is the beginning of the second word. This is what the par-
2072 // function returns. If the layout does not contain a label, the main
2073 // body always starts with position 0. This differentiation is necessary,
2074 // because there cannot be a newline or a blank <= the beginning of the
2075 // main body in TeX.
2077 int LyXParagraph::BeginningOfMainBody() const
2079 if (FirstPhysicalPar() != this)
2082 // Unroll the first two cycles of the loop
2083 // and remember the previous character to
2084 // remove unnecessary GetChar() calls
2087 && GetChar(i) != LyXParagraph::META_NEWLINE) {
2089 char previous_char, temp;
2091 && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
2092 // Yes, this ^ is supposed to be "= " not "=="
2095 && previous_char != ' '
2096 && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
2098 previous_char = temp;
2103 if (i == 0 && i == size() &&
2104 !(footnoteflag == LyXParagraph::NO_FOOTNOTE
2105 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
2106 ++i; /* the cursor should not jump
2107 * to the main body if there
2113 LyXParagraph * LyXParagraph::DepthHook(int deth)
2115 LyXParagraph * newpar = this;
2120 newpar = newpar->FirstPhysicalPar()->Previous();
2121 } while (newpar && newpar->GetDepth() > deth
2122 && newpar->footnoteflag == footnoteflag);
2125 if (Previous() || GetDepth())
2126 lyxerr << "ERROR (LyXParagraph::DepthHook): "
2130 return newpar->FirstPhysicalPar();
2134 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
2136 LyXParagraph const * newpar = this;
2141 newpar = newpar->FirstPhysicalPar()->Previous();
2142 } while (newpar && newpar->GetDepth() > deth
2143 && newpar->footnoteflag == footnoteflag);
2146 if (Previous() || GetDepth())
2147 lyxerr << "ERROR (LyXParagraph::DepthHook): "
2151 return newpar->FirstPhysicalPar();
2155 int LyXParagraph::AutoDeleteInsets()
2157 #ifdef NEW_INSETTABLE
2158 vector<size_type> tmpvec;
2160 for (InsetList::iterator it = insetlist.begin();
2161 it != insetlist.end(); ++it) {
2162 if ((*it).inset && (*it).inset->AutoDelete()) {
2163 tmpvec.push_back((*it).pos);
2167 for (vector<size_type>::const_iterator cit = tmpvec.begin();
2168 cit != tmpvec.end(); ++cit) {
2173 InsetTable * tmpi = insettable;
2174 InsetTable * tmpi2 = tmpi;
2180 if (tmpi2->inset->AutoDelete()) {
2185 lyxerr << "ERROR (LyXParagraph::AutoDeleteInsets): "
2186 "cannot auto-delete insets" << endl;
2194 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
2196 #ifdef NEW_INSETTABLE
2197 InsetList::iterator it2 = insetlist.end();
2198 for (InsetList::iterator it = insetlist.begin();
2199 it != insetlist.end(); ++it) {
2200 if ((*it).pos >= pos) {
2201 if (it2 == insetlist.end() || (*it).pos < (*it2).pos)
2205 if (it2 != insetlist.end()) {
2207 return (*it2).inset;
2211 InsetTable * tmpi = insettable;
2212 InsetTable * tmpi2 = 0;
2214 if (tmpi->pos >= pos) {
2215 if (!tmpi2 || tmpi->pos < tmpi2->pos)
2222 return tmpi2->inset;
2230 // returns -1 if inset not found
2231 int LyXParagraph::GetPositionOfInset(Inset * inset) const
2234 #ifdef NEW_INSETTABLE
2235 for (InsetList::const_iterator cit = insetlist.begin();
2236 cit != insetlist.end(); ++cit) {
2237 if ((*cit).inset == inset) {
2242 InsetTable * tmpi = insettable;
2243 while (tmpi && tmpi->inset != inset) {
2246 if (tmpi && tmpi->inset)
2249 // Think about footnotes.
2250 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
2251 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2253 NextAfterFootnote()->GetPositionOfInset(inset);
2255 return text.size() + 1 + further;
2261 void LyXParagraph::readSimpleWholeFile(istream & is)
2267 InsertChar(text.size(), c);
2272 LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow,
2273 string & foot, TexRow & foot_texrow,
2276 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
2277 LyXParagraph * par = next;
2278 LyXLayout const & style =
2279 textclasslist.Style(current_view->buffer()->params.textclass,
2282 bool further_blank_line = false;
2284 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
2286 if (start_of_appendix) {
2287 file += "\\appendix\n";
2291 if (tex_code_break_column && style.isCommand()){
2296 if (pagebreak_top) {
2297 file += "\\newpage";
2298 further_blank_line = true;
2300 if (added_space_top.kind() != VSpace::NONE) {
2301 file += added_space_top.asLatexCommand();
2302 further_blank_line = true;
2306 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
2307 file += "\\vspace{-1\\parskip}";
2308 further_blank_line = true;
2311 if (further_blank_line){
2316 switch (style.latextype) {
2319 file += style.latexname();
2320 file += style.latexparam();
2322 case LATEX_ITEM_ENVIRONMENT:
2324 bibkey->Latex(file, false);
2328 case LATEX_LIST_ENVIRONMENT:
2335 bool need_par = SimpleTeXOnePar(file, texrow);
2337 // Spit out footnotes
2338 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2339 && par->footnoteflag != footnoteflag) {
2340 par = par->TeXFootnote(file, texrow,
2341 foot, foot_texrow, foot_count);
2342 par->SimpleTeXOnePar(file, texrow);
2346 // Make sure that \\par is done with the font of the last
2347 // character if this has another size as the default.
2348 // This is necessary because LaTeX (and LyX on the screen)
2349 // calculates the space between the baselines according
2350 // to this font. (Matthias)
2351 LyXFont font = getFont(Last()-1);
2353 if (style.resfont.size() != font.size()) {
2355 file += font.latexSize();
2359 } else if (textclasslist.Style(current_view->buffer()->params.textclass,
2360 GetLayout()).isCommand()){
2361 if (style.resfont.size() != font.size()) {
2363 file += font.latexSize();
2367 } else if (style.resfont.size() != font.size()){
2368 file += "{\\" + font.latexSize() + " \\par}";
2371 switch (style.latextype) {
2372 case LATEX_ITEM_ENVIRONMENT:
2373 case LATEX_LIST_ENVIRONMENT:
2374 if (par && (depth < par->depth)) {
2379 case LATEX_ENVIRONMENT:
2380 // if its the last paragraph of the current environment
2381 // skip it otherwise fall through
2383 && (par->layout != layout
2384 || par->depth != depth
2385 || par->pextra_type != pextra_type))
2388 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2389 && footnotekind != LyXParagraph::FOOTNOTE
2390 && footnotekind != LyXParagraph::MARGIN
2394 // don't insert this if we would be adding it
2395 // before or after a table in a float. This
2396 // little trick is needed in order to allow
2397 // use of tables in \subfigures or \subtables.
2403 further_blank_line = false;
2405 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2406 further_blank_line = true;
2409 if (added_space_bottom.kind() != VSpace::NONE) {
2410 file += added_space_bottom.asLatexCommand();
2411 further_blank_line = true;
2414 if (pagebreak_bottom) {
2415 file += "\\newpage";
2416 further_blank_line = true;
2419 if (further_blank_line){
2424 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2425 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2430 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2435 // This one spits out the text of the paragraph
2436 bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow)
2438 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2441 return SimpleTeXOneTablePar(file, texrow);
2444 size_type main_body;
2446 bool return_value = false;
2448 LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass, GetLayout());
2451 // Maybe we have to create a optional argument.
2452 if (style.labeltype != LABEL_MANUAL)
2455 main_body = BeginningOfMainBody();
2457 if (main_body > 0) {
2459 basefont = getFont(-2); // Get label font
2461 basefont = getFont(-1); // Get layout font
2469 if (style.isCommand()) {
2472 } else if (align != LYX_ALIGN_LAYOUT) {
2475 return_value = true;
2479 // Which font is currently active?
2480 LyXFont running_font = basefont;
2481 // Do we have an open font change?
2482 bool open_font = false;
2484 texrow.start(this, 0);
2486 for (size_type i = 0; i < size(); ++i) {
2488 // First char in paragraph or after label?
2489 if (i == main_body && !IsDummy()) {
2490 if (main_body > 0) {
2492 column += running_font.latexWriteEndChanges(file, basefont);
2495 basefont = getFont(-1); // Now use the layout font
2496 running_font = basefont;
2500 if (style.isCommand()) {
2503 } else if (align != LYX_ALIGN_LAYOUT) {
2506 return_value = true;
2510 file += "\\noindent ";
2514 case LYX_ALIGN_NONE:
2515 case LYX_ALIGN_BLOCK:
2516 case LYX_ALIGN_LAYOUT:
2517 case LYX_ALIGN_SPECIAL: break;
2518 case LYX_ALIGN_LEFT:
2519 file += "\\raggedright ";
2522 case LYX_ALIGN_RIGHT:
2523 file += "\\raggedleft ";
2526 case LYX_ALIGN_CENTER:
2527 file += "\\centering ";
2535 // Fully instantiated font
2536 LyXFont font = getFont(i);
2538 // Spaces at end of font change are simulated to be
2539 // outside font change, i.e. we write "\textXX{text} "
2540 // rather than "\textXX{text }". (Asger)
2541 if (open_font && c == ' ' && i <= size() - 2
2542 && !getFont(i+1).equalExceptLatex(running_font)
2543 && !getFont(i+1).equalExceptLatex(font)) {
2544 font = getFont(i + 1);
2546 // We end font definition before blanks
2547 if (!font.equalExceptLatex(running_font) && open_font) {
2548 column += running_font.latexWriteEndChanges(file,
2550 running_font = basefont;
2554 // Blanks are printed before start of fontswitch
2556 // Do not print the separation of the optional argument
2557 if (i != main_body - 1) {
2558 SimpleTeXBlanks(file, texrow, i,
2559 column, font, style);
2563 // Do we need to change font?
2564 if (!font.equalExceptLatex(running_font)
2565 && i != main_body-1) {
2566 column += font.latexWriteStartChanges(file, basefont);
2567 running_font = font;
2571 if (c == LyXParagraph::META_NEWLINE) {
2572 // newlines are handled differently here than
2573 // the default in SimpleTeXSpecialChars().
2574 if (!style.newline_allowed
2575 || font.latex() == LyXFont::ON) {
2579 column += running_font.latexWriteEndChanges(file, basefont);
2582 basefont = getFont(-1);
2583 running_font = basefont;
2584 if (font.family() ==
2585 LyXFont::TYPEWRITER_FAMILY) {
2591 texrow.start(this, i + 1);
2594 SimpleTeXSpecialChars(file, texrow,
2595 font, running_font, basefont,
2596 open_font, style, i, column, c);
2600 // If we have an open font definition, we have to close it
2602 running_font.latexWriteEndChanges(file, basefont);
2605 // Needed if there is an optional argument but no contents.
2606 if (main_body > 0 && main_body == size()) {
2608 return_value = false;
2611 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2612 return return_value;
2616 // This one spits out the text of a table paragraph
2617 bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow)
2619 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2621 bool return_value = false;
2623 LyXLayout const & style =
2624 textclasslist.Style(current_view->buffer()->params.textclass,
2628 if (!IsDummy()) { // it is dummy if it is in a float!!!
2629 if (style.isCommand()) {
2632 } else if (align != LYX_ALIGN_LAYOUT) {
2635 return_value = true;
2638 file += "\\noindent ";
2642 case LYX_ALIGN_NONE:
2643 case LYX_ALIGN_BLOCK:
2644 case LYX_ALIGN_LAYOUT:
2645 case LYX_ALIGN_SPECIAL: break;
2646 case LYX_ALIGN_LEFT:
2647 file += "\\raggedright ";
2650 case LYX_ALIGN_RIGHT:
2651 file += "\\raggedleft ";
2654 case LYX_ALIGN_CENTER:
2655 file += "\\centering ";
2661 LyXFont basefont = getFont(-1); // Get layout font
2662 // Which font is currently active?
2663 LyXFont running_font = basefont;
2664 // Do we have an open font change?
2665 bool open_font = false;
2666 int current_cell_number = -1;
2667 int tmp = table->TexEndOfCell(file, current_cell_number);
2668 for (; tmp > 0 ; --tmp)
2671 texrow.start(this, 0);
2673 for (size_type i = 0; i < size(); ++i) {
2674 char c = GetChar(i);
2675 if (table->IsContRow(current_cell_number + 1)) {
2676 if (c == LyXParagraph::META_NEWLINE)
2677 ++current_cell_number;
2682 // Fully instantiated font
2683 LyXFont font = getFont(i);
2685 // Spaces at end of font change are simulated to be
2686 // outside font change.
2687 // i.e. we write "\textXX{text} " rather than
2688 // "\textXX{text }". (Asger)
2689 if (open_font && c == ' ' && i <= size() - 2
2690 && getFont(i+1) != running_font && getFont(i+1) != font) {
2691 font = getFont(i+1);
2694 // We end font definition before blanks
2695 if (font != running_font && open_font) {
2696 column += running_font.latexWriteEndChanges(file,
2698 running_font = basefont;
2701 // Blanks are printed before start of fontswitch
2703 SimpleTeXBlanks(file, texrow, i, column, font, style);
2705 // Do we need to change font?
2706 if (font != running_font) {
2707 column += font.latexWriteStartChanges(file, basefont);
2708 running_font = font;
2711 // Do we need to turn on LaTeX mode?
2712 if (font.latex() != running_font.latex()) {
2713 if (font.latex() == LyXFont::ON
2714 && style.needprotect) {
2715 file += "\\protect ";
2719 if (c == LyXParagraph::META_NEWLINE) {
2720 // special case for inside a table
2721 // different from default case in
2722 // SimpleTeXSpecialChars()
2724 column += running_font
2725 .latexWriteEndChanges(file, basefont);
2728 basefont = getFont(-1);
2729 running_font = basefont;
2730 ++current_cell_number;
2731 if (table->CellHasContRow(current_cell_number) >= 0) {
2732 TeXContTableRows(file, i + 1,
2733 current_cell_number,
2736 // if this cell follow only ContRows till end don't
2737 // put the EndOfCell because it is put after the
2739 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2740 --current_cell_number;
2743 int tmp = table->TexEndOfCell(file,
2744 current_cell_number);
2747 } else if (tmp < 0) {
2753 texrow.start(this, i + 1);
2755 SimpleTeXSpecialChars(file, texrow,
2756 font, running_font, basefont,
2757 open_font, style, i, column, c);
2761 // If we have an open font definition, we have to close it
2763 running_font.latexWriteEndChanges(file, basefont);
2765 ++current_cell_number;
2766 tmp = table->TexEndOfCell(file, current_cell_number);
2767 for (; tmp > 0; --tmp)
2769 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2770 return return_value;
2774 // This one spits out the text off ContRows in tables
2775 bool LyXParagraph::TeXContTableRows(string & file,
2776 LyXParagraph::size_type i,
2777 int current_cell_number,
2778 int & column, TexRow & texrow)
2780 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2786 bool return_value = false;
2787 LyXLayout const & style =
2788 textclasslist.Style(current_view->buffer()->params.textclass,
2790 LyXFont basefont = getFont(-1); // Get layout font
2791 // Which font is currently active?
2792 LyXFont running_font = basefont;
2793 // Do we have an open font change?
2794 bool open_font = false;
2796 size_type lastpos = i;
2797 int cell = table->CellHasContRow(current_cell_number);
2798 ++current_cell_number;
2800 // first find the right position
2802 for (; (i < size()) && (current_cell_number<cell); ++i) {
2804 if (c == LyXParagraph::META_NEWLINE)
2805 ++current_cell_number;
2809 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2813 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2818 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2822 // Fully instantiated font
2823 LyXFont font = getFont(i);
2825 // Spaces at end of font change are simulated to
2826 // be outside font change. i.e. we write
2827 // "\textXX{text} " rather than "\textXX{text }".
2829 if (open_font && c == ' ' && i <= size() - 2
2830 && getFont(i + 1) != running_font
2831 && getFont(i + 1) != font) {
2832 font = getFont(i + 1);
2835 // We end font definition before blanks
2836 if (font != running_font && open_font) {
2837 column += running_font.latexWriteEndChanges(file, basefont);
2838 running_font = basefont;
2841 // Blanks are printed before start of fontswitch
2843 SimpleTeXBlanks(file, texrow, i,
2844 column, font, style);
2846 // Do we need to change font?
2847 if (font != running_font) {
2849 font.latexWriteStartChanges(file,
2851 running_font = font;
2854 // Do we need to turn on LaTeX mode?
2855 if (font.latex() != running_font.latex()) {
2856 if (font.latex() == LyXFont::ON
2857 && style.needprotect)
2859 file += "\\protect ";
2863 SimpleTeXSpecialChars(file, texrow, font,
2864 running_font, basefont,
2865 open_font, style, i, column, c);
2867 // If we have an open font definition, we have to close it
2869 running_font.latexWriteEndChanges(file, basefont);
2872 basefont = getFont(-1);
2873 running_font = basefont;
2874 cell = table->CellHasContRow(current_cell_number);
2876 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2877 return return_value;
2881 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2883 bool retval = false;
2885 case LyXParagraph::META_HFILL:
2886 sgml_string.clear();
2888 case LyXParagraph::META_PROTECTED_SEPARATOR:
2891 case LyXParagraph::META_NEWLINE:
2895 sgml_string = "&";
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 = "\";
2937 case '\0': // Ignore :-)
2938 sgml_string.clear();
2948 void LyXParagraph::SimpleDocBookOneTablePar(string & file, string & extra,
2949 int & desc_on, int depth)
2952 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2954 LyXFont font1, font2;
2957 size_type main_body;
2958 string emph = "emphasis";
2959 bool emph_flag = false;
2961 LyXLayout const & style =
2962 textclasslist.Style(current_view->buffer()->params.textclass,
2965 if (style.labeltype != LABEL_MANUAL)
2968 main_body = BeginningOfMainBody();
2970 // Gets paragraph main font.
2972 font1 = style.labelfont;
2976 int char_line_count = depth;
2977 addNewlineAndDepth(file, depth);
2978 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2979 file += "<INFORMALTABLE>";
2980 addNewlineAndDepth(file, ++depth);
2982 int current_cell_number = -1;
2983 int tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
2985 // Parsing main loop.
2986 for (size_type i = 0; i < size(); ++i) {
2988 if (table->IsContRow(current_cell_number+1)) {
2989 if (c == LyXParagraph::META_NEWLINE)
2990 ++current_cell_number;
2995 // Fully instantiated font
2998 // Handle <emphasis> tag.
2999 if (font1.emph() != font2.emph() && i) {
3000 if (font2.emph() == LyXFont::ON) {
3001 file += "<emphasis>";
3003 } else if (emph_flag) {
3004 file += "</emphasis>";
3008 if (c == LyXParagraph::META_NEWLINE) {
3009 // We have only to control for emphasis open here!
3011 file += "</emphasis>";
3014 font1 = font2 = getFont(-1);
3015 ++current_cell_number;
3016 if (table->CellHasContRow(current_cell_number) >= 0) {
3017 DocBookContTableRows(file, extra, desc_on, i+1,
3018 current_cell_number,
3021 // if this cell follow only ContRows till end don't
3022 // put the EndOfCell because it is put after the
3024 if (table->ShouldBeVeryLastCell(current_cell_number)) {
3025 --current_cell_number;
3028 tmp = table->DocBookEndOfCell(file,
3029 current_cell_number,
3034 } else if (c == LyXParagraph::META_INSET) {
3035 inset = GetInset(i);
3037 inset->DocBook(tmp_out);
3039 // This code needs some explanation:
3040 // Two insets are treated specially
3041 // label if it is the first element in a
3042 // command paragraph
3044 // graphics inside tables or figure floats
3046 // title (the equivalente in latex for this
3048 // and title should come first
3051 if(desc_on != 3 || i != 0) {
3052 if(tmp_out[0] == '@') {
3054 extra += frontStrip(tmp_out,
3057 file += frontStrip(tmp_out,
3062 } else if (font2.latex() == LyXFont::ON) {
3063 // "TeX"-Mode on == > SGML-Mode on.
3069 if (linuxDocConvertChar(c, sgml_string)
3070 && !style.free_spacing) {
3071 // in freespacing mode, spaces are
3072 // non-breaking characters
3077 file += "</term><listitem><para>";
3083 file += sgml_string;
3089 // Needed if there is an optional argument but no contents.
3090 if (main_body > 0 && main_body == size()) {
3095 file += "</emphasis>";
3098 ++current_cell_number;
3099 tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
3100 // Resets description flag correctly.
3103 // <term> not closed...
3107 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3108 file += "</INFORMALTABLE>";
3110 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
3115 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
3117 LyXParagraph::size_type i,
3118 int current_cell_number, int &column)
3123 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
3128 string emph= "emphasis";
3129 bool emph_flag= false;
3130 int char_line_count= 0;
3132 LyXLayout const & style =
3133 textclasslist.Style(current_view->buffer()->params.textclass,
3136 size_type main_body;
3137 if (style.labeltype != LABEL_MANUAL)
3140 main_body = BeginningOfMainBody();
3142 // Gets paragraph main font.
3145 font1 = style.labelfont;
3149 size_type lastpos = i;
3150 int cell = table->CellHasContRow(current_cell_number);
3151 ++current_cell_number;
3153 // first find the right position
3155 for (; i < size() && current_cell_number < cell; ++i) {
3157 if (c == LyXParagraph::META_NEWLINE)
3158 ++current_cell_number;
3162 // I don't know how to handle this so I comment it
3163 // for the moment (Jug)
3164 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3165 // file += " \\\\\n";
3168 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
3173 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3177 // Fully instantiated font
3180 // Handle <emphasis> tag.
3181 if (font1.emph() != font2.emph() && i) {
3182 if (font2.emph() == LyXFont::ON) {
3183 file += "<emphasis>";
3185 } else if (emph_flag) {
3186 file += "</emphasis>";
3190 if (c == LyXParagraph::META_INSET) {
3191 inset = GetInset(i);
3193 inset->DocBook(tmp_out);
3195 // This code needs some explanation:
3196 // Two insets are treated specially
3197 // label if it is the first element in a
3198 // command paragraph
3200 // graphics inside tables or figure floats
3201 // can't go on title (the equivalente in
3202 // latex for this case is caption and title
3203 // should come first
3206 if(desc_on != 3 || i != 0) {
3207 if(tmp_out[0] == '@') {
3209 extra += frontStrip(tmp_out, '@');
3211 file += frontStrip(tmp_out, '@');
3215 } else if (font2.latex() == LyXFont::ON) {
3216 // "TeX"-Mode on == > SGML-Mode on.
3222 if (linuxDocConvertChar(c, sgml_string)
3223 && !style.free_spacing) {
3224 // in freespacing mode, spaces are
3225 // non-breaking characters
3230 file += "</term><listitem><para>";
3236 file += sgml_string;
3240 // we have only to control for emphasis open here!
3242 file += "</emphasis>";
3245 font1 = font2 = getFont(-1);
3246 cell = table->CellHasContRow(current_cell_number);
3248 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3252 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
3253 LyXParagraph::size_type const i,
3254 int & column, LyXFont const & font,
3255 LyXLayout const & style)
3257 if (column > tex_code_break_column
3259 && GetChar(i - 1) != ' '
3261 // In LaTeX mode, we don't want to
3262 // break lines since some commands
3264 && ! (font.latex() == LyXFont::ON)
3265 // same in FreeSpacing mode
3266 && !style.free_spacing
3267 // In typewriter mode, we want to avoid
3268 // ! . ? : at the end of a line
3269 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3270 && (GetChar(i-1) == '.'
3271 || GetChar(i-1) == '?'
3272 || GetChar(i-1) == ':'
3273 || GetChar(i-1) == '!'))) {
3274 if (tex_code_break_column == 0) {
3275 // in batchmode we need LaTeX to still
3276 // see it as a space not as an extra '\n'
3282 texrow.start(this, i+1);
3284 } else if (font.latex() == LyXFont::OFF) {
3285 if (style.free_spacing) {
3294 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
3296 LyXFont & running_font,
3299 LyXLayout const & style,
3300 LyXParagraph::size_type & i,
3301 int & column, char const c)
3303 // Two major modes: LaTeX or plain
3304 // Handle here those cases common to both modes
3305 // and then split to handle the two modes separately.
3307 case LyXParagraph::META_INSET: {
3308 Inset * inset = GetInset(i);
3310 int len = file.length();
3311 int tmp = inset->Latex(file, style.isCommand());
3316 column += file.length() - len;
3325 case LyXParagraph::META_NEWLINE:
3327 column += running_font.latexWriteEndChanges(file,
3331 basefont = getFont(-1);
3332 running_font = basefont;
3335 case LyXParagraph::META_HFILL:
3336 file += "\\hfill{}";
3341 // And now for the special cases within each mode
3342 // Are we in LaTeX mode?
3343 if (font.latex() == LyXFont::ON) {
3344 // at present we only have one option
3345 // but I'll leave it as a switch statement
3346 // so its simpler to extend. (ARRae)
3348 case LyXParagraph::META_PROTECTED_SEPARATOR:
3353 // make sure that we will not print
3354 // error generating chars to the tex
3355 // file. This test would not be needed
3356 // if it were done in the buffer
3364 // Plain mode (i.e. not LaTeX)
3366 case LyXParagraph::META_PROTECTED_SEPARATOR:
3371 file += "\\textbackslash{}";
3375 case '°': case '±': case '²': case '³':
3376 case '×': case '÷': case '¹': case 'ª':
3377 case 'º': case '¬': case 'µ':
3378 if (current_view->buffer()->params.inputenc == "latin1") {
3379 file += "\\ensuremath{";
3388 case '|': case '<': case '>':
3389 // In T1 encoding, these characters exist
3390 if (lyxrc->fontenc == "T1") {
3392 //... but we should avoid ligatures
3393 if ((c == '>' || c == '<')
3395 && GetChar(i+1) == c){
3396 file += "\\textcompwordmark{}";
3401 // Typewriter font also has them
3402 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3406 // Otherwise, we use what LaTeX
3410 file += "\\textless{}";
3414 file += "\\textgreater{}";
3418 file += "\\textbar{}";
3424 case '-': // "--" in Typewriter mode -> "-{}-"
3426 && GetChar(i + 1) == '-'
3427 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3436 file += "\\char`\\\"{}";
3441 if (current_view->buffer()->params.inputenc == "default") {
3442 file += "\\pounds{}";
3450 case '%': case '#': case '{':
3458 file += "\\textasciitilde{}";
3463 file += "\\textasciicircum{}";
3467 case '*': case '[': case ']':
3468 // avoid being mistaken for optional arguments
3476 // Blanks are printed before font switching.
3477 // Sure? I am not! (try nice-latex)
3478 // I am sure it's correct. LyX might be smarter
3479 // in the future, but for now, nothing wrong is
3484 /* idea for labels --- begin*/
3488 && font.family() != LyXFont::TYPEWRITER_FAMILY
3489 && GetChar(i + 1) == 'y'
3490 && GetChar(i + 2) == 'X') {
3498 && font.family() != LyXFont::TYPEWRITER_FAMILY
3499 && GetChar(i + 1) == 'e'
3500 && GetChar(i + 2) == 'X') {
3505 // Check for "LaTeX2e"
3508 && font.family() != LyXFont::TYPEWRITER_FAMILY
3509 && GetChar(i + 1) == 'a'
3510 && GetChar(i + 2) == 'T'
3511 && GetChar(i + 3) == 'e'
3512 && GetChar(i + 4) == 'X'
3513 && GetChar(i + 5) == '2'
3514 && GetChar(i + 6) == 'e') {
3515 file += "\\LaTeXe{}";
3519 // Check for "LaTeX"
3522 && font.family() != LyXFont::TYPEWRITER_FAMILY
3523 && GetChar(i + 1) == 'a'
3524 && GetChar(i + 2) == 'T'
3525 && GetChar(i + 3) == 'e'
3526 && GetChar(i + 4) == 'X') {
3527 file += "\\LaTeX{}";
3530 /* idea for labels --- end*/
3531 } else if (c != '\0') {
3541 bool LyXParagraph::RoffContTableRows(ostream & os,
3542 LyXParagraph::size_type i,
3548 LyXFont font1 = LyXFont(LyXFont::ALL_INHERIT);
3553 string fname2 = TmpFileName(string(), "RAT2");
3555 int cell = table->CellHasContRow(actcell);
3558 // first find the right position
3560 for (; i < size() && actcell < cell; ++i) {
3562 if (c == LyXParagraph::META_NEWLINE)
3567 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3570 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3572 font2 = GetFontSettings(i);
3573 if (font1.latex() != font2.latex()) {
3574 if (font2.latex() != LyXFont::OFF)
3579 case LyXParagraph::META_INSET:
3580 if ((inset = GetInset(i))) {
3581 fstream fs(fname2.c_str(),
3584 WriteAlert(_("LYX_ERROR:"),
3585 _("Cannot open temporary file:"),
3589 inset->Latex(fs, -1);
3602 case LyXParagraph::META_NEWLINE:
3604 case LyXParagraph::META_HFILL:
3606 case LyXParagraph::META_PROTECTED_SEPARATOR:
3615 lyxerr.debug() << "RoffAsciiTable: "
3616 "NULL char in structure."
3621 cell = table->CellHasContRow(actcell);
3627 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
3628 string & foot, TexRow & foot_texrow,
3631 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3632 LyXParagraph * par = this;
3634 while (par && par->depth == depth) {
3636 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3637 if (textclasslist.Style(current_view->buffer()->params.textclass,
3638 par->layout).isEnvironment()
3639 || par->pextra_type != PEXTRA_NONE)
3641 par = par->TeXEnvironment(file, texrow,
3645 par = par->TeXOnePar(file, texrow,
3650 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3656 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
3658 TexRow & foot_texrow,
3661 bool eindent_open = false;
3662 bool foot_this_level = false;
3663 // flags when footnotetext should be appended to file.
3664 static bool minipage_open = false;
3665 static int minipage_open_depth = 0;
3666 char par_sep = current_view->buffer()->params.paragraph_separation;
3668 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3670 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3672 LyXLayout const & style =
3673 textclasslist.Style(current_view->buffer()->params.textclass,
3676 if (pextra_type == PEXTRA_INDENT) {
3677 if (!pextra_width.empty()) {
3678 file += "\\begin{LyXParagraphIndent}{"
3679 + pextra_width + "}\n";
3681 //float ib = atof(pextra_widthp.c_str())/100;
3682 // string can't handle floats at present (971109)
3683 // so I'll do a conversion by hand knowing that
3684 // the limits are 0.0 to 1.0. ARRae.
3685 file += "\\begin{LyXParagraphIndent}{";
3686 switch (pextra_widthp.length()) {
3692 file += pextra_widthp;
3696 file += pextra_widthp;
3698 file += "\\columnwidth}\n";
3701 eindent_open = true;
3703 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3704 if (pextra_hfill && Previous() &&
3705 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3706 file += "\\hfill{}\n";
3709 if (par_sep == BufferParams::PARSEP_INDENT) {
3710 file += "{\\setlength\\parindent{0pt}\n";
3713 file += "\\begin{minipage}";
3714 switch(pextra_alignment) {
3715 case MINIPAGE_ALIGN_TOP:
3718 case MINIPAGE_ALIGN_MIDDLE:
3721 case MINIPAGE_ALIGN_BOTTOM:
3725 if (!pextra_width.empty()) {
3727 file += pextra_width + "}\n";
3729 //float ib = atof(par->pextra_width.c_str())/100;
3730 // string can't handle floats at present
3731 // so I'll do a conversion by hand knowing that
3732 // the limits are 0.0 to 1.0. ARRae.
3734 switch (pextra_widthp.length()) {
3740 file += pextra_widthp;
3744 file += pextra_widthp;
3746 file += "\\columnwidth}\n";
3749 if (par_sep == BufferParams::PARSEP_INDENT) {
3750 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3753 minipage_open = true;
3754 minipage_open_depth = depth;
3757 #ifdef WITH_WARNINGS
3758 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3759 //I disabled it because it breaks when lists span on several
3762 if (style.isEnvironment()){
3763 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3764 #ifdef FANCY_FOOTNOTE_CODE
3765 if (foot_count < 0) {
3766 // flag that footnote[mark][text] should be
3767 // used for any footnotes from now on
3769 foot_this_level = true;
3772 file += "\\begin{" + style.latexname() + "}{"
3773 + labelwidthstring + "}\n";
3774 } else if (style.labeltype == LABEL_BIBLIO) {
3776 file += "\\begin{" + style.latexname() + "}{"
3777 + bibitemWidthest() + "}\n";
3778 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3779 #ifdef FANCY_FOOTNOTE_CODE
3780 if (foot_count < 0) {
3781 // flag that footnote[mark][text] should be
3782 // used for any footnotes from now on
3784 foot_this_level = true;
3787 file += "\\begin{" + style.latexname() + '}'
3788 + style.latexparam() + '\n';
3790 file += "\\begin{" + style.latexname() + '}'
3791 + style.latexparam() + '\n';
3794 LyXParagraph * par = this;
3796 par = par->TeXOnePar(file, texrow,
3797 foot, foot_texrow, foot_count);
3799 if (minipage_open && par && !style.isEnvironment() &&
3800 (par->pextra_type == PEXTRA_MINIPAGE) &&
3801 par->pextra_start_minipage) {
3802 file += "\\end{minipage}\n";
3804 if (par_sep == BufferParams::PARSEP_INDENT) {
3808 minipage_open = false;
3810 if (par && par->depth > depth) {
3811 if (textclasslist.Style(current_view->buffer()->params.textclass,
3812 par->layout).isParagraph()
3814 && !suffixIs(file, "\n\n")) {
3815 // There should be at least one '\n' already
3816 // but we need there to be two for Standard
3817 // paragraphs that are depth-increment'ed to be
3818 // output correctly. However, tables can
3819 // also be paragraphs so don't adjust them.
3824 par = par->TeXDeeper(file, texrow,
3825 foot, foot_texrow, foot_count);
3827 if (par && par->layout == layout && par->depth == depth &&
3828 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3829 if (par->pextra_hfill && par->Previous() &&
3830 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3831 file += "\\hfill{}\n";
3834 if (par_sep == BufferParams::PARSEP_INDENT) {
3835 file += "{\\setlength\\parindent{0pt}\n";
3838 file += "\\begin{minipage}";
3839 switch(par->pextra_alignment) {
3840 case MINIPAGE_ALIGN_TOP:
3843 case MINIPAGE_ALIGN_MIDDLE:
3846 case MINIPAGE_ALIGN_BOTTOM:
3850 if (!par->pextra_width.empty()) {
3852 file += par->pextra_width;
3855 //float ib = atof(par->pextra_widthp.c_str())/100;
3856 // string can't handle floats at present
3857 // so I'll do a conversion by hand knowing that
3858 // the limits are 0.0 to 1.0. ARRae.
3860 switch (par->pextra_widthp.length()) {
3866 file += par->pextra_widthp;
3870 file += par->pextra_widthp;
3872 file += "\\columnwidth}\n";
3875 if (par_sep == BufferParams::PARSEP_INDENT) {
3876 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3879 minipage_open = true;
3880 minipage_open_depth = par->depth;
3883 && par->layout == layout
3884 && par->depth == depth
3885 && par->pextra_type == pextra_type);
3887 if (style.isEnvironment()) {
3888 file += "\\end{" + style.latexname() + '}';
3889 // maybe this should go after the minipage closes?
3890 if (foot_this_level) {
3891 if (foot_count >= 1) {
3892 if (foot_count > 1) {
3893 file += "\\addtocounter{footnote}{-";
3894 file += tostr(foot_count - 1);
3898 texrow += foot_texrow;
3900 foot_texrow.reset();
3905 if (minipage_open && (minipage_open_depth == depth) &&
3906 (!par || par->pextra_start_minipage ||
3907 par->pextra_type != PEXTRA_MINIPAGE)) {
3908 file += "\\end{minipage}\n";
3910 if (par_sep == BufferParams::PARSEP_INDENT) {
3914 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3915 file += "\\medskip\n\n";
3919 minipage_open = false;
3922 file += "\\end{LyXParagraphIndent}\n";
3925 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
3926 && par->pextra_hfill)) {
3930 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3931 return par; // ale970302
3935 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
3936 string & foot, TexRow & foot_texrow,
3939 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3940 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3941 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3942 "No footnote!" << endl;
3944 LyXParagraph * par = this;
3945 LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass,
3946 previous->GetLayout());
3948 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3949 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3950 "Float other than footnote in command"
3951 " with moving argument is illegal" << endl;
3954 if (footnotekind != LyXParagraph::FOOTNOTE
3955 && footnotekind != LyXParagraph::MARGIN
3957 && !suffixIs(file, '\n')) {
3958 // we need to ensure that real floats like tables and figures
3959 // have their \begin{} on a new line otherwise we can get
3960 // incorrect results when using the endfloat.sty package
3961 // especially if two floats follow one another. ARRae 981022
3962 // NOTE: if the file is length 0 it must have just been
3963 // written out so we assume it ended with a '\n'
3968 BufferParams * params = ¤t_view->buffer()->params;
3969 bool footer_in_body = true;
3970 switch (footnotekind) {
3971 case LyXParagraph::FOOTNOTE:
3972 if (style.intitle) {
3973 file += "\\thanks{\n";
3974 footer_in_body = false;
3976 if (foot_count == -1) {
3977 // we're at depth 0 so we can use:
3978 file += "\\footnote{%\n";
3979 footer_in_body = false;
3981 file += "\\footnotemark{}%\n";
3983 // we only need this when there are
3984 // multiple footnotes
3985 foot += "\\stepcounter{footnote}";
3987 foot += "\\footnotetext{%\n";
3988 foot_texrow.start(this, 0);
3989 foot_texrow.newline();
3994 case LyXParagraph::MARGIN:
3995 file += "\\marginpar{\n";
3997 case LyXParagraph::FIG:
3998 if (pextra_type == PEXTRA_FLOATFLT
3999 && (!pextra_width.empty()
4000 || !pextra_widthp.empty())) {
4002 if (!pextra_width.empty())
4003 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
4004 pextra_width.c_str());
4007 "\\begin{floatingfigure}{%f\\textwidth}\n",
4008 atoi(pextra_widthp.c_str())/100.0);
4011 file += "\\begin{figure}";
4012 if (!params->float_placement.empty()) {
4014 file += params->float_placement;
4021 case LyXParagraph::TAB:
4022 file += "\\begin{table}";
4023 if (!params->float_placement.empty()) {
4025 file += params->float_placement;
4031 case LyXParagraph::WIDE_FIG:
4032 file += "\\begin{figure*}";
4033 if (!params->float_placement.empty()) {
4035 file += params->float_placement;
4041 case LyXParagraph::WIDE_TAB:
4042 file += "\\begin{table*}";
4043 if (!params->float_placement.empty()) {
4045 file += params->float_placement;
4051 case LyXParagraph::ALGORITHM:
4052 file += "\\begin{algorithm}\n";
4057 if (footnotekind != LyXParagraph::FOOTNOTE
4058 || !footer_in_body) {
4059 // Process text for all floats except footnotes in body
4061 LyXLayout const & style =
4062 textclasslist.Style(current_view->buffer()->params.textclass,
4065 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4067 if (style.isEnvironment()
4068 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4069 // Allows the use of minipages within float
4070 // environments. Shouldn't be circular because
4071 // we don't support footnotes inside
4072 // floats (yet). ARRae
4073 par = par->TeXEnvironment(file, texrow,
4077 par = par->TeXOnePar(file, texrow,
4082 if (par && !par->IsDummy() && par->depth > depth) {
4083 par = par->TeXDeeper(file, texrow,
4087 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4089 // process footnotes > depth 0 or in environments separately
4090 // NOTE: Currently don't support footnotes within footnotes
4091 // even though that is possible using the \footnotemark
4093 TexRow dummy_texrow;
4094 int dummy_count = 0;
4096 LyXLayout const & style =
4097 textclasslist.Style(current_view->buffer()->params.textclass,
4100 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4102 if (style.isEnvironment()
4103 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4104 // Allows the use of minipages within float
4105 // environments. Shouldn't be circular because
4106 // we don't support footnotes inside
4107 // floats (yet). ARRae
4108 par = par->TeXEnvironment(foot, foot_texrow,
4109 dummy, dummy_texrow,
4112 par = par->TeXOnePar(foot, foot_texrow,
4113 dummy, dummy_texrow,
4117 if (par && !par->IsDummy() && par->depth > depth) {
4118 par = par->TeXDeeper(foot, foot_texrow,
4119 dummy, dummy_texrow,
4123 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4125 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4126 "Footnote in a Footnote -- not supported"
4131 switch (footnotekind) {
4132 case LyXParagraph::FOOTNOTE:
4133 if (footer_in_body) {
4134 // This helps tell which of the multiple
4135 // footnotetexts an error was in.
4137 foot_texrow.newline();
4142 case LyXParagraph::MARGIN:
4145 case LyXParagraph::FIG:
4146 if (pextra_type == PEXTRA_FLOATFLT
4147 && (!pextra_width.empty()
4148 || !pextra_widthp.empty()))
4149 file += "\\end{floatingfigure}";
4151 file += "\\end{figure}";
4153 case LyXParagraph::TAB:
4154 file += "\\end{table}";
4156 case LyXParagraph::WIDE_FIG:
4157 file += "\\end{figure*}";
4159 case LyXParagraph::WIDE_TAB:
4160 file += "\\end{table*}";
4162 case LyXParagraph::ALGORITHM:
4163 file += "\\end{algorithm}";
4167 if (footnotekind != LyXParagraph::FOOTNOTE
4168 && footnotekind != LyXParagraph::MARGIN) {
4169 // we need to ensure that real floats like tables and figures
4170 // have their \end{} on a line of their own otherwise we can
4171 // get incorrect results when using the endfloat.sty package.
4176 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4181 void LyXParagraph::SetPExtraType(int type, char const * width,
4182 char const * widthp)
4185 pextra_width = width;
4186 pextra_widthp = widthp;
4188 if (textclasslist.Style(current_view->buffer()->params.textclass,
4189 layout).isEnvironment()) {
4194 while (par && (par->layout == layout)
4195 && (par->depth == depth)) {
4197 par = par->Previous();
4199 par = par->FirstPhysicalPar();
4200 while (par && par->depth > depth) {
4201 par = par->Previous();
4203 par = par->FirstPhysicalPar();
4207 while (par && (par->layout == layout)
4208 && (par->depth == depth)) {
4209 par->pextra_type = type;
4210 par->pextra_width = width;
4211 par->pextra_widthp = widthp;
4212 par = par->NextAfterFootnote();
4213 if (par && (par->depth > depth))
4214 par->SetPExtraType(type, width, widthp);
4215 while (par && ((par->depth > depth) || par->IsDummy()))
4216 par = par->NextAfterFootnote();
4222 void LyXParagraph::UnsetPExtraType()
4224 if (pextra_type == PEXTRA_NONE)
4227 pextra_type = PEXTRA_NONE;
4228 pextra_width.clear();
4229 pextra_widthp.clear();
4231 if (textclasslist.Style(current_view->buffer()->params.textclass,
4232 layout).isEnvironment()) {
4237 while (par && (par->layout == layout)
4238 && (par->depth == depth)) {
4240 par = par->Previous();
4242 par = par->FirstPhysicalPar();
4243 while (par && par->depth > depth) {
4244 par = par->Previous();
4246 par = par->FirstPhysicalPar();
4250 while (par && (par->layout == layout)
4251 && (par->depth == depth)) {
4252 par->pextra_type = PEXTRA_NONE;
4253 par->pextra_width.clear();
4254 par->pextra_widthp.clear();
4255 par = par->NextAfterFootnote();
4256 if (par && (par->depth > depth))
4257 par->UnsetPExtraType();
4258 while (par && ((par->depth > depth) || par->IsDummy()))
4259 par = par->NextAfterFootnote();
4265 bool LyXParagraph::IsHfill(size_type pos) const
4267 return IsHfillChar(GetChar(pos));
4271 bool LyXParagraph::IsInset(size_type pos) const
4273 return IsInsetChar(GetChar(pos));
4277 bool LyXParagraph::IsFloat(size_type pos) const
4279 return IsFloatChar(GetChar(pos));
4283 bool LyXParagraph::IsNewline(size_type pos) const
4287 tmp = IsNewlineChar(GetChar(pos));
4292 bool LyXParagraph::IsSeparator(size_type pos) const
4294 return IsSeparatorChar(GetChar(pos));
4298 bool LyXParagraph::IsLineSeparator(size_type pos) const
4300 return IsLineSeparatorChar(GetChar(pos));
4304 bool LyXParagraph::IsKomma(size_type pos) const
4306 return IsKommaChar(GetChar(pos));
4310 /// Used by the spellchecker
4311 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4313 unsigned char c = GetChar(pos);
4314 if (IsLetterChar(c))
4316 // '\0' is not a letter, allthough every string contains "" (below)
4319 // We want to pass the ' and escape chars to ispell
4320 string extra = lyxrc->isp_esc_chars + '\'';
4324 return contains(extra, ch);
4328 bool LyXParagraph::IsWord(size_type pos ) const
4330 return IsWordChar(GetChar(pos)) ;