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"
17 #include "lyxparagraph.h"
18 #include "support/textutils.h"
21 #include "tex-strings.h"
22 #include "bufferparams.h"
23 #include "support/FileInfo.h"
25 #include "LaTeXFeatures.h"
26 #include "insets/insetinclude.h"
27 #include "support/filetools.h"
28 #include "lyx_gui_misc.h"
32 extern void addNewlineAndDepth(string & file, int const depth); // Jug 990923
33 extern unsigned char GetCurrentTextClass(); // this should be fixed/removed
34 int tex_code_break_column = 72; // needs non-zero initialization. set later.
35 // this is a bad idea, but how can LyXParagraph find its buffer to get
36 // parameters? (JMarc)
37 extern BufferView * current_view;
42 extern string bibitemWidthest();
44 /* this is a minibuffer */
45 static char minibuffer_char;
46 static LyXFont minibuffer_font;
47 static Inset * minibuffer_inset;
50 // Initialization of the counter for the paragraph id's,
51 // declared in lyxparagraph.h
52 unsigned int LyXParagraph::paragraph_id = 0;
55 LyXParagraph::LyXParagraph()
57 text.reserve(500); // is this number too big?
59 for (int i = 0; i < 10; ++i) setCounter(i , 0);
69 footnoteflag = LyXParagraph::NO_FOOTNOTE;
71 align = LYX_ALIGN_BLOCK;
73 /* table stuff -- begin*/
75 /* table stuff -- end*/
77 bibkey = 0; // ale970302
82 /* this konstruktor inserts the new paragraph in a list */
83 LyXParagraph::LyXParagraph(LyXParagraph * par)
85 #warning we also need a reserve here
86 #warning this would be a nice place to shrink par
87 for (int i = 0; i < 10; ++i) setCounter(i, 0);
93 next->previous = this;
95 previous->next = this;
100 footnoteflag = LyXParagraph::NO_FOOTNOTE;
101 footnotekind = LyXParagraph::FOOTNOTE;
103 /* table stuff -- begin*/
105 /* table stuff -- end*/
106 id_ = paragraph_id++;
108 bibkey = 0; // ale970302
114 void LyXParagraph::writeFile(FILE * file, BufferParams & params,
115 char footflag, char dth)
117 LyXFont font1, font2;
123 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
125 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
127 /* The beginning or the end of a footnote environment? */
128 if (footflag != footnoteflag) {
129 footflag = footnoteflag;
131 fprintf(file, "\n\\begin_float %s ",
132 string_footnotekinds[footnotekind]);
135 fprintf(file, "\n\\end_float ");
139 /* The beginning or end of a deeper (i.e. nested) area? */
142 while (depth > dth) {
143 fprintf(file, "\n\\begin_deeper ");
148 while (depth < dth) {
149 fprintf(file, "\n\\end_deeper ");
155 /* First write the layout */
156 fprintf(file, "\n\\layout %s\n",
157 textclasslist.NameOfLayout(params.textclass, layout)
160 /* maybe some vertical spaces */
161 if (added_space_top.kind() != VSpace::NONE)
162 fprintf(file, "\\added_space_top %s ",
163 added_space_top.asLyXCommand().c_str());
164 if (added_space_bottom.kind() != VSpace::NONE)
165 fprintf(file, "\\added_space_bottom %s ",
166 added_space_bottom.asLyXCommand().c_str());
168 /* The labelwidth string used in lists */
169 if (!labelwidthstring.empty())
170 fprintf(file, "\\labelwidthstring %s\n",
171 labelwidthstring.c_str());
173 /* Lines above or below? */
175 fprintf(file, "\\line_top ");
177 fprintf(file, "\\line_bottom ");
179 /* Pagebreaks above or below? */
181 fprintf(file, "\\pagebreak_top ");
182 if (pagebreak_bottom)
183 fprintf(file, "\\pagebreak_bottom ");
185 /* Start of appendix? */
186 if (start_of_appendix)
187 fprintf(file, "\\start_of_appendix ");
191 fprintf(file, "\\noindent ");
194 if (align != LYX_ALIGN_LAYOUT) {
196 case LYX_ALIGN_LEFT: h = 1; break;
197 case LYX_ALIGN_RIGHT: h = 2; break;
198 case LYX_ALIGN_CENTER: h = 3; break;
199 default: h = 0; break;
201 fprintf(file, "\\align %s ", string_align[h]);
203 if (pextra_type != PEXTRA_NONE) {
204 fprintf(file, "\\pextra_type %d", pextra_type);
205 if (pextra_type == PEXTRA_MINIPAGE) {
206 fprintf(file, " \\pextra_alignment %d",
209 fprintf(file, " \\pextra_hfill %d",
211 if (pextra_start_minipage)
213 " \\pextra_start_minipage %d",
214 pextra_start_minipage);
216 if (!pextra_width.empty()) {
217 fprintf(file, " \\pextra_width %s",
219 .asLyXCommand().c_str());
220 } else if (!pextra_widthp.empty()) {
221 fprintf(file, " \\pextra_widthp %s",
222 pextra_widthp.c_str());
228 /* Dummy layout. This means that a footnote ended */
229 fprintf(file, "\n\\end_float ");
230 footflag = LyXParagraph::NO_FOOTNOTE;
233 /* It might be a table */
235 fprintf(file, "\\LyXTable\n");
243 font1 = LyXFont(LyXFont::ALL_INHERIT);
246 for (size_type i = 0; i < size(); i++) {
252 // Write font changes
253 font2 = GetFontSettings(i);
254 if (font2 != font1) {
255 font2.lyxWriteChanges(font1, file);
265 if (inset->DirectWrite()) {
266 // international char, let it write
267 // code directly so it's shorter in
271 fprintf(file, "\n\\begin_inset ");
273 fprintf(file, "\n\\end_inset \n");
279 fprintf(file, "\n\\newline \n");
283 fprintf(file, "\n\\hfill \n");
286 case META_PROTECTED_SEPARATOR:
287 fprintf(file, "\n\\protected_separator \n");
291 fprintf(file, "\n\\backslash \n");
295 if (i + 1 < size() && GetChar(i + 1) == ' ') {
296 fprintf(file, ".\n");
302 if ((column > 70 && c == ' ')
307 // this check is to amend a bug. LyX sometimes
308 // inserts '\0' this could cause problems.
310 fprintf(file, "%c", c);
312 lyxerr << "ERROR (LyXParagraph::writeFile):"
313 " NULL char in structure." << endl;
319 // now write the next paragraph
321 next->writeFile(file, params, footflag, dth);
325 void LyXParagraph::validate(LaTeXFeatures & features)
327 // this will be useful later
328 LyXLayout const & layout = textclasslist.Style(GetCurrentTextClass(),
332 if (line_top || line_bottom)
333 features.lyxline = true;
336 features.layout[GetLayout()] = true;
339 for (FontList::const_iterator cit = fontlist.begin();
340 cit != fontlist.end(); ++cit) {
341 if ((*cit).font.noun() == LyXFont::ON) {
342 lyxerr[Debug::LATEX] << "font.noun: "
343 << (*cit).font.noun()
345 features.noun = true;
346 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
347 << (*cit).font.stateText()
350 switch ((*cit).font.color()) {
352 case LyXFont::INHERIT_COLOR:
353 case LyXFont::IGNORE_COLOR: break;
355 features.color = true;
356 lyxerr[Debug::LATEX] << "Color enabled. Font: "
357 << (*cit).font.stateText()
363 FontTable * tmpfonttable = fonttable;
364 while (tmpfonttable) {
365 if (tmpfonttable->font.noun() == LyXFont::ON) {
366 lyxerr[Debug::LATEX] << "font.noun: "
367 << tmpfonttable->font.noun()
369 features.noun = true;
370 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
371 << tmpfonttable->font.stateText()
374 switch (tmpfonttable->font.color()) {
376 case LyXFont::INHERIT_COLOR:
377 case LyXFont::IGNORE_COLOR:
380 features.color = true;
381 lyxerr[Debug::LATEX] << "Color enabled. Font: "
382 << tmpfonttable->font.stateText()
385 tmpfonttable = tmpfonttable->next;
389 for (InsetList::const_iterator cit = insetlist.begin();
390 cit != insetlist.end(); ++cit) {
391 (*cit).inset->Validate(features);
395 InsetTable * tmpinsettable = insettable;
396 while (tmpinsettable) {
397 if (tmpinsettable->inset) {
398 tmpinsettable->inset->Validate(features);
400 tmpinsettable = tmpinsettable->next;
403 if (table && table->IsLongTable())
404 features.longtable = true;
405 if (pextra_type == PEXTRA_INDENT)
406 features.LyXParagraphIndent = true;
407 if (pextra_type == PEXTRA_FLOATFLT)
408 features.floatflt = true;
409 if (layout.needprotect
410 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
411 features.NeedLyXFootnoteCode = true;
412 if ((current_view->buffer()->params.paragraph_separation == BufferParams::PARSEP_INDENT) &&
413 (pextra_type == LyXParagraph::PEXTRA_MINIPAGE))
414 features.NeedLyXMinipageIndent = true;
415 if (table && table->NeedRotating())
416 features.rotating = true;
417 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
418 features.algorithm = true;
422 /* first few functions needed for cut and paste and paragraph breaking */
423 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos) const
425 minibuffer_char = GetChar(pos);
426 minibuffer_font = GetFontSettings(pos);
427 minibuffer_inset = 0;
428 if (minibuffer_char == LyXParagraph::META_INSET) {
430 minibuffer_inset = GetInset(pos)->Clone();
432 minibuffer_inset = 0;
433 minibuffer_char = ' ';
434 // This reflects what GetInset() does (ARRae)
439 void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos)
441 minibuffer_char = GetChar(pos);
442 minibuffer_font = GetFontSettings(pos);
443 minibuffer_inset = 0;
444 if (minibuffer_char == LyXParagraph::META_INSET) {
446 minibuffer_inset = GetInset(pos);
447 // This is a little hack since I want exactly
448 // the inset, not just a clone. Otherwise
449 // the inset would be deleted when calling Erase(pos)
451 for (InsetList::iterator it = insetlist.begin();
452 it != insetlist.end(); ++it) {
453 if ((*it).pos == pos) {
460 InsetTable * tmpi = insettable;
461 while (tmpi && tmpi->pos != pos) {
464 if (tmpi) { /* This should always be true */
469 minibuffer_inset = 0;
470 minibuffer_char = ' ';
471 // This reflects what GetInset() does (ARRae)
476 /* Erase(pos); now the caller is responsible for that*/
480 void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
482 InsertChar(pos, minibuffer_char);
483 SetFont(pos, minibuffer_font);
484 if (minibuffer_char == LyXParagraph::META_INSET)
485 InsertInset(pos, minibuffer_inset);
488 /* end of minibuffer */
492 void LyXParagraph::Clear()
497 pagebreak_top = false;
498 pagebreak_bottom = false;
500 added_space_top = VSpace(VSpace::NONE);
501 added_space_bottom = VSpace(VSpace::NONE);
503 align = LYX_ALIGN_LAYOUT;
507 pextra_type = PEXTRA_NONE;
508 pextra_width.clear();
509 pextra_widthp.clear();
510 pextra_alignment = MINIPAGE_ALIGN_TOP;
511 pextra_hfill = false;
512 pextra_start_minipage = false;
515 labelwidthstring.clear();
519 start_of_appendix = false;
523 /* the destructor removes the new paragraph from the list */
524 LyXParagraph::~LyXParagraph()
527 previous->next = next;
529 next->previous = previous;
532 InsetTable * tmpinset;
534 tmpinset = insettable;
535 insettable = insettable->next;
537 delete tmpinset->inset;
539 if (insettable && insettable->next == insettable) {
540 // somehow this recursion appears occasionally
541 // but I can't find where. This bandaid
542 // helps but isn't the best fix. (ARRae)
543 if (insettable->inset) {
544 delete insettable->inset;
554 fonttable = fonttable->next;
559 /* table stuff -- begin*/
562 /* table stuff -- end*/
570 void LyXParagraph::Erase(LyXParagraph::size_type pos)
572 /* > because last is the next unused position, and you can
573 * use it if you want */
575 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
576 NextAfterFootnote()->Erase(pos - text.size() - 1);
578 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
579 "position does not exist." << endl;
582 if (pos < size()) { // last is free for insertation, but should be empty
584 /* if it is an inset, delete the inset entry */
585 if (text[pos] == LyXParagraph::META_INSET) {
587 for(InsetList::iterator it = insetlist.begin();
588 it != insetlist.end(); ++it) {
589 if ((*it).pos == pos) {
597 /* if it is an inset, delete the inset entry */
598 if (text[pos] == LyXParagraph::META_INSET) {
600 InsetTable *tmpi = insettable;
601 InsetTable *tmpi2 = tmpi;
602 while (tmpi && tmpi->pos != pos) {
606 if (tmpi) { // this should always be true
607 if (tmpi->inset) // delete the inset if it exists
609 if (tmpi == insettable)
610 insettable = tmpi->next;
612 tmpi2->next = tmpi->next;
617 text.erase(text.begin() + pos);
619 /* erase entries in the tables */
620 for(FontList::iterator it = fontlist.begin();
621 it != fontlist.end(); ++it) {
622 if (pos >= (*it).pos && pos <= (*it).pos_end) {
623 if ((*it).pos == (*it).pos_end) {
630 /* update all other entries */
631 for(FontList::iterator it = fontlist.begin();
632 it != fontlist.end(); ++it) {
635 if ((*it).pos_end >= pos)
639 /* update the inset table */
640 for(InsetList::iterator it = insetlist.begin();
641 it != insetlist.end(); ++it) {
646 /* erase entries in the tables */
648 FontTable * tmp = fonttable;
649 FontTable * prev = 0;
650 while (tmp && !found) {
651 if (pos >= tmp->pos && pos <= tmp->pos_end)
659 if (found && tmp->pos == tmp->pos_end) {
660 /* if it is a multi-character font entry, we just make
661 * it smaller (see update below), otherwise we should
664 prev->next = tmp->next;
666 fonttable = tmp->next;
671 /* update all other entries */
677 if (tmp->pos_end >= pos)
682 /* update the inset table */
683 InsetTable * tmpi = insettable;
691 lyxerr << "ERROR (LyXParagraph::Erase): "
692 "can't erase non-existant char." << endl;
697 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
699 /* > because last is the next unused position, and you can
700 * use it if you want */
703 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
704 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
707 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
708 "position does not exist." << endl;
711 text.insert(text.begin() + pos, c);
713 // update the font table
714 for(FontList::iterator it = fontlist.begin();
715 it != fontlist.end(); ++it) {
716 if ((*it).pos >= pos)
718 if ((*it).pos_end >= pos)
721 // update the inset table
722 for(InsetList::iterator it = insetlist.begin();
723 it != insetlist.end(); ++it) {
724 if ((*it).pos >= pos)
728 /* update the font table */
729 FontTable * tmp = fonttable;
733 if (tmp->pos_end >= pos)
738 /* update the inset table */
739 InsetTable * tmpi = insettable;
741 if (tmpi->pos >= pos)
749 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
752 /* > because last is the next unused position, and you can
753 * use it if you want */
756 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
758 ->InsertInset(pos - text.size() - 1, inset);
760 lyxerr << "ERROR (LyXParagraph::InsertInset): "
761 "position does not exist: " << pos << endl;
764 if (text[pos] != LyXParagraph::META_INSET) {
765 lyxerr << "ERROR (LyXParagraph::InsertInset): "
766 "there is no LyXParagraph::META_INSET" << endl;
775 insetlist.push_back(tmp);
780 /* add a new entry in the inset table */
781 InsetTable * tmpi = new InsetTable;
784 tmpi->next = insettable;
791 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
795 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
796 return NextAfterFootnote()
797 ->GetInset(pos - text.size() - 1);
799 lyxerr << "ERROR (LyXParagraph::GetInset): "
800 "position does not exist: "
807 for(InsetList::iterator it = insetlist.begin();
808 it != insetlist.end(); ++it) {
809 if ((*it).pos == pos) {
813 lyxerr << "ERROR (LyXParagraph::GetInset): "
814 "Inset does not exist: " << pos << endl;
815 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
816 // Did this commenting out introduce a bug? So far I have not
817 // seen any, please enlighten me. (Lgb)
818 // My guess is that since the inset does not exist, we might
819 // as well replace it with a space to prevent crashes. (Asger)
823 InsetTable * tmpi = insettable;
825 while (tmpi && tmpi->pos != pos)
831 lyxerr << "ERROR (LyXParagraph::GetInset): "
832 "Inset does not exist: " << pos << endl;
833 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
834 // Did this commenting out introduce a bug? So far I have not
835 // seen any, please enlighten me. (Lgb)
836 // My guess is that since the inset does not exist, we might
837 // as well replace it with a space to prevent crashes. (Asger)
844 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
848 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
849 return NextAfterFootnote()
850 ->GetInset(pos - text.size() - 1);
852 lyxerr << "ERROR (LyXParagraph::GetInset): "
853 "position does not exist: "
860 for(InsetList::const_iterator cit = insetlist.begin();
861 cit != insetlist.end(); ++cit) {
862 if ((*cit).pos == pos) {
866 lyxerr << "ERROR (LyXParagraph::GetInset): "
867 "Inset does not exist: " << pos << endl;
868 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
869 // Did this commenting out introduce a bug? So far I have not
870 // seen any, please enlighten me. (Lgb)
871 // My guess is that since the inset does not exist, we might
872 // as well replace it with a space to prevent crashes. (Asger)
876 InsetTable * tmpi = insettable;
878 while (tmpi && tmpi->pos != pos)
884 lyxerr << "ERROR (LyXParagraph::GetInset): "
885 "Inset does not exist: " << pos << endl;
886 // in the const version we need to comment it out anyway...
887 //text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
888 // Did this commenting out introduce a bug? So far I have not
889 // seen any, please enlighten me. (Lgb)
890 // My guess is that since the inset does not exist, we might
891 // as well replace it with a space to prevent crashes. (Asger)
898 // Gets uninstantiated font setting at position.
899 // Optimized after profiling. (Asger)
900 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos) const
904 for(FontList::iterator it = fontlist.begin();
905 it != fontlist.end(); ++it) {
906 if (pos >= (*it).pos && pos <= (*it).pos_end)
910 FontTable * tmp = fonttable;
912 if (pos >= tmp->pos && pos <= tmp->pos_end)
918 /* > because last is the next unused position, and you can
919 * use it if you want */
920 else if (pos > size()) {
922 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
923 return NextAfterFootnote()
924 ->GetFontSettings(pos - text.size() - 1);
926 // Why is it an error to ask for the font of a
927 // position that does not exist? Would it be
928 // enough for this to be anable on debug?
929 // We want strict error checking, but it's ok to only
930 // have it when debugging. (Asger)
931 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
932 "position does not exist. "
933 << pos << " (" << static_cast<int>(pos)
937 return GetFontSettings(pos - 1);
939 return LyXFont(LyXFont::ALL_INHERIT);
943 // Gets the fully instantiated font at a given position in a paragraph
944 // This is basically the same function as LyXText::GetFont() in text2.C.
945 // The difference is that this one is used for generating the LaTeX file,
946 // and thus cosmetic "improvements" are disallowed: This has to deliver
947 // the true picture of the buffer. (Asger)
948 // If position is -1, we get the layout font of the paragraph.
949 // If position is -2, we get the font of the manual label of the paragraph.
950 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos) const
953 LyXLayout const & layout = textclasslist.Style(GetCurrentTextClass(),
955 LyXParagraph::size_type main_body = 0;
956 if (layout.labeltype == LABEL_MANUAL)
957 main_body = BeginningOfMainBody();
962 layoutfont = layout.labelfont;
964 layoutfont = layout.font;
965 tmpfont = GetFontSettings(pos);
966 tmpfont.realize(layoutfont);
968 // process layoutfont for pos == -1 and labelfont for pos < -1
970 tmpfont = layout.font;
972 tmpfont = layout.labelfont;
975 // check for environment font information
976 char par_depth = GetDepth();
977 LyXParagraph const * par = this;
978 while (par && par_depth && !tmpfont.resolved()) {
979 par = par->DepthHook(par_depth - 1);
981 tmpfont.realize(textclasslist.
982 Style(GetCurrentTextClass(),
983 par->GetLayout()).font);
984 par_depth = par->GetDepth();
988 tmpfont.realize(textclasslist.TextClass(GetCurrentTextClass()).defaultfont());
993 /// Returns the height of the highest font in range
994 LyXFont::FONT_SIZE LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos, LyXParagraph::size_type endpos) const
996 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
998 for(FontList::const_iterator cit = fontlist.begin();
999 cit != fontlist.end(); ++cit) {
1000 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
1001 LyXFont::FONT_SIZE size = (*cit).font.size();
1002 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
1007 FontTable * tmp = fonttable;
1009 if (startpos <= tmp->pos_end && endpos >= tmp->pos) {
1010 LyXFont::FONT_SIZE size = tmp->font.size();
1011 if (size > maxsize && size<= LyXFont::SIZE_HUGER)
1021 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
1023 #ifdef DEVEL_VERSION
1024 /* a workaround to 'fix' some bugs in text-class */
1026 // This function is important. It should not work around bugs.
1027 // Let's find the bugs instead and fix them. (Asger)
1028 lyxerr << "FATAL ERROR (LyXParagraph::GetChar):"
1029 " bad position " << pos << endl;
1037 /* > because last is the next unused position, and you can
1038 * use it if you want */
1039 else if (pos > size()) {
1040 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1041 return NextAfterFootnote()
1042 ->GetChar(pos - text.size() - 1);
1044 lyxerr << "ERROR (LyXParagraph::GetChar): "
1045 "position does not exist."
1046 << pos << " (" << static_cast<int>(pos)
1051 /* we should have a footnote environment */
1052 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
1053 // Notice that LyX does request the
1054 // last char from time to time. (Asger)
1055 //lyxerr << "ERROR (LyXParagraph::GetChar): "
1056 // "expected footnote." << endl;
1059 switch (next->footnotekind) {
1060 case LyXParagraph::FOOTNOTE:
1061 return LyXParagraph::META_FOOTNOTE;
1062 case LyXParagraph::MARGIN:
1063 return LyXParagraph::META_MARGIN;
1064 case LyXParagraph::FIG:
1065 case LyXParagraph::WIDE_FIG:
1066 return LyXParagraph::META_FIG;
1067 case LyXParagraph::TAB:
1068 case LyXParagraph::WIDE_TAB:
1069 return LyXParagraph::META_TAB;
1070 case LyXParagraph::ALGORITHM:
1071 return LyXParagraph::META_ALGORITHM;
1073 return '\0'; // to shut up gcc
1078 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
1080 #ifdef DEVEL_VERSION
1081 /* a workaround to 'fix' some bugs in text-class */
1083 // This function is important. It should not work around bugs.
1084 // Let's find the bugs instead and fix them. (Asger)
1085 lyxerr << "FATAL ERROR (LyXParagraph::GetChar):"
1086 " bad position " << pos << endl;
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): "
1102 "position does not exist."
1103 << pos << " (" << static_cast<int>(pos)
1108 /* we should have a footnote environment */
1109 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
1110 // Notice that LyX does request the
1111 // last char from time to time. (Asger)
1112 //lyxerr << "ERROR (LyXParagraph::GetChar): "
1113 // "expected footnote." << endl;
1116 switch (next->footnotekind) {
1117 case LyXParagraph::FOOTNOTE:
1118 return LyXParagraph::META_FOOTNOTE;
1119 case LyXParagraph::MARGIN:
1120 return LyXParagraph::META_MARGIN;
1121 case LyXParagraph::FIG:
1122 case LyXParagraph::WIDE_FIG:
1123 return LyXParagraph::META_FIG;
1124 case LyXParagraph::TAB:
1125 case LyXParagraph::WIDE_TAB:
1126 return LyXParagraph::META_TAB;
1127 case LyXParagraph::ALGORITHM:
1128 return LyXParagraph::META_ALGORITHM;
1130 return '\0'; // to shut up gcc
1135 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
1136 //Added 98/9/21 by REH
1137 // return an string of the current word, and the end of the word
1140 // the current word is defined as starting at the first character from
1141 // the immediate left of lastpospos which meets the definition of IsLetter(),
1142 // continuing to the last character to the right of this meeting
1146 // i just left this in from GetChar()
1148 #ifdef DEVEL_VERSION
1149 /* a workaround to 'fix' some bugs in text-class */
1151 // This function is important. It should not work around bugs.
1152 // Let's find the bugs instead and fix them. (Asger)
1153 lyxerr << "FATAL ERROR (LyXParagraph::GetWord):"
1154 " bad position " << lastpos << endl;
1164 //i think the devcode aborts before this, but why not be
1166 if (lastpos < 0) lastpos= 0;
1169 // move back until we have a letter
1171 //there's no real reason to have firstpos & lastpos as
1172 //separate variables as this is written, but maybe someon
1173 // will want to return firstpos in the future.
1175 //since someone might have typed a punctuation first
1176 int firstpos = lastpos;
1178 while ((firstpos >= 0) && !IsLetter(firstpos))
1181 // now find the beginning by looking for a nonletter
1183 while ((firstpos>= 0) && IsLetter(firstpos))
1186 // the above is now pointing to the preceeding non-letter
1190 // so copy characters into theword until we get a nonletter
1191 // note that this can easily exceed lastpos, wich means
1192 // that if used in the middle of a word, the whole word
1195 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1202 LyXParagraph::size_type LyXParagraph::Last() const
1204 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1205 return text.size() + NextAfterFootnote()->Last() + 1;
1206 /* the 1 is the symbol
1213 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
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 ->ParFromPos(pos - text.size() - 1);
1223 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1224 "position does not exist." << endl;
1232 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
1234 /* > because last is the next unused position, and you can
1235 * use it if you want */
1238 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1239 return NextAfterFootnote()
1240 ->PositionInParFromPos(pos - text.size() - 1);
1243 "ERROR (LyXParagraph::PositionInParFromPos): "
1244 "position does not exist." << endl;
1252 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1253 LyXFont const & font)
1255 /* > because last is the next unused position, and you can
1256 * use it if you want */
1258 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1259 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1262 lyxerr << "ERROR (LyXParagraph::SetFont): "
1263 "position does not exist." << endl;
1267 LyXFont patternfont(LyXFont::ALL_INHERIT);
1269 // First, reduce font against layout/label font
1270 // Update: The SetCharFont() routine in text2.C already reduces font, so
1271 // we don't need to do that here. (Asger)
1272 // No need to simplify this because it will disappear in a new kernel. (Asger)
1274 // Next search font table
1275 for(FontList::iterator it = fontlist.begin();
1276 it != fontlist.end(); ++it) {
1277 if (pos >= (*it).pos && pos <= (*it).pos_end) {
1279 // we found a font entry. maybe we have to
1280 // split it and create a new one
1282 if ((*it).pos != (*it).pos_end) {
1283 // more than one character
1284 if (pos == (*it).pos) {
1285 // maybe we could enlarge
1286 // the left fonttable
1287 for(FontList::iterator fit = fontlist.begin();
1288 fit != fontlist.end(); ++fit) {
1289 if (pos - 1 >= (*fit).pos
1290 && pos - 1 <= (*fit).pos_end
1291 && (*fit).font == font) {
1299 // Add a new entry in the
1300 // fonttable for the position
1303 tmp.pos_end = (*it).pos_end;
1304 tmp.font = (*it).font;
1305 (*it).pos_end = pos;
1306 fontlist.push_back(tmp);
1307 } else if (pos == (*it).pos_end) {
1308 // Add a new entry in the
1309 // fonttable for the position
1311 tmp.pos = (*it).pos;
1312 tmp.pos_end = (*it).pos_end - 1;
1313 tmp.font = (*it).font;
1314 (*it).pos = (*it).pos_end;
1315 fontlist.push_back(tmp);
1317 // Add a new entry in the
1318 // fonttable for the position
1320 tmp.pos = (*it).pos;
1321 tmp.pos_end = pos - 1;
1322 tmp.font = (*it).font;
1323 fontlist.push_back(tmp);
1326 tmp.pos_end = (*it).pos_end;
1327 tmp.font = (*it).font;
1328 fontlist.push_back(tmp);
1331 (*it).pos_end = pos;
1339 // if we did not find a font entry, but if the font at hand
1340 // is the same as default, we just forget it
1341 if (font == patternfont) return;
1343 // ok, we did not find a font entry. But maybe there is exactly
1344 // the needed font entry one position left
1345 for(FontList::iterator it = fontlist.begin();
1346 it != fontlist.end(); ++it) {
1347 if (pos - 1 >= (*it).pos && pos - 1 <= (*it).pos_end
1348 && (*it).font == font) {
1353 // Add a new entry in the
1354 // fonttable for the position
1358 tmp.font = patternfont;
1359 fontlist.push_back(tmp);
1361 // Next search font table
1365 FontTable * tmp = fonttable;
1366 while (tmp && !found) {
1367 if (pos >= tmp->pos && pos <= tmp->pos_end)
1374 /* if we did not find a font entry, but if the font at hand
1375 * is the same as default, we just forget it */
1376 if (font == patternfont)
1379 /* ok, we did not find a font entry. But maybe there is exactly
1380 * the needed font entry one position left */
1383 while (tmp2 && !found) {
1384 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1390 /* ok there is one. maybe it is exactly the needed font */
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;
1403 tmp->next = fonttable;
1406 /* we found a font entry. maybe we have to split it and create
1409 if (tmp->pos != tmp->pos_end) { /* more than one character */
1411 if (pos == tmp->pos) {
1412 /* maybe we could enlarge the left fonttable */
1416 while (tmp2 && !found) {
1417 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1423 /* Is there is one, and is it exactly the needed font? */
1424 if (found && tmp2->font == font) {
1425 /* put the position under the font */
1431 /* Add a new entry in the
1432 * fonttable for the position */
1433 tmp2 = new FontTable;
1434 tmp2->pos = pos + 1;
1435 tmp2->pos_end = tmp->pos_end;
1436 tmp2->font = tmp->font;
1438 tmp2->next = fonttable;
1441 else if (pos == tmp->pos_end) {
1442 /* Add a new entry in the
1443 * fonttable for the position */
1444 tmp2 = new FontTable;
1445 tmp2->pos = tmp->pos;
1446 tmp2->pos_end = tmp->pos_end - 1;
1447 tmp2->font = tmp->font;
1448 tmp->pos = tmp->pos_end;
1449 tmp2->next = fonttable;
1453 /* Add a new entry in the
1454 * fonttable for the position */
1455 tmp2 = new FontTable;
1456 tmp2->pos = tmp->pos;
1457 tmp2->pos_end = pos - 1;
1458 tmp2->font = tmp->font;
1459 tmp2->next = fonttable;
1462 tmp2 = new FontTable;
1463 tmp2->pos = pos + 1;
1464 tmp2->pos_end = tmp->pos_end;
1465 tmp2->font = tmp->font;
1466 tmp2->next = fonttable;
1479 /* this function is able to hide closed footnotes */
1480 LyXParagraph * LyXParagraph::Next()
1482 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1483 LyXParagraph * tmp = next;
1485 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1487 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1488 return tmp->Next(); /* there can be more than one
1489 footnote in a logical
1492 return next; /* this should never happen! */
1499 LyXParagraph * LyXParagraph::NextAfterFootnote()
1501 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1502 LyXParagraph * tmp = next;
1503 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1505 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1506 return tmp; /* there can be more than one footnote
1507 in a logical paragraph */
1509 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! */
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! */
1551 LyXParagraph * LyXParagraph::LastPhysicalPar()
1553 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1556 LyXParagraph * tmp = this;
1558 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1559 tmp = tmp->NextAfterFootnote();
1566 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1570 LyXParagraph * tmppar = this;
1572 while (tmppar && (tmppar->IsDummy()
1573 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1574 tmppar = tmppar->previous;
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 return this; /* this should never happen! */
1600 /* this function is able to hide closed footnotes */
1601 LyXParagraph * LyXParagraph::Previous()
1603 LyXParagraph * tmp = previous;
1608 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1609 tmp = tmp->previous;
1611 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1612 tmp = tmp->previous;
1613 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1614 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();
1648 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1651 size_type i, pos_end, pos_first;
1652 /* create a new paragraph */
1653 LyXParagraph * par = ParFromPos(pos);
1654 LyXParagraph * firstpar = FirstPhysicalPar();
1656 LyXParagraph * tmp = new LyXParagraph(par);
1658 tmp->footnoteflag = footnoteflag;
1659 tmp->footnotekind = footnotekind;
1661 /* this is an idea for a more userfriendly layout handling, I will
1662 * see what the users say */
1664 /* layout stays the same with latex-environments */
1666 tmp->SetOnlyLayout(firstpar->layout);
1667 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1670 if (Last() > pos || !Last() || flag == 2) {
1671 tmp->SetOnlyLayout(firstpar->layout);
1672 tmp->align = firstpar->align;
1673 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1675 tmp->line_bottom = firstpar->line_bottom;
1676 firstpar->line_bottom = false;
1677 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1678 firstpar->pagebreak_bottom = false;
1679 tmp->added_space_bottom = firstpar->added_space_bottom;
1680 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1682 tmp->depth = firstpar->depth;
1683 tmp->noindent = firstpar->noindent;
1685 /* copy everything behind the break-position
1686 to the new paragraph
1689 while (ParFromPos(pos_first) != par)
1692 pos_end = pos_first + par->text.size() - 1;
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);
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 size_type i, pos_end, pos_first;
1841 /* create a new paragraph */
1842 LyXParagraph * par = ParFromPos(pos);
1844 LyXParagraph * tmp = new LyXParagraph(par);
1846 tmp->MakeSameLayout(par);
1849 /* copy everything behind the break-position to the new
1852 while (ParFromPos(pos_first) != par)
1854 pos_end = pos_first + par->text.size() - 1;
1855 /* make shure 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 tmp->text.reserve(pos_end - pos);
1862 for (i = pos; i <= pos_end; i++) {
1864 par->CutIntoMinibuffer(i - pos_first);
1865 tmp->InsertFromMinibuffer(i - pos);
1867 for (i = pos_end; i >= pos; i--)
1868 par->Erase(i - pos_first);
1870 par->text.resize(par->text.size());
1875 /* be carefull, this does not make any check at all */
1876 void LyXParagraph::PasteParagraph()
1878 /* copy the next paragraph to this one */
1879 LyXParagraph * the_next = Next();
1881 LyXParagraph * firstpar = FirstPhysicalPar();
1883 /* first the DTP-stuff */
1884 firstpar->line_bottom = the_next->line_bottom;
1885 firstpar->added_space_bottom = the_next->added_space_bottom;
1886 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1888 size_type pos_end = the_next->text.size() - 1;
1889 size_type pos_insert = Last();
1892 /* ok, now copy the paragraph */
1893 for (i = 0; i <= pos_end; i++) {
1894 the_next->CutIntoMinibuffer(i);
1895 InsertFromMinibuffer(pos_insert + i);
1898 /* delete the next paragraph */
1903 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1905 LyXParagraph * par = ParFromPos(pos);
1907 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1908 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1914 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1916 LyXParagraph * par = ParFromPos(pos);
1918 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1919 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1925 LyXTextClass::LayoutList::size_type LyXParagraph::GetLayout() const
1927 return FirstPhysicalPar()->layout;
1931 char LyXParagraph::GetDepth() const
1933 return FirstPhysicalPar()->depth;
1937 char LyXParagraph::GetAlign() const
1939 return FirstPhysicalPar()->align;
1943 string LyXParagraph::GetLabestring() const
1945 return FirstPhysicalPar()->labelstring;
1949 int LyXParagraph::GetFirstCounter(int i) const
1951 return FirstPhysicalPar()->counter_[i];
1955 /* the next two functions are for the manual labels */
1956 string LyXParagraph::GetLabelWidthString() const
1958 if (!FirstPhysicalPar()->labelwidthstring.empty())
1959 return FirstPhysicalPar()->labelwidthstring;
1961 return _("Senseless with this layout!");
1965 void LyXParagraph::SetLabelWidthString(string const & s)
1967 LyXParagraph * par = FirstPhysicalPar();
1969 par->labelwidthstring = s;
1973 void LyXParagraph::SetOnlyLayout(LyXTextClass::LayoutList::size_type new_layout)
1975 LyXParagraph * par = FirstPhysicalPar();
1976 LyXParagraph * ppar = 0;
1977 LyXParagraph * npar = 0;
1979 par->layout = new_layout;
1980 /* table stuff -- begin*/
1983 /* table stuff -- end*/
1984 if (par->pextra_type == PEXTRA_NONE) {
1985 if (par->Previous()) {
1986 ppar = par->Previous()->FirstPhysicalPar();
1989 && (ppar->depth > par->depth))
1990 ppar = ppar->Previous()->FirstPhysicalPar();
1993 npar = par->Next()->NextAfterFootnote();
1996 && (npar->depth > par->depth))
1997 npar = npar->Next()->NextAfterFootnote();
1999 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
2001 p1 = ppar->pextra_width,
2002 p2 = ppar->pextra_widthp;
2003 ppar->SetPExtraType(ppar->pextra_type,
2004 p1.c_str(), p2.c_str());
2006 if ((par->pextra_type == PEXTRA_NONE) &&
2007 npar && (npar->pextra_type != PEXTRA_NONE)) {
2009 p1 = npar->pextra_width,
2010 p2 = npar->pextra_widthp;
2011 npar->SetPExtraType(npar->pextra_type,
2012 p1.c_str(), p2.c_str());
2018 void LyXParagraph::SetLayout(LyXTextClass::LayoutList::size_type new_layout)
2021 * par = FirstPhysicalPar(),
2025 par->layout = new_layout;
2026 par->labelwidthstring.clear();
2027 par->align = LYX_ALIGN_LAYOUT;
2028 par->added_space_top = VSpace(VSpace::NONE);
2029 par->added_space_bottom = VSpace(VSpace::NONE);
2030 /* table stuff -- begin*/
2033 /* table stuff -- end*/
2034 if (par->pextra_type == PEXTRA_NONE) {
2035 if (par->Previous()) {
2036 ppar = par->Previous()->FirstPhysicalPar();
2039 && (ppar->depth > par->depth))
2040 ppar = ppar->Previous()->FirstPhysicalPar();
2043 npar = par->Next()->NextAfterFootnote();
2046 && (npar->depth > par->depth))
2047 npar = npar->Next()->NextAfterFootnote();
2049 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
2051 p1 = ppar->pextra_width,
2052 p2 = ppar->pextra_widthp;
2053 ppar->SetPExtraType(ppar->pextra_type,
2054 p1.c_str(), p2.c_str());
2056 if ((par->pextra_type == PEXTRA_NONE) &&
2057 npar && (npar->pextra_type != PEXTRA_NONE)) {
2059 p1 = npar->pextra_width,
2060 p2 = npar->pextra_widthp;
2061 npar->SetPExtraType(npar->pextra_type,
2062 p1.c_str(), p2.c_str());
2068 /* if the layout of a paragraph contains a manual label, the beginning of the
2069 * main body is the beginning of the second word. This is what the par-
2070 * function returns. If the layout does not contain a label, the main
2071 * body always starts with position 0. This differentiation is necessary,
2072 * because there cannot be a newline or a blank <= the beginning of the
2073 * main body in TeX. */
2075 int LyXParagraph::BeginningOfMainBody() const
2077 if (FirstPhysicalPar() != this)
2080 // Unroll the first two cycles of the loop
2081 // and remember the previous character to
2082 // remove unnecessary GetChar() calls
2085 && GetChar(i) != LyXParagraph::META_NEWLINE) {
2087 char previous_char, temp;
2089 && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
2090 // Yes, this ^ is supposed to be "= " not "== "
2093 && previous_char != ' '
2094 && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
2096 previous_char = temp;
2101 if (i == 0 && i == size() &&
2102 !(footnoteflag == LyXParagraph::NO_FOOTNOTE
2103 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
2104 i++; /* the cursor should not jump
2105 * to the main body if there
2111 LyXParagraph * LyXParagraph::DepthHook(int deth)
2113 LyXParagraph * newpar = this;
2118 newpar = newpar->FirstPhysicalPar()->Previous();
2119 } while (newpar && newpar->GetDepth() > deth
2120 && newpar->footnoteflag == footnoteflag);
2123 if (Previous() || GetDepth())
2124 lyxerr << "ERROR (LyXParagraph::DepthHook): "
2128 return newpar->FirstPhysicalPar();
2132 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
2134 LyXParagraph const * newpar = this;
2139 newpar = newpar->FirstPhysicalPar()->Previous();
2140 } while (newpar && newpar->GetDepth() > deth
2141 && newpar->footnoteflag == footnoteflag);
2144 if (Previous() || GetDepth())
2145 lyxerr << "ERROR (LyXParagraph::DepthHook): "
2149 return newpar->FirstPhysicalPar();
2153 int LyXParagraph::AutoDeleteInsets()
2157 for (InsetList::iterator it = insetlist.begin();
2158 it != insetlist.end(); ++it) {
2159 if ((*it).inset->AutoDelete()) {
2166 InsetTable * tmpi = insettable;
2167 InsetTable * tmpi2 = tmpi;
2173 if (tmpi2->inset->AutoDelete()) {
2178 lyxerr << "ERROR (LyXParagraph::AutoDeleteInsets): "
2179 "cannot auto-delete insets" << endl;
2186 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
2189 InsetTable * tmp = 0;
2190 for (InsetList::iterator it = insetlist.begin();
2191 it != insetlist.end(); ++it) {
2192 if ((*it).pos >= pos && (!tmp || (*it).pos < tmp->pos)) {
2203 InsetTable * tmpi = insettable;
2204 InsetTable * tmpi2 = 0;
2206 if (tmpi->pos >= pos) {
2207 if (!tmpi2 || tmpi->pos < tmpi2->pos)
2214 return tmpi2->inset;
2222 /* returns -1 if inset not found */
2223 int LyXParagraph::GetPositionOfInset(Inset * inset) const
2226 for (InsetList::iterator it = insetlist.begin();
2227 it != insetlist.end(); ++it) {
2228 if ((*it).inset == inset) {
2232 // Think about footnotes
2233 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
2234 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2235 int further = NextAfterFootnote()->GetPositionOfInset(inset);
2237 return size() + 1 + further;
2241 /* find the entry */
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;
2263 void LyXParagraph::readSimpleWholeFile(FILE * myfile)
2267 if (!feof(myfile)) {
2271 InsertChar(text.size(), c);
2272 } while (!feof(myfile));
2278 LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow,
2279 string & foot, TexRow & foot_texrow,
2282 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
2283 LyXParagraph * par = next;
2284 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
2287 bool further_blank_line = false;
2289 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
2291 if (start_of_appendix) {
2292 file += "\\appendix\n";
2296 if (tex_code_break_column && style.isCommand()){
2301 if (pagebreak_top) {
2302 file += "\\newpage";
2303 further_blank_line = true;
2305 if (added_space_top.kind() != VSpace::NONE) {
2306 file += added_space_top.asLatexCommand();
2307 further_blank_line = true;
2311 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
2312 file += "\\vspace{-1\\parskip}";
2313 further_blank_line = true;
2316 if (further_blank_line){
2321 switch (style.latextype) {
2324 file += style.latexname();
2325 file += style.latexparam();
2327 case LATEX_ITEM_ENVIRONMENT:
2329 bibkey->Latex(file, false);
2333 case LATEX_LIST_ENVIRONMENT:
2340 bool need_par = SimpleTeXOnePar(file, texrow);
2342 // Spit out footnotes
2343 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2344 && par->footnoteflag != footnoteflag) {
2345 par = par->TeXFootnote(file, texrow,
2346 foot, foot_texrow, foot_count);
2347 par->SimpleTeXOnePar(file, texrow);
2351 // Make sure that \\par is done with the font of the last
2352 // character if this has another size as the default.
2353 // This is necessary because LaTeX (and LyX on the screen)
2354 // calculates the space between the baselines according
2355 // to this font. (Matthias)
2356 LyXFont font = getFont(Last()-1);
2358 if (style.resfont.size() != font.size()) {
2360 file += font.latexSize();
2364 } else if (textclasslist.Style(GetCurrentTextClass(),
2365 GetLayout()).isCommand()){
2366 if (style.resfont.size() != font.size()) {
2368 file += font.latexSize();
2372 } else if (style.resfont.size() != font.size()){
2373 file += "{\\" + font.latexSize() + " \\par}";
2376 switch (style.latextype) {
2377 case LATEX_ITEM_ENVIRONMENT:
2378 case LATEX_LIST_ENVIRONMENT:
2379 if (par && (depth < par->depth)) {
2384 case LATEX_ENVIRONMENT:
2385 // if its the last paragraph of the current environment
2386 // skip it otherwise fall through
2388 && (par->layout != layout
2389 || par->depth != depth
2390 || par->pextra_type != pextra_type))
2393 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2394 && footnotekind != LyXParagraph::FOOTNOTE
2395 && footnotekind != LyXParagraph::MARGIN
2399 // don't insert this if we would be adding it
2400 // before or after a table in a float. This
2401 // little trick is needed in order to allow
2402 // use of tables in \subfigures or \subtables.
2408 further_blank_line = false;
2410 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2411 further_blank_line = true;
2414 if (added_space_bottom.kind() != VSpace::NONE) {
2415 file += added_space_bottom.asLatexCommand();
2416 further_blank_line = true;
2419 if (pagebreak_bottom) {
2420 file += "\\newpage";
2421 further_blank_line = true;
2424 if (further_blank_line){
2429 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2430 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2435 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2440 // This one spits out the text of the paragraph
2441 bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow)
2443 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2446 return SimpleTeXOneTablePar(file, texrow);
2449 size_type main_body;
2451 bool return_value = false;
2453 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), GetLayout());
2456 /* maybe we have to create a optional argument */
2457 if (style.labeltype != LABEL_MANUAL)
2460 main_body = BeginningOfMainBody();
2462 if (main_body > 0) {
2464 basefont = getFont(-2); // Get label font
2466 basefont = getFont(-1); // Get layout font
2474 if (style.isCommand()) {
2477 } else if (align != LYX_ALIGN_LAYOUT) {
2480 return_value = true;
2484 // Which font is currently active?
2485 LyXFont running_font = basefont;
2486 // Do we have an open font change?
2487 bool open_font = false;
2489 texrow.start(this, 0);
2491 for (size_type i = 0; i < size(); ++i) {
2493 // First char in paragraph or after label?
2494 if (i == main_body && !IsDummy()) {
2495 if (main_body > 0) {
2497 column += running_font.latexWriteEndChanges(file, basefont);
2500 basefont = getFont(-1); // Now use the layout font
2501 running_font = basefont;
2505 if (style.isCommand()) {
2508 } else if (align != LYX_ALIGN_LAYOUT) {
2511 return_value = true;
2515 file += "\\noindent ";
2519 case LYX_ALIGN_NONE:
2520 case LYX_ALIGN_BLOCK:
2521 case LYX_ALIGN_LAYOUT:
2522 case LYX_ALIGN_SPECIAL: break;
2523 case LYX_ALIGN_LEFT:
2524 file += "\\raggedright ";
2527 case LYX_ALIGN_RIGHT:
2528 file += "\\raggedleft ";
2531 case LYX_ALIGN_CENTER:
2532 file += "\\centering ";
2540 // Fully instantiated font
2541 LyXFont font = getFont(i);
2543 // Spaces at end of font change are simulated to be
2544 // outside font change, i.e. we write "\textXX{text} "
2545 // rather than "\textXX{text }". (Asger)
2546 if (open_font && c == ' ' && i <= size() - 2
2547 && !getFont(i+1).equalExceptLatex(running_font)
2548 && !getFont(i+1).equalExceptLatex(font)) {
2549 font = getFont(i+1);
2551 // We end font definition before blanks
2552 if (!font.equalExceptLatex(running_font) && open_font) {
2553 column += running_font.latexWriteEndChanges(file,
2555 running_font = basefont;
2559 // Blanks are printed before start of fontswitch
2561 // Do not print the separation of the optional argument
2562 if (i != main_body - 1) {
2563 SimpleTeXBlanks(file, texrow, i,
2564 column, font, style);
2568 // Do we need to change font?
2569 if (!font.equalExceptLatex(running_font)
2570 && i != main_body-1) {
2571 column += font.latexWriteStartChanges(file, basefont);
2572 running_font = font;
2576 if (c == LyXParagraph::META_NEWLINE) {
2577 // newlines are handled differently here than
2578 // the default in SimpleTeXSpecialChars().
2579 if (!style.newline_allowed
2580 || font.latex() == LyXFont::ON) {
2584 column += running_font.latexWriteEndChanges(file, basefont);
2587 basefont = getFont(-1);
2588 running_font = basefont;
2589 if (font.family() ==
2590 LyXFont::TYPEWRITER_FAMILY) {
2596 texrow.start(this, i+1);
2599 SimpleTeXSpecialChars(file, texrow,
2600 font, running_font, basefont,
2601 open_font, style, i, column, c);
2605 // If we have an open font definition, we have to close it
2607 running_font.latexWriteEndChanges(file, basefont);
2610 /* needed if there is an optional argument but no contents */
2611 if (main_body > 0 && main_body == size()) {
2613 return_value = false;
2616 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2617 return return_value;
2621 // This one spits out the text of a table paragraph
2622 bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow)
2624 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2628 bool return_value = false;
2629 int current_cell_number = -1;
2631 LyXLayout const & style =
2632 textclasslist.Style(GetCurrentTextClass(), GetLayout());
2633 LyXFont basefont = getFont(-1); // Get layout font
2634 // Which font is currently active?
2635 LyXFont running_font = basefont;
2636 // Do we have an open font change?
2637 bool open_font = false;
2640 if (!IsDummy()) { // it is dummy if it is in a float!!!
2641 if (style.isCommand()) {
2644 } else if (align != LYX_ALIGN_LAYOUT) {
2647 return_value = true;
2650 file += "\\noindent ";
2654 case LYX_ALIGN_NONE:
2655 case LYX_ALIGN_BLOCK:
2656 case LYX_ALIGN_LAYOUT:
2657 case LYX_ALIGN_SPECIAL: break;
2658 case LYX_ALIGN_LEFT:
2659 file += "\\raggedright ";
2662 case LYX_ALIGN_RIGHT:
2663 file += "\\raggedleft ";
2666 case LYX_ALIGN_CENTER:
2667 file += "\\centering ";
2672 current_cell_number = -1;
2673 tmp = table->TexEndOfCell(file, current_cell_number);
2674 for (; tmp >0 ; --tmp)
2677 texrow.start(this, 0);
2679 for (size_type i = 0; i < size(); ++i) {
2681 if (table->IsContRow(current_cell_number+1)) {
2682 if (c == LyXParagraph::META_NEWLINE)
2683 current_cell_number++;
2688 // Fully instantiated font
2689 LyXFont font = getFont(i);
2691 // Spaces at end of font change are simulated to be outside font change.
2692 // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
2693 if (open_font && c == ' ' && i <= size() - 2
2694 && getFont(i+1) != running_font && getFont(i+1) != font) {
2695 font = getFont(i+1);
2698 // We end font definition before blanks
2699 if (font != running_font && open_font) {
2700 column += running_font.latexWriteEndChanges(file,
2702 running_font = basefont;
2705 // Blanks are printed before start of fontswitch
2707 SimpleTeXBlanks(file, texrow, i, column, font, style);
2709 // Do we need to change font?
2710 if (font != running_font) {
2711 column += font.latexWriteStartChanges(file, basefont);
2712 running_font = font;
2715 // Do we need to turn on LaTeX mode?
2716 if (font.latex() != running_font.latex()) {
2717 if (font.latex() == LyXFont::ON
2718 && style.needprotect) {
2719 file += "\\protect ";
2723 if (c == LyXParagraph::META_NEWLINE) {
2724 // special case for inside a table
2725 // different from default case in SimpleTeXSpecialChars()
2727 column += running_font.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(GetCurrentTextClass(),
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)) {
2820 for (; i < size() && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2824 // Fully instantiated font
2825 LyXFont font = getFont(i);
2827 // Spaces at end of font change are simulated to be outside font change.
2828 // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
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();
2947 void LyXParagraph::SimpleDocBookOneTablePar(string & file, string & extra,
2948 int & desc_on, int depth)
2952 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2954 int current_cell_number = -1;
2955 LyXFont font1, font2;
2958 size_type main_body;
2959 string emph = "emphasis";
2960 bool emph_flag= false;
2961 int char_line_count= 0;
2963 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), GetLayout());
2965 if (style.labeltype != LABEL_MANUAL)
2968 main_body = BeginningOfMainBody();
2970 /* gets paragraph main font */
2972 font1 = style.labelfont;
2976 char_line_count = depth;
2977 addNewlineAndDepth(file, depth);
2978 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2979 file += "<INFORMALTABLE>";
2980 addNewlineAndDepth(file, ++depth);
2982 current_cell_number = -1;
2983 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, current_cell_number,
3033 } else if (c == LyXParagraph::META_INSET) {
3034 inset = GetInset(i);
3036 inset->DocBook(tmp_out);
3038 // This code needs some explanation:
3039 // Two insets are treated specially
3040 // label if it is the first element in a command paragraph
3042 // graphics inside tables or figure floats can't go on
3043 // title (the equivalente in latex for this case is caption
3044 // and title should come first
3047 if(desc_on != 3 || i != 0) {
3048 if(tmp_out[0] == '@') {
3050 extra += frontStrip(tmp_out, '@');
3052 file += frontStrip(tmp_out, '@');
3056 } else if (font2.latex() == LyXFont::ON) {
3057 // "TeX"-Mode on == > SGML-Mode on.
3063 if (linuxDocConvertChar(c, sgml_string)
3064 && !style.free_spacing) {
3065 // in freespacing mode, spaces are
3066 // non-breaking characters
3071 file += "</term><listitem><para>";
3077 file += sgml_string;
3083 /* needed if there is an optional argument but no contents */
3084 if (main_body > 0 && main_body == size()) {
3089 file += "</emphasis>";
3092 current_cell_number++;
3093 tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
3094 /* resets description flag correctly */
3097 /* <term> not closed... */
3101 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3102 file += "</INFORMALTABLE>";
3104 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
3109 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
3110 int & desc_on, LyXParagraph::size_type i,
3111 int current_cell_number, int &column)
3117 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
3120 LyXFont font1, font2;
3123 size_type main_body;
3125 string emph= "emphasis";
3126 bool emph_flag= false;
3127 int char_line_count= 0;
3129 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
3132 if (style.labeltype != LABEL_MANUAL)
3135 main_body = BeginningOfMainBody();
3137 /* gets paragraph main font */
3139 font1 = style.labelfont;
3144 cell = table->CellHasContRow(current_cell_number);
3145 current_cell_number++;
3147 // first find the right position
3149 for (; i < size() && current_cell_number < cell; ++i) {
3151 if (c == LyXParagraph::META_NEWLINE)
3152 current_cell_number++;
3156 // I don't know how to handle this so I comment it
3157 // for the moment (Jug)
3158 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3159 // file += " \\\\\n";
3162 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
3167 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3171 // Fully instantiated font
3174 /* handle <emphasis> tag */
3175 if (font1.emph() != font2.emph() && i) {
3176 if (font2.emph() == LyXFont::ON) {
3177 file += "<emphasis>";
3179 } else if (emph_flag) {
3180 file += "</emphasis>";
3184 if (c == LyXParagraph::META_INSET) {
3185 inset = GetInset(i);
3187 inset->DocBook(tmp_out);
3189 // This code needs some explanation:
3190 // Two insets are treated specially
3191 // label if it is the first element in a command paragraph
3193 // graphics inside tables or figure floats can't go on
3194 // title (the equivalente in latex for this case is caption
3195 // and title should come first
3198 if(desc_on != 3 || i != 0) {
3199 if(tmp_out[0] == '@') {
3201 extra += frontStrip(tmp_out, '@');
3203 file += frontStrip(tmp_out, '@');
3207 } else if (font2.latex() == LyXFont::ON) {
3208 // "TeX"-Mode on == > SGML-Mode on.
3214 if (linuxDocConvertChar(c, sgml_string)
3215 && !style.free_spacing) {
3216 // in freespacing mode, spaces are
3217 // non-breaking characters
3222 file += "</term><listitem><para>";
3228 file += sgml_string;
3232 // we have only to control for emphasis open here!
3234 file += "</emphasis>";
3237 font1 = font2 = getFont(-1);
3238 cell = table->CellHasContRow(current_cell_number);
3240 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3243 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
3244 LyXParagraph::size_type const i,
3245 int & column, LyXFont const & font,
3246 LyXLayout const & style)
3248 if (column > tex_code_break_column
3250 && GetChar(i - 1) != ' '
3252 // In LaTeX mode, we don't want to
3253 // break lines since some commands
3255 && ! (font.latex() == LyXFont::ON)
3256 // same in FreeSpacing mode
3257 && !style.free_spacing
3258 // In typewriter mode, we want to avoid
3259 // ! . ? : at the end of a line
3260 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3261 && (GetChar(i-1) == '.'
3262 || GetChar(i-1) == '?'
3263 || GetChar(i-1) == ':'
3264 || GetChar(i-1) == '!'))) {
3265 if (tex_code_break_column == 0) {
3266 // in batchmode we need LaTeX to still
3267 // see it as a space not as an extra '\n'
3273 texrow.start(this, i+1);
3275 } else if (font.latex() == LyXFont::OFF) {
3276 if (style.free_spacing) {
3285 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
3287 LyXFont & running_font,
3290 LyXLayout const & style,
3291 LyXParagraph::size_type & i,
3292 int & column, char const c)
3294 // Two major modes: LaTeX or plain
3295 // Handle here those cases common to both modes
3296 // and then split to handle the two modes separately.
3298 case LyXParagraph::META_INSET: {
3299 Inset * inset = GetInset(i);
3301 int len = file.length();
3302 int tmp = inset->Latex(file, style.isCommand());
3307 column += file.length() - len;
3316 case LyXParagraph::META_NEWLINE:
3318 column += running_font.latexWriteEndChanges(file,
3322 basefont = getFont(-1);
3323 running_font = basefont;
3326 case LyXParagraph::META_HFILL:
3327 file += "\\hfill{}";
3332 // And now for the special cases within each mode
3333 // Are we in LaTeX mode?
3334 if (font.latex() == LyXFont::ON) {
3335 // at present we only have one option
3336 // but I'll leave it as a switch statement
3337 // so its simpler to extend. (ARRae)
3339 case LyXParagraph::META_PROTECTED_SEPARATOR:
3344 // make sure that we will not print
3345 // error generating chars to the tex
3346 // file. This test would not be needed
3347 // if it were done in the buffer
3355 // Plain mode (i.e. not LaTeX)
3357 case LyXParagraph::META_PROTECTED_SEPARATOR:
3362 file += "\\textbackslash{}";
3366 case '°': case '±': case '²': case '³':
3367 case '×': case '÷': case '¹': case 'ª':
3368 case 'º': case '¬': case 'µ':
3369 if (current_view->buffer()->params.inputenc == "latin1") {
3370 file += "\\ensuremath{";
3379 case '|': case '<': case '>':
3380 // In T1 encoding, these characters exist
3381 if (lyxrc->fontenc == "T1") {
3383 //... but we should avoid ligatures
3384 if ((c == '>' || c == '<')
3386 && GetChar(i+1) == c){
3387 file += "\\textcompwordmark{}";
3392 // Typewriter font also has them
3393 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3397 // Otherwise, we use what LaTeX
3401 file += "\\textless{}";
3405 file += "\\textgreater{}";
3409 file += "\\textbar{}";
3415 case '-': // "--" in Typewriter mode -> "-{}-"
3417 && GetChar(i + 1) == '-'
3418 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3427 file += "\\char`\\\"{}";
3432 if (current_view->buffer()->params.inputenc == "default") {
3433 file += "\\pounds{}";
3441 case '%': case '#': case '{':
3449 file += "\\textasciitilde{}";
3454 file += "\\textasciicircum{}";
3458 case '*': case '[': case ']':
3459 // avoid being mistaken for optional arguments
3467 /* blanks are printed before font switching */
3468 // Sure? I am not! (try nice-latex)
3469 // I am sure it's correct. LyX might be smarter
3470 // in the future, but for now, nothing wrong is
3475 /* idea for labels --- begin*/
3479 && font.family() != LyXFont::TYPEWRITER_FAMILY
3480 && GetChar(i + 1) == 'y'
3481 && GetChar(i + 2) == 'X') {
3489 && font.family() != LyXFont::TYPEWRITER_FAMILY
3490 && GetChar(i + 1) == 'e'
3491 && GetChar(i + 2) == 'X') {
3496 /* check for LaTeX2e */
3499 && font.family() != LyXFont::TYPEWRITER_FAMILY
3500 && GetChar(i + 1) == 'a'
3501 && GetChar(i + 2) == 'T'
3502 && GetChar(i + 3) == 'e'
3503 && GetChar(i + 4) == 'X'
3504 && GetChar(i + 5) == '2'
3505 && GetChar(i + 6) == 'e') {
3506 file += "\\LaTeXe{}";
3510 /* check for LaTeX */
3513 && font.family() != LyXFont::TYPEWRITER_FAMILY
3514 && GetChar(i + 1) == 'a'
3515 && GetChar(i + 2) == 'T'
3516 && GetChar(i + 3) == 'e'
3517 && GetChar(i + 4) == 'X') {
3518 file += "\\LaTeX{}";
3521 /* idea for labels --- end*/
3522 } else if (c != '\0') {
3532 bool LyXParagraph::RoffContTableRows(FILE * fp,
3533 LyXParagraph::size_type i,
3539 LyXFont font1 = LyXFont(LyXFont::ALL_INHERIT);
3545 string fname2 = TmpFileName(string(), "RAT2");
3547 int cell = table->CellHasContRow(actcell);
3550 // first find the right position
3552 for (; i < size() && actcell < cell; ++i) {
3554 if (c == LyXParagraph::META_NEWLINE)
3559 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3562 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3564 font2 = GetFontSettings(i);
3565 if (font1.latex() != font2.latex()) {
3566 if (font2.latex() != LyXFont::OFF)
3571 case LyXParagraph::META_INSET:
3572 if ((inset = GetInset(i))) {
3573 if (!(fp2= fopen(fname2.c_str(), "w+"))) {
3574 WriteAlert(_("LYX_ERROR:"),
3575 _("Cannot open temporary file:"),
3579 inset->Latex(fp2,-1);
3584 fprintf(fp, "\\\\");
3592 case LyXParagraph::META_NEWLINE:
3594 case LyXParagraph::META_HFILL:
3596 case LyXParagraph::META_PROTECTED_SEPARATOR:
3599 fprintf(fp, "\\\\");
3603 fprintf(fp, "%c", c);
3605 lyxerr.debug() << "RoffAsciiTable: NULL char in structure." << endl;
3609 cell = table->CellHasContRow(actcell);
3615 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
3616 string & foot, TexRow & foot_texrow,
3619 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3620 LyXParagraph * par = this;
3622 while (par && par->depth == depth) {
3624 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3625 if (textclasslist.Style(GetCurrentTextClass(),
3626 par->layout).isEnvironment()
3627 || par->pextra_type != PEXTRA_NONE)
3629 par = par->TeXEnvironment(file, texrow,
3633 par = par->TeXOnePar(file, texrow,
3638 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3644 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
3645 string & foot, TexRow & foot_texrow,
3648 bool eindent_open = false;
3649 bool foot_this_level = false;
3650 // flags when footnotetext should be appended to file.
3651 static bool minipage_open = false;
3652 static int minipage_open_depth = 0;
3653 char par_sep = current_view->buffer()->params.paragraph_separation;
3655 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3657 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3659 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
3662 if (pextra_type == PEXTRA_INDENT) {
3663 if (!pextra_width.empty()) {
3664 file += "\\begin{LyXParagraphIndent}{"
3665 + pextra_width + "}\n";
3667 //float ib = atof(pextra_widthp.c_str())/100;
3668 // string can't handle floats at present (971109)
3669 // so I'll do a conversion by hand knowing that
3670 // the limits are 0.0 to 1.0. ARRae.
3671 file += "\\begin{LyXParagraphIndent}{";
3672 switch (pextra_widthp.length()) {
3678 file += pextra_widthp;
3682 file += pextra_widthp;
3684 file += "\\columnwidth}\n";
3687 eindent_open = true;
3689 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3690 if (pextra_hfill && Previous() &&
3691 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3692 file += "\\hfill{}\n";
3695 if (par_sep == BufferParams::PARSEP_INDENT) {
3696 file += "{\\setlength\\parindent{0pt}\n";
3699 file += "\\begin{minipage}";
3700 switch(pextra_alignment) {
3701 case MINIPAGE_ALIGN_TOP:
3704 case MINIPAGE_ALIGN_MIDDLE:
3707 case MINIPAGE_ALIGN_BOTTOM:
3711 if (!pextra_width.empty()) {
3713 file += pextra_width + "}\n";
3715 //float ib = atof(par->pextra_width.c_str())/100;
3716 // string can't handle floats at present
3717 // so I'll do a conversion by hand knowing that
3718 // the limits are 0.0 to 1.0. ARRae.
3720 switch (pextra_widthp.length()) {
3726 file += pextra_widthp;
3730 file += pextra_widthp;
3732 file += "\\columnwidth}\n";
3735 if (par_sep == BufferParams::PARSEP_INDENT) {
3736 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3739 minipage_open = true;
3740 minipage_open_depth = depth;
3743 #ifdef WITH_WARNINGS
3744 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3745 //I disabled it because it breaks when lists span on several
3748 if (style.isEnvironment()){
3749 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3750 #ifdef FANCY_FOOTNOTE_CODE
3751 if (foot_count < 0) {
3752 // flag that footnote[mark][text] should be
3753 // used for any footnotes from now on
3755 foot_this_level = true;
3758 file += "\\begin{" + style.latexname() + "}{"
3759 + labelwidthstring + "}\n";
3760 } else if (style.labeltype == LABEL_BIBLIO) {
3762 file += "\\begin{" + style.latexname() + "}{"
3763 + bibitemWidthest() + "}\n";
3764 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3765 #ifdef FANCY_FOOTNOTE_CODE
3766 if (foot_count < 0) {
3767 // flag that footnote[mark][text] should be
3768 // used for any footnotes from now on
3770 foot_this_level = true;
3773 file += "\\begin{" + style.latexname() + '}'
3774 + style.latexparam() + '\n';
3776 file += "\\begin{" + style.latexname() + '}'
3777 + style.latexparam() + '\n';
3780 LyXParagraph * par = this;
3782 par = par->TeXOnePar(file, texrow,
3783 foot, foot_texrow, foot_count);
3785 if (minipage_open && par && !style.isEnvironment() &&
3786 (par->pextra_type == PEXTRA_MINIPAGE) &&
3787 par->pextra_start_minipage) {
3788 file += "\\end{minipage}\n";
3790 if (par_sep == BufferParams::PARSEP_INDENT) {
3794 minipage_open = false;
3796 if (par && par->depth > depth) {
3797 if (textclasslist.Style(GetCurrentTextClass(),
3798 par->layout).isParagraph()
3800 && !suffixIs(file, "\n\n")) {
3801 // There should be at least one '\n' already
3802 // but we need there to be two for Standard
3803 // paragraphs that are depth-increment'ed to be
3804 // output correctly. However, tables can also be
3805 // paragraphs so don't adjust them. ARRae
3809 par = par->TeXDeeper(file, texrow,
3810 foot, foot_texrow, foot_count);
3812 if (par && par->layout == layout && par->depth == depth &&
3813 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3814 if (par->pextra_hfill && par->Previous() &&
3815 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3816 file += "\\hfill{}\n";
3819 if (par_sep == BufferParams::PARSEP_INDENT) {
3820 file += "{\\setlength\\parindent{0pt}\n";
3823 file += "\\begin{minipage}";
3824 switch(par->pextra_alignment) {
3825 case MINIPAGE_ALIGN_TOP:
3828 case MINIPAGE_ALIGN_MIDDLE:
3831 case MINIPAGE_ALIGN_BOTTOM:
3835 if (!par->pextra_width.empty()) {
3837 file += par->pextra_width;
3840 //float ib = atof(par->pextra_widthp.c_str())/100;
3841 // string can't handle floats at present
3842 // so I'll do a conversion by hand knowing that
3843 // the limits are 0.0 to 1.0. ARRae.
3845 switch (par->pextra_widthp.length()) {
3851 file += par->pextra_widthp;
3855 file += par->pextra_widthp;
3857 file += "\\columnwidth}\n";
3860 if (par_sep == BufferParams::PARSEP_INDENT) {
3861 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3864 minipage_open = true;
3865 minipage_open_depth = par->depth;
3868 && par->layout == layout
3869 && par->depth == depth
3870 && par->pextra_type == pextra_type);
3872 if (style.isEnvironment()) {
3873 file += "\\end{" + style.latexname() + '}';
3874 // maybe this should go after the minipage closes?
3875 if (foot_this_level) {
3876 if (foot_count >= 1) {
3877 if (foot_count > 1) {
3878 file += "\\addtocounter{footnote}{-";
3879 file += tostr(foot_count - 1);
3883 texrow += foot_texrow;
3885 foot_texrow.reset();
3890 if (minipage_open && (minipage_open_depth == depth) &&
3891 (!par || par->pextra_start_minipage ||
3892 par->pextra_type != PEXTRA_MINIPAGE)) {
3893 file += "\\end{minipage}\n";
3895 if (par_sep == BufferParams::PARSEP_INDENT) {
3899 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3900 file += "\\medskip\n\n";
3904 minipage_open = false;
3907 file += "\\end{LyXParagraphIndent}\n";
3910 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
3911 && par->pextra_hfill)) {
3915 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3916 return par; // ale970302
3920 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
3921 string & foot, TexRow & foot_texrow,
3924 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3925 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3926 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3927 "No footnote!" << endl;
3929 LyXParagraph * par = this;
3930 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
3931 previous->GetLayout());
3933 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3934 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3935 "Float other than footnote in command"
3936 " with moving argument is illegal" << endl;
3939 if (footnotekind != LyXParagraph::FOOTNOTE
3940 && footnotekind != LyXParagraph::MARGIN
3942 && !suffixIs(file, '\n')) {
3943 // we need to ensure that real floats like tables and figures
3944 // have their \begin{} on a new line otherwise we can get
3945 // incorrect results when using the endfloat.sty package
3946 // especially if two floats follow one another. ARRae 981022
3947 // NOTE: if the file is length 0 it must have just been
3948 // written out so we assume it ended with a '\n'
3953 BufferParams * params = ¤t_view->buffer()->params;
3954 bool footer_in_body = true;
3955 switch (footnotekind) {
3956 case LyXParagraph::FOOTNOTE:
3957 if (style.intitle) {
3958 file += "\\thanks{\n";
3959 footer_in_body = false;
3961 if (foot_count == -1) {
3962 // we're at depth 0 so we can use:
3963 file += "\\footnote{%\n";
3964 footer_in_body = false;
3966 file += "\\footnotemark{}%\n";
3968 // we only need this when there are
3969 // multiple footnotes
3970 foot += "\\stepcounter{footnote}";
3972 foot += "\\footnotetext{%\n";
3973 foot_texrow.start(this, 0);
3974 foot_texrow.newline();
3979 case LyXParagraph::MARGIN:
3980 file += "\\marginpar{\n";
3982 case LyXParagraph::FIG:
3983 if (pextra_type == PEXTRA_FLOATFLT
3984 && (!pextra_width.empty()
3985 || !pextra_widthp.empty())) {
3987 if (!pextra_width.empty())
3988 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
3989 pextra_width.c_str());
3991 sprintf(bufr, "\\begin{floatingfigure}{%f\\textwidth}\n",
3992 atoi(pextra_widthp.c_str())/100.0);
3995 file += "\\begin{figure}";
3996 if (!params->float_placement.empty()) {
3998 file += params->float_placement;
4005 case LyXParagraph::TAB:
4006 file += "\\begin{table}";
4007 if (!params->float_placement.empty()) {
4009 file += params->float_placement;
4015 case LyXParagraph::WIDE_FIG:
4016 file += "\\begin{figure*}";
4017 if (!params->float_placement.empty()) {
4019 file += params->float_placement;
4025 case LyXParagraph::WIDE_TAB:
4026 file += "\\begin{table*}";
4027 if (!params->float_placement.empty()) {
4029 file += params->float_placement;
4035 case LyXParagraph::ALGORITHM:
4036 file += "\\begin{algorithm}\n";
4041 if (footnotekind != LyXParagraph::FOOTNOTE
4042 || !footer_in_body) {
4043 // Process text for all floats except footnotes in body
4045 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
4048 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4050 if (style.isEnvironment()
4051 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4052 // Allows the use of minipages within float environments.
4053 // Shouldn't be circular because we don't support
4054 // footnotes inside floats (yet). ARRae
4055 par = par->TeXEnvironment(file, texrow,
4059 par = par->TeXOnePar(file, texrow,
4064 if (par && !par->IsDummy() && par->depth > depth) {
4065 par = par->TeXDeeper(file, texrow,
4069 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4071 // process footnotes > depth 0 or in environments separately
4072 // NOTE: Currently don't support footnotes within footnotes
4073 // even though that is possible using the \footnotemark
4075 TexRow dummy_texrow;
4076 int dummy_count = 0;
4078 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
4081 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4083 if (style.isEnvironment()
4084 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4085 // Allows the use of minipages within float environments.
4086 // Shouldn't be circular because we don't support
4087 // footnotes inside floats (yet). ARRae
4088 par = par->TeXEnvironment(foot, foot_texrow,
4089 dummy, dummy_texrow,
4092 par = par->TeXOnePar(foot, foot_texrow,
4093 dummy, dummy_texrow,
4097 if (par && !par->IsDummy() && par->depth > depth) {
4098 par = par->TeXDeeper(foot, foot_texrow,
4099 dummy, dummy_texrow,
4102 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4104 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4105 "Footnote in a Footnote -- not supported"
4110 switch (footnotekind) {
4111 case LyXParagraph::FOOTNOTE:
4112 if (footer_in_body) {
4113 // This helps tell which of the multiple
4114 // footnotetexts an error was in.
4116 foot_texrow.newline();
4121 case LyXParagraph::MARGIN:
4124 case LyXParagraph::FIG:
4125 if (pextra_type == PEXTRA_FLOATFLT
4126 && (!pextra_width.empty()
4127 || !pextra_widthp.empty()))
4128 file += "\\end{floatingfigure}";
4130 file += "\\end{figure}";
4132 case LyXParagraph::TAB:
4133 file += "\\end{table}";
4135 case LyXParagraph::WIDE_FIG:
4136 file += "\\end{figure*}";
4138 case LyXParagraph::WIDE_TAB:
4139 file += "\\end{table*}";
4141 case LyXParagraph::ALGORITHM:
4142 file += "\\end{algorithm}";
4146 if (footnotekind != LyXParagraph::FOOTNOTE
4147 && footnotekind != LyXParagraph::MARGIN) {
4148 // we need to ensure that real floats like tables and figures
4149 // have their \end{} on a line of their own otherwise we can
4150 // get incorrect results when using the endfloat.sty package.
4155 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4160 void LyXParagraph::SetPExtraType(int type, char const * width,
4161 char const * widthp)
4164 pextra_width = width;
4165 pextra_widthp = widthp;
4167 if (textclasslist.Style(GetCurrentTextClass(),
4168 layout).isEnvironment()) {
4173 while (par && (par->layout == layout) && (par->depth == depth)) {
4175 par = par->Previous();
4177 par = par->FirstPhysicalPar();
4178 while (par && par->depth > depth) {
4179 par = par->Previous();
4181 par = par->FirstPhysicalPar();
4185 while (par && (par->layout == layout) && (par->depth == depth)) {
4186 par->pextra_type = type;
4187 par->pextra_width = width;
4188 par->pextra_widthp = widthp;
4189 par = par->NextAfterFootnote();
4190 if (par && (par->depth > depth))
4191 par->SetPExtraType(type, width, widthp);
4192 while (par && ((par->depth > depth) || par->IsDummy()))
4193 par = par->NextAfterFootnote();
4199 void LyXParagraph::UnsetPExtraType()
4201 if (pextra_type == PEXTRA_NONE)
4204 pextra_type = PEXTRA_NONE;
4205 pextra_width.clear();
4206 pextra_widthp.clear();
4208 if (textclasslist.Style(GetCurrentTextClass(),
4209 layout).isEnvironment()) {
4214 while (par && (par->layout == layout) && (par->depth == depth)) {
4216 par = par->Previous();
4218 par = par->FirstPhysicalPar();
4219 while (par && par->depth > depth) {
4220 par = par->Previous();
4222 par = par->FirstPhysicalPar();
4226 while (par && (par->layout == layout) && (par->depth == depth)) {
4227 par->pextra_type = PEXTRA_NONE;
4228 par->pextra_width.clear();
4229 par->pextra_widthp.clear();
4230 par = par->NextAfterFootnote();
4231 if (par && (par->depth > depth))
4232 par->UnsetPExtraType();
4233 while (par && ((par->depth > depth) || par->IsDummy()))
4234 par = par->NextAfterFootnote();
4240 bool LyXParagraph::IsHfill(size_type pos) const
4242 return IsHfillChar(GetChar(pos));
4246 bool LyXParagraph::IsInset(size_type pos) const
4248 return IsInsetChar(GetChar(pos));
4252 bool LyXParagraph::IsFloat(size_type pos) const
4254 return IsFloatChar(GetChar(pos));
4258 bool LyXParagraph::IsNewline(size_type pos) const
4262 tmp = IsNewlineChar(GetChar(pos));
4267 bool LyXParagraph::IsSeparator(size_type pos) const
4269 return IsSeparatorChar(GetChar(pos));
4273 bool LyXParagraph::IsLineSeparator(size_type pos) const
4275 return IsLineSeparatorChar(GetChar(pos));
4279 bool LyXParagraph::IsKomma(size_type pos) const
4281 return IsKommaChar(GetChar(pos));
4285 /// Used by the spellchecker
4286 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
4288 unsigned char c = GetChar(pos);
4289 if (IsLetterChar(c))
4291 // '\0' is not a letter, allthough every string contains "" (below)
4294 // We want to pass the ' and escape chars to ispell
4295 string extra = lyxrc->isp_esc_chars + '\'';
4299 return contains(extra, ch);
4303 bool LyXParagraph::IsWord(size_type pos ) const
4305 return IsWordChar( GetChar(pos) ) ;