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"
20 #include "tex-strings.h"
21 #include "bufferparams.h"
22 #include "support/FileInfo.h"
24 #include "LaTeXFeatures.h"
25 #include "insets/insetinclude.h"
26 #include "support/filetools.h"
27 #include "lyx_gui_misc.h"
31 #define INITIAL_SIZE_PAR 10 /*Number of bytes in one paragraph*/
32 #define STEP_SIZE_PAR 10 /*Number of bytes added when reallocated*/
35 extern void addNewlineAndDepth(string & file, int const depth); // Jug 990923
36 extern unsigned char GetCurrentTextClass(); // this should be fixed/removed
37 int tex_code_break_column = 72; // needs non-zero initialization. set later.
38 // this is a bad idea, but how can LyXParagraph find its buffer to get
39 // parameters? (JMarc)
40 extern BufferView * current_view;
45 extern string bibitemWidthest();
47 /* this is a minibuffer */
48 static char minibuffer_char;
49 static LyXFont minibuffer_font;
50 static Inset * minibuffer_inset;
53 // Initialization of the counter for the paragraph id's,
54 // declared in lyxparagraph.h
55 unsigned int LyXParagraph::paragraph_id = 0;
58 LyXParagraph::LyXParagraph()
61 size = INITIAL_SIZE_PAR;
62 text = new char[size];
65 for (int i = 0; i < 10; ++i) setCounter(i , 0);
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 size = INITIAL_SIZE_PAR;
93 text = new char[size];
96 for (int i = 0; i < 10; ++i) setCounter(i, 0);
102 next->previous = this;
104 previous->next = this;
109 footnoteflag = LyXParagraph::NO_FOOTNOTE;
110 footnotekind = LyXParagraph::FOOTNOTE;
112 /* table stuff -- begin*/
114 /* table stuff -- end*/
117 bibkey = 0; // ale970302
122 /// Used by the spellchecker
124 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) {
126 bool LyXParagraph::IsLetter(int pos) {
128 unsigned char c = GetChar(pos);
131 // '\0' is not a letter, allthough every string contains "" (below)
134 // We want to pass the ' and escape chars to ispell
135 string extra = lyxrc->isp_esc_chars + '\'';
139 return contains(extra, ch);
143 void LyXParagraph::writeFile(FILE * file, BufferParams & params,
144 char footflag, char dth)
146 LyXFont font1, font2;
152 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
154 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
156 /* The beginning or the end of a footnote environment? */
157 if (footflag != footnoteflag) {
158 footflag = footnoteflag;
160 fprintf(file, "\n\\begin_float %s ",
161 string_footnotekinds[footnotekind]);
164 fprintf(file, "\n\\end_float ");
168 /* The beginning or end of a deeper (i.e. nested) area? */
171 while (depth > dth) {
172 fprintf(file, "\n\\begin_deeper ");
177 while (depth < dth) {
178 fprintf(file, "\n\\end_deeper ");
184 /* First write the layout */
185 fprintf(file, "\n\\layout %s\n",
186 textclasslist.NameOfLayout(params.textclass,layout)
189 /* maybe some vertical spaces */
190 if (added_space_top.kind() != VSpace::NONE)
191 fprintf(file, "\\added_space_top %s ",
192 added_space_top.asLyXCommand().c_str());
193 if (added_space_bottom.kind() != VSpace::NONE)
194 fprintf(file, "\\added_space_bottom %s ",
195 added_space_bottom.asLyXCommand().c_str());
197 /* The labelwidth string used in lists */
198 if (!labelwidthstring.empty())
199 fprintf(file, "\\labelwidthstring %s\n",
200 labelwidthstring.c_str());
202 /* Lines above or below? */
204 fprintf(file, "\\line_top ");
206 fprintf(file, "\\line_bottom ");
208 /* Pagebreaks above or below? */
210 fprintf(file, "\\pagebreak_top ");
211 if (pagebreak_bottom)
212 fprintf(file, "\\pagebreak_bottom ");
214 /* Start of appendix? */
215 if (start_of_appendix)
216 fprintf(file, "\\start_of_appendix ");
220 fprintf(file, "\\noindent ");
223 if (align != LYX_ALIGN_LAYOUT) {
225 case LYX_ALIGN_LEFT: h = 1; break;
226 case LYX_ALIGN_RIGHT: h = 2; break;
227 case LYX_ALIGN_CENTER: h = 3; break;
228 default: h = 0; break;
230 fprintf(file, "\\align %s ", string_align[h]);
232 if (pextra_type != PEXTRA_NONE) {
233 fprintf(file, "\\pextra_type %d", pextra_type);
234 if (pextra_type == PEXTRA_MINIPAGE) {
235 fprintf(file, " \\pextra_alignment %d",
238 fprintf(file, " \\pextra_hfill %d",
240 if (pextra_start_minipage)
242 " \\pextra_start_minipage %d",
243 pextra_start_minipage);
245 if (!pextra_width.empty()) {
246 fprintf(file, " \\pextra_width %s",
248 .asLyXCommand().c_str());
249 } else if (!pextra_widthp.empty()) {
250 fprintf(file, " \\pextra_widthp %s",
251 pextra_widthp.c_str());
257 /* Dummy layout. This means that a footnote ended */
258 fprintf(file, "\n\\end_float ");
259 footflag = LyXParagraph::NO_FOOTNOTE;
262 /* It might be a table */
264 fprintf(file, "\\LyXTable\n");
272 font1 = LyXFont(LyXFont::ALL_INHERIT);
276 for (size_type i = 0; i < size(); i++) {
282 for (int i = 0; i < last; i++) {
289 // Write font changes
290 font2 = GetFontSettings(i);
291 if (font2 != font1) {
292 font2.lyxWriteChanges(font1, file);
302 if (inset->DirectWrite()) {
303 // international char, let it write
304 // code directly so it's shorter in
308 fprintf(file, "\n\\begin_inset ");
310 fprintf(file, "\n\\end_inset \n");
315 case LYX_META_NEWLINE:
316 fprintf(file, "\n\\newline \n");
320 fprintf(file, "\n\\hfill \n");
323 case LYX_META_PROTECTED_SEPARATOR:
324 fprintf(file, "\n\\protected_separator \n");
328 fprintf(file, "\n\\backslash \n");
333 if (i + 1 < size() && GetChar(i + 1) == ' ') {
334 fprintf(file, ".\n");
339 if (i + 1 < last && GetChar(i + 1) == ' ') {
340 fprintf(file, ".\n");
347 if ((column > 70 && c==' ')
352 // this check is to amend a bug. LyX sometimes
353 // inserts '\0' this could cause problems.
355 fprintf(file, "%c", c);
357 lyxerr << "ERROR (LyXParagraph::writeFile):"
358 " NULL char in structure." << endl;
364 // now write the next paragraph
366 next->writeFile(file, params, footflag, dth);
370 void LyXParagraph::validate(LaTeXFeatures & features)
372 // this will be useful later
373 LyXLayout const & layout = textclasslist.Style(GetCurrentTextClass(),
377 if (line_top || line_bottom)
378 features.lyxline = true;
381 features.layout[GetLayout()] = true;
384 for (FontList::const_iterator cit = fontlist.begin();
385 cit != fontlist.end(); ++cit) {
386 if ((*cit).font.noun() == LyXFont::ON) {
387 lyxerr[Debug::LATEX] << "font.noun: "
388 << (*cit).font.noun()
390 features.noun = true;
391 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
392 << (*cit).font.stateText()
395 switch ((*cit).font.color()) {
397 case LyXFont::INHERIT_COLOR:
398 case LyXFont::IGNORE_COLOR: break;
400 features.color = true;
401 lyxerr[Debug::LATEX] << "Color enabled. Font: "
402 << (*cit).font.stateText()
408 FontTable * tmpfonttable = fonttable;
409 while (tmpfonttable) {
410 if (tmpfonttable->font.noun() == LyXFont::ON) {
411 lyxerr[Debug::LATEX] << "font.noun: "
412 << tmpfonttable->font.noun()
414 features.noun = true;
415 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
416 << tmpfonttable->font.stateText()
419 switch (tmpfonttable->font.color()) {
421 case LyXFont::INHERIT_COLOR:
422 case LyXFont::IGNORE_COLOR:
425 features.color = true;
426 lyxerr[Debug::LATEX] << "Color enabled. Font: "
427 << tmpfonttable->font.stateText()
430 tmpfonttable = tmpfonttable->next;
434 for (InsetList::const_iterator cit = insetlist.begin();
435 cit != insetlist.end(); ++cit) {
436 (*cit).inset->Validate(features);
440 InsetTable * tmpinsettable = insettable;
441 while (tmpinsettable) {
442 if (tmpinsettable->inset) {
443 tmpinsettable->inset->Validate(features);
445 tmpinsettable = tmpinsettable->next;
448 if (table && table->IsLongTable())
449 features.longtable = true;
450 if (pextra_type == PEXTRA_INDENT)
451 features.LyXParagraphIndent = true;
452 if (pextra_type == PEXTRA_FLOATFLT)
453 features.floatflt = true;
454 if (layout.needprotect
455 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
456 features.NeedLyXFootnoteCode = true;
457 if ((current_view->currentBuffer()->params.paragraph_separation == LYX_PARSEP_INDENT) &&
458 (pextra_type == PEXTRA_MINIPAGE))
459 features.NeedLyXMinipageIndent = true;
460 if (table && table->NeedRotating())
461 features.rotating = true;
462 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
463 features.algorithm = true;
467 /* first few functions needed for cut and paste and paragraph breaking */
469 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos)
471 void LyXParagraph::CopyIntoMinibuffer(int pos)
474 minibuffer_char = GetChar(pos);
475 minibuffer_font = GetFontSettings(pos);
476 minibuffer_inset = 0;
477 if (minibuffer_char == LYX_META_INSET) {
479 minibuffer_inset = GetInset(pos)->Clone();
481 minibuffer_inset = 0;
482 minibuffer_char = ' ';
483 // This reflects what GetInset() does (ARRae)
489 void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos)
491 void LyXParagraph::CutIntoMinibuffer(int pos)
494 minibuffer_char = GetChar(pos);
495 minibuffer_font = GetFontSettings(pos);
496 minibuffer_inset = 0;
497 if (minibuffer_char == LYX_META_INSET) {
499 minibuffer_inset = GetInset(pos);
500 // This is a little hack since I want exactly
501 // the inset, not just a clone. Otherwise
502 // the inset would be deleted when calling Erase(pos)
504 for (InsetList::iterator it = insetlist.begin();
505 it != insetlist.end(); ++it) {
506 if ((*it).pos == pos) {
513 InsetTable * tmpi = insettable;
514 while (tmpi && tmpi->pos != pos) {
517 if (tmpi) { /* This should always be true */
522 minibuffer_inset = 0;
523 minibuffer_char = ' ';
524 // This reflects what GetInset() does (ARRae)
529 /* Erase(pos); now the caller is responsible for that*/
534 void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
536 void LyXParagraph::InsertFromMinibuffer(int pos)
539 InsertChar(pos, minibuffer_char);
540 SetFont(pos, minibuffer_font);
541 if (minibuffer_char == LYX_META_INSET)
542 InsertInset(pos, minibuffer_inset);
545 /* end of minibuffer */
549 void LyXParagraph::Clear()
554 pagebreak_top = false;
555 pagebreak_bottom = false;
557 added_space_top = VSpace(VSpace::NONE);
558 added_space_bottom = VSpace(VSpace::NONE);
560 align = LYX_ALIGN_LAYOUT;
564 pextra_type = PEXTRA_NONE;
565 pextra_width.clear();
566 pextra_widthp.clear();
567 pextra_alignment = MINIPAGE_ALIGN_TOP;
568 pextra_hfill = false;
569 pextra_start_minipage = false;
572 labelwidthstring.clear();
576 start_of_appendix = false;
580 /* the destructor removes the new paragraph from the list */
581 LyXParagraph::~LyXParagraph()
584 previous->next = next;
586 next->previous = previous;
594 InsetTable * tmpinset;
596 tmpinset = insettable;
597 insettable = insettable->next;
599 delete tmpinset->inset;
601 if (insettable && insettable->next == insettable) {
602 // somehow this recursion appears occasionally
603 // but I can't find where. This bandaid
604 // helps but isn't the best fix. (ARRae)
605 if (insettable->inset) {
606 delete insettable->inset;
616 fonttable = fonttable->next;
621 /* table stuff -- begin*/
624 /* table stuff -- end*/
633 void LyXParagraph::Erase(LyXParagraph::size_type pos)
635 void LyXParagraph::Erase(int pos)
638 /* > because last is the next unused position, and you can
639 * use it if you want */
642 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
643 NextAfterFootnote()->Erase(pos - text.size() - 1);
645 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
646 "position does not exist." << endl;
651 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
652 NextAfterFootnote()->Erase(pos - last - 1);
654 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
655 "position does not exist." << endl;
660 if (pos < size()) { // last is free for insertation, but should be empty
662 if (pos < last) { // last is free for insertation, but should be empty
665 /* if it is an inset, delete the inset entry */
666 if (text[pos] == LYX_META_INSET) {
668 for(InsetList::iterator it = insetlist.begin();
669 it != insetlist.end(); ++it) {
670 if ((*it).pos == pos) {
678 /* if it is an inset, delete the inset entry */
679 if (text[pos] == LYX_META_INSET) {
681 InsetTable *tmpi = insettable;
682 InsetTable *tmpi2 = tmpi;
683 while (tmpi && tmpi->pos != pos) {
687 if (tmpi) { // this should always be true
688 if (tmpi->inset) // delete the inset if it exists
690 if (tmpi == insettable)
691 insettable = tmpi->next;
693 tmpi2->next = tmpi->next;
699 text.erase(text.begin() + pos);
701 // Shift rest of text
702 for (int i = pos; i < last - 1; i++) {
708 /* erase entries in the tables */
709 for(FontList::iterator it = fontlist.begin();
710 it != fontlist.end(); ++it) {
711 if (pos >= (*it).pos && pos <= (*it).pos_end) {
712 if ((*it).pos == (*it).pos_end) {
719 /* update all other entries */
720 for(FontList::iterator it = fontlist.begin();
721 it != fontlist.end(); ++it) {
724 if ((*it).pos_end >= pos)
728 /* update the inset table */
729 for(InsetList::iterator it = insetlist.begin();
730 it != insetlist.end(); ++it) {
735 /* erase entries in the tables */
737 FontTable * tmp = fonttable;
738 FontTable * prev = 0;
739 while (tmp && !found) {
740 if (pos >= tmp->pos && pos <= tmp->pos_end)
748 if (found && tmp->pos == tmp->pos_end) {
749 /* if it is a multi-character font entry, we just make
750 * it smaller (see update below), otherwise we should
753 prev->next = tmp->next;
755 fonttable = tmp->next;
760 /* update all other entries */
766 if (tmp->pos_end >= pos)
771 /* update the inset table */
772 InsetTable * tmpi = insettable;
780 lyxerr << "ERROR (LyXParagraph::Erase): "
781 "can't erase non-existant char." << endl;
787 /* pos is needed to specify the paragraph correctly. Remember the
788 * closed footnotes */
789 void LyXParagraph::Enlarge(int pos, int number)
791 /* > because last is the next unused position, and you can
792 * use it if you want */
794 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
795 NextAfterFootnote()->Enlarge(pos - last - 1, number);
797 lyxerr << "ERROR (LyXParagraph::Enlarge): "
798 "position does not exist." << endl;
802 if (size - last < number) {
803 size += number - size + last + STEP_SIZE_PAR;
804 char * tmp = new char[size];
805 for (int i = 0; i < last; ++i)
815 /* make the allocated memory fit to the needed size */
816 /* used to make a paragraph smaller */
817 void LyXParagraph::FitSize()
819 if (size - last > STEP_SIZE_PAR) {
820 size = last + STEP_SIZE_PAR;
821 char * tmp = new char[size];
822 for (int i = 0; i < last; ++i)
831 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
833 void LyXParagraph::InsertChar(int pos, char c)
837 /* > because last is the next unused position, and you can
838 * use it if you want */
841 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
842 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
845 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
846 "position does not exist." << endl;
849 text.insert(text.begin() + pos, c);
851 /* > because last is the next unused position, and you can
852 * use it if you want */
855 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
856 NextAfterFootnote()->InsertChar(pos - last - 1, c);
858 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
859 "position does not exist." << endl;
862 // Are we full? If so, enlarge.
864 size += STEP_SIZE_PAR;
865 char * tmp = new char[size];
866 for (int i = 0; i < last; i++)
872 // Shift rest of character
873 for (int i = last; i>pos; i--) {
874 text[i] = text[i - 1];
881 // update the font table
882 for(FontList::iterator it = fontlist.begin();
883 it != fontlist.end(); ++it) {
884 if ((*it).pos >= pos)
886 if ((*it).pos_end >= pos)
889 // update the inset table
890 for(InsetList::iterator it = insetlist.begin();
891 it != insetlist.end(); ++it) {
892 if ((*it).pos >= pos)
896 /* update the font table */
897 FontTable * tmp = fonttable;
901 if (tmp->pos_end >= pos)
906 /* update the inset table */
907 InsetTable * tmpi = insettable;
909 if (tmpi->pos >= pos)
917 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
920 void LyXParagraph::InsertInset(int pos, Inset * inset)
923 /* > because last is the next unused position, and you can
924 * use it if you want */
928 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
930 ->InsertInset(pos - text.size() - 1, inset);
932 lyxerr << "ERROR (LyXParagraph::InsertInset): "
933 "position does not exist: " << pos << endl;
939 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
941 ->InsertInset(pos - last - 1, inset);
943 lyxerr << "ERROR (LyXParagraph::InsertInset): "
944 "position does not exist: " << pos << endl;
948 if (text[pos] != LYX_META_INSET) {
949 lyxerr << "ERROR (LyXParagraph::InsertInset): "
950 "there is no LYX_META_INSET" << endl;
959 insetlist.push_back(tmp);
964 /* add a new entry in the inset table */
965 InsetTable * tmpi = new InsetTable;
968 tmpi->next = insettable;
975 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
977 Inset * LyXParagraph::GetInset(int pos)
983 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
984 return NextAfterFootnote()
985 ->GetInset(pos - text.size() - 1);
987 lyxerr << "ERROR (LyXParagraph::GetInset): "
988 "position does not exist: "
996 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
997 return NextAfterFootnote()->GetInset(pos - last - 1);
999 lyxerr << "ERROR (LyXParagraph::GetInset): "
1000 "position does not exist: "
1007 /* find the inset */
1008 for(InsetList::iterator it = insetlist.begin();
1009 it != insetlist.end(); ++it) {
1010 if ((*it).pos == pos) {
1014 lyxerr << "ERROR (LyXParagraph::GetInset): "
1015 "Inset does not exist: " << pos << endl;
1016 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
1017 // Did this commenting out introduce a bug? So far I have not
1018 // seen any, please enlighten me. (Lgb)
1019 // My guess is that since the inset does not exist, we might
1020 // as well replace it with a space to prevent crashes. (Asger)
1023 /* find the inset */
1024 InsetTable * tmpi = insettable;
1026 while (tmpi && tmpi->pos != pos)
1032 lyxerr << "ERROR (LyXParagraph::GetInset): "
1033 "Inset does not exist: " << pos << endl;
1034 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
1035 // Did this commenting out introduce a bug? So far I have not
1036 // seen any, please enlighten me. (Lgb)
1037 // My guess is that since the inset does not exist, we might
1038 // as well replace it with a space to prevent crashes. (Asger)
1045 // Gets uninstantiated font setting at position.
1046 // Optimized after profiling. (Asger)
1048 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos)
1050 LyXFont LyXParagraph::GetFontSettings(int pos)
1056 for(FontList::iterator it = fontlist.begin();
1057 it != fontlist.end(); ++it) {
1058 if (pos >= (*it).pos && pos <= (*it).pos_end)
1062 FontTable * tmp = fonttable;
1064 if (pos >= tmp->pos && pos <= tmp->pos_end)
1070 /* > because last is the next unused position, and you can
1071 * use it if you want */
1072 else if (pos > size()) {
1074 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1075 return NextAfterFootnote()
1076 ->GetFontSettings(pos - text.size() - 1);
1078 // Why is it an error to ask for the font of a
1079 // position that does not exist? Would it be
1080 // enough for this to be anable on debug?
1081 // We want strict error checking, but it's ok to only
1082 // have it when debugging. (Asger)
1083 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
1084 "position does not exist. "
1085 << pos << " (" << static_cast<int>(pos)
1089 return GetFontSettings(pos - 1);
1094 for(FontList::iterator it = fontlist.begin();
1095 it != fontlist.end(); ++it) {
1096 if (pos >= (*it).pos && pos <= (*it).pos_end)
1100 FontTable * tmp = fonttable;
1102 if (pos >= tmp->pos && pos <= tmp->pos_end)
1108 /* > because last is the next unused position, and you can
1109 * use it if you want */
1110 else if (pos > last) {
1112 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1113 return NextAfterFootnote()
1114 ->GetFontSettings(pos - last - 1);
1116 // Why is it an error to ask for the font of a
1117 // position that does not exist? Would it be
1118 // enough for this to be anable on debug?
1119 // We want strict error checking, but it's ok to only
1120 // have it when debugging. (Asger)
1121 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
1122 "position does not exist. " << pos << endl;
1125 return GetFontSettings(pos - 1);
1128 return LyXFont(LyXFont::ALL_INHERIT);
1132 // Gets the fully instantiated font at a given position in a paragraph
1133 // This is basically the same function as LyXText::GetFont() in text2.C.
1134 // The difference is that this one is used for generating the LaTeX file,
1135 // and thus cosmetic "improvements" are disallowed: This has to deliver
1136 // the true picture of the buffer. (Asger)
1137 // If position is -1, we get the layout font of the paragraph.
1138 // If position is -2, we get the font of the manual label of the paragraph.
1140 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos)
1142 LyXFont LyXParagraph::getFont(int pos)
1146 LyXLayout const & layout = textclasslist.Style(GetCurrentTextClass(),
1149 LyXParagraph::size_type main_body = 0;
1153 if (layout.labeltype == LABEL_MANUAL)
1154 main_body = BeginningOfMainBody();
1158 if (pos < main_body)
1159 layoutfont = layout.labelfont;
1161 layoutfont = layout.font;
1162 tmpfont = GetFontSettings(pos);
1163 tmpfont.realize(layoutfont);
1165 // process layoutfont for pos == -1 and labelfont for pos < -1
1167 tmpfont = layout.font;
1169 tmpfont = layout.labelfont;
1172 // check for environment font information
1173 char par_depth = GetDepth();
1174 LyXParagraph * par = this;
1175 while (par && par_depth && !tmpfont.resolved()) {
1176 par = par->DepthHook(par_depth - 1);
1178 tmpfont.realize(textclasslist.
1179 Style(GetCurrentTextClass(),
1180 par->GetLayout()).font);
1181 par_depth = par->GetDepth();
1185 tmpfont.realize(textclasslist.TextClass(GetCurrentTextClass()).defaultfont());
1190 /// Returns the height of the highest font in range
1192 LyXFont::FONT_SIZE LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos, LyXParagraph::size_type endpos) const
1194 LyXFont::FONT_SIZE LyXParagraph::HighestFontInRange(int startpos, int endpos) const
1197 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
1199 for(FontList::const_iterator cit = fontlist.begin();
1200 cit != fontlist.end(); ++cit) {
1201 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
1202 LyXFont::FONT_SIZE size = (*cit).font.size();
1203 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
1208 FontTable * tmp = fonttable;
1210 if (startpos <= tmp->pos_end && endpos >= tmp->pos) {
1211 LyXFont::FONT_SIZE size = tmp->font.size();
1212 if (size > maxsize && size<=LyXFont::SIZE_HUGER)
1223 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
1225 char LyXParagraph::GetChar(int pos)
1228 #ifdef DEVEL_VERSION
1229 /* a workaround to 'fix' some bugs in text-class */
1231 // This function is important. It should not work around bugs.
1232 // Let's find the bugs instead and fix them. (Asger)
1233 lyxerr << "FATAL ERROR (LyXParagraph::GetChar):"
1234 " bad position " << pos << endl;
1243 /* > because last is the next unused position, and you can
1244 * use it if you want */
1245 else if (pos > size()) {
1246 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1247 return NextAfterFootnote()
1248 ->GetChar(pos - text.size() - 1);
1250 lyxerr << "ERROR (LyXParagraph::GetChar): "
1251 "position does not exist."
1252 << pos << " (" << static_cast<int>(pos)
1260 /* > because last is the next unused position, and you can
1261 * use it if you want */
1262 else if (pos > last) {
1263 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1264 return NextAfterFootnote()->GetChar(pos - last - 1);
1266 lyxerr << "ERROR (LyXParagraph::GetChar): "
1267 "position does not exist." << pos << endl;
1271 /* we should have a footnote environment */
1272 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
1273 // Notice that LyX does request the
1274 // last char from time to time. (Asger)
1275 //lyxerr << "ERROR (LyXParagraph::GetChar): "
1276 // "expected footnote." << endl;
1279 switch (next->footnotekind) {
1280 case LyXParagraph::FOOTNOTE:
1281 return LYX_META_FOOTNOTE;
1282 case LyXParagraph::MARGIN:
1283 return LYX_META_MARGIN;
1284 case LyXParagraph::FIG:
1285 case LyXParagraph::WIDE_FIG:
1286 return LYX_META_FIG;
1287 case LyXParagraph::TAB:
1288 case LyXParagraph::WIDE_TAB:
1289 return LYX_META_TAB;
1290 case LyXParagraph::ALGORITHM:
1291 return LYX_META_ALGORITHM;
1293 return '\0'; // to shut up gcc
1299 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos)
1301 string LyXParagraph::GetWord(int & lastpos)
1304 //Added 98/9/21 by REH
1305 // return an string of the current word, and the end of the word
1308 // the current word is defined as starting at the first character from
1309 // the immediate left of lastpospos which meets the definition of IsLetter(),
1310 // continuing to the last character to the right of this meeting
1314 // i just left this in from GetChar()
1316 #ifdef DEVEL_VERSION
1317 /* a workaround to 'fix' some bugs in text-class */
1319 // This function is important. It should not work around bugs.
1320 // Let's find the bugs instead and fix them. (Asger)
1321 lyxerr << "FATAL ERROR (LyXParagraph::GetWord):"
1322 " bad position " << lastpos << endl;
1332 //i think the devcode aborts before this, but why not be
1334 if (lastpos < 0) lastpos=0;
1337 // move back until we have a letter
1339 //there's no real reason to have firstpos & lastpos as
1340 //separate variables as this is written, but maybe someon
1341 // will want to return firstpos in the future.
1343 //since someone might have typed a punctuation first
1344 int firstpos = lastpos;
1346 while ((firstpos >=0) && !IsLetter(firstpos))
1349 // now find the beginning by looking for a nonletter
1351 while ((firstpos>=0) && IsLetter(firstpos))
1354 // the above is now pointing to the preceeding non-letter
1358 // so copy characters into theword until we get a nonletter
1359 // note that this can easily exceed lastpos, wich means
1360 // that if used in the middle of a word, the whole word
1363 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1371 LyXParagraph::size_type LyXParagraph::Last()
1373 int LyXParagraph::Last()
1377 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1378 return text.size() + NextAfterFootnote()->Last() + 1;
1379 /* the 1 is the symbol
1384 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1385 return last + NextAfterFootnote()->Last() + 1;
1386 /* the 1 is the symbol
1395 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
1397 LyXParagraph * LyXParagraph::ParFromPos(int pos)
1401 /* > because last is the next unused position, and you can
1402 * use it if you want */
1405 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1406 return NextAfterFootnote()
1407 ->ParFromPos(pos - text.size() - 1);
1409 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1410 "position does not exist." << endl;
1414 /* > because last is the next unused position, and you can
1415 * use it if you want */
1418 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1419 return NextAfterFootnote()->ParFromPos(pos - last - 1);
1421 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1422 "position does not exist." << endl;
1432 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos)
1434 int LyXParagraph::PositionInParFromPos(int pos)
1437 /* > because last is the next unused position, and you can
1438 * use it if you want */
1442 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1443 return NextAfterFootnote()
1444 ->PositionInParFromPos(pos - text.size() - 1);
1447 "ERROR (LyXParagraph::PositionInParFromPos): "
1448 "position does not exist." << endl;
1454 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1455 return NextAfterFootnote()
1456 ->PositionInParFromPos(pos - last - 1);
1459 "ERROR (LyXParagraph::PositionInParFromPos): "
1460 "position does not exist." << endl;
1470 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1471 LyXFont const & font)
1473 void LyXParagraph::SetFont(int pos, LyXFont const & font)
1476 /* > because last is the next unused position, and you can
1477 * use it if you want */
1480 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1481 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1484 lyxerr << "ERROR (LyXParagraph::SetFont): "
1485 "position does not exist." << endl;
1491 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1492 NextAfterFootnote()->SetFont(pos - last - 1, font);
1494 lyxerr << "ERROR (LyXParagraph::SetFont): "
1495 "position does not exist." << endl;
1500 LyXFont patternfont(LyXFont::ALL_INHERIT);
1502 // First, reduce font against layout/label font
1503 // Update: The SetCharFont() routine in text2.C already reduces font, so
1504 // we don't need to do that here. (Asger)
1505 // No need to simplify this because it will disappear in a new kernel. (Asger)
1507 // Next search font table
1508 for(FontList::iterator it = fontlist.begin();
1509 it != fontlist.end(); ++it) {
1510 if (pos >= (*it).pos && pos <= (*it).pos_end) {
1512 // we found a font entry. maybe we have to
1513 // split it and create a new one
1515 if ((*it).pos != (*it).pos_end) {
1516 // more than one character
1517 if (pos == (*it).pos) {
1518 // maybe we could enlarge
1519 // the left fonttable
1520 for(FontList::iterator fit = fontlist.begin();
1521 fit != fontlist.end(); ++fit) {
1522 if (pos - 1 >= (*fit).pos
1523 && pos - 1 <= (*fit).pos_end
1524 && (*fit).font == font) {
1532 // Add a new entry in the
1533 // fonttable for the position
1536 tmp.pos_end = (*it).pos_end;
1537 tmp.font = (*it).font;
1538 (*it).pos_end = pos;
1539 fontlist.push_back(tmp);
1540 } else if (pos == (*it).pos_end) {
1541 // Add a new entry in the
1542 // fonttable for the position
1544 tmp.pos = (*it).pos;
1545 tmp.pos_end = (*it).pos_end - 1;
1546 tmp.font = (*it).font;
1547 (*it).pos = (*it).pos_end;
1548 fontlist.push_back(tmp);
1550 // Add a new entry in the
1551 // fonttable for the position
1553 tmp.pos = (*it).pos;
1554 tmp.pos_end = pos - 1;
1555 tmp.font = (*it).font;
1556 fontlist.push_back(tmp);
1559 tmp.pos_end = (*it).pos_end;
1560 tmp.font = (*it).font;
1561 fontlist.push_back(tmp);
1564 (*it).pos_end = pos;
1572 // if we did not find a font entry, but if the font at hand
1573 // is the same as default, we just forget it
1574 if (font == patternfont) return;
1576 // ok, we did not find a font entry. But maybe there is exactly
1577 // the needed font entry one position left
1578 for(FontList::iterator it = fontlist.begin();
1579 it != fontlist.end(); ++it) {
1580 if (pos - 1 >= (*it).pos && pos - 1 <= (*it).pos_end
1581 && (*it).font == font) {
1586 // Add a new entry in the
1587 // fonttable for the position
1591 tmp.font = patternfont;
1592 fontlist.push_back(tmp);
1594 // Next search font table
1598 FontTable * tmp = fonttable;
1599 while (tmp && !found) {
1600 if (pos >= tmp->pos && pos <= tmp->pos_end)
1607 /* if we did not find a font entry, but if the font at hand
1608 * is the same as default, we just forget it */
1609 if (font == patternfont)
1612 /* ok, we did not find a font entry. But maybe there is exactly
1613 * the needed font entry one position left */
1616 while (tmp2 && !found) {
1617 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1623 /* ok there is one. maybe it is exactly the needed font */
1624 if (tmp2->font == font) {
1625 /* put the position under the font */
1630 /* Add a new entry in the
1631 * fonttable for the position */
1632 tmp = new FontTable;
1635 tmp->font = patternfont;
1636 tmp->next = fonttable;
1639 /* we found a font entry. maybe we have to split it and create
1642 if (tmp->pos != tmp->pos_end) { /* more than one character */
1644 if (pos == tmp->pos) {
1645 /* maybe we could enlarge the left fonttable */
1649 while (tmp2 && !found) {
1650 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1656 /* Is there is one, and is it exactly the needed font? */
1657 if (found && tmp2->font == font) {
1658 /* put the position under the font */
1664 /* Add a new entry in the
1665 * fonttable for the position */
1666 tmp2 = new FontTable;
1667 tmp2->pos = pos + 1;
1668 tmp2->pos_end = tmp->pos_end;
1669 tmp2->font = tmp->font;
1671 tmp2->next = fonttable;
1674 else if (pos == tmp->pos_end) {
1675 /* Add a new entry in the
1676 * fonttable for the position */
1677 tmp2 = new FontTable;
1678 tmp2->pos = tmp->pos;
1679 tmp2->pos_end = tmp->pos_end - 1;
1680 tmp2->font = tmp->font;
1681 tmp->pos = tmp->pos_end;
1682 tmp2->next = fonttable;
1686 /* Add a new entry in the
1687 * fonttable for the position */
1688 tmp2 = new FontTable;
1689 tmp2->pos = tmp->pos;
1690 tmp2->pos_end = pos - 1;
1691 tmp2->font = tmp->font;
1692 tmp2->next = fonttable;
1695 tmp2 = new FontTable;
1696 tmp2->pos = pos + 1;
1697 tmp2->pos_end = tmp->pos_end;
1698 tmp2->font = tmp->font;
1699 tmp2->next = fonttable;
1712 /* this function is able to hide closed footnotes */
1713 LyXParagraph * LyXParagraph::Next()
1715 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1716 LyXParagraph * tmp = next;
1718 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1720 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1721 return tmp->Next(); /* there can be more than one
1722 footnote in a logical
1725 return next; /* this should never happen! */
1732 LyXParagraph * LyXParagraph::NextAfterFootnote()
1734 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1735 LyXParagraph * tmp = next;
1736 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1738 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1739 return tmp; /* there can be more than one footnote
1740 in a logical paragraph */
1742 return next; /* this should never happen! */
1749 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1752 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1754 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1755 tmp = tmp->previous;
1756 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1757 return tmp; /* there can be more than one footnote
1758 in a logical paragraph */
1760 return previous; /* this should never happen! */
1767 LyXParagraph * LyXParagraph::LastPhysicalPar()
1769 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1772 LyXParagraph * tmp = this;
1773 while (tmp->next && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1774 tmp = tmp->NextAfterFootnote();
1781 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1785 LyXParagraph * tmppar = this;
1787 while (tmppar && (tmppar->IsDummy()
1788 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1789 tmppar = tmppar->previous;
1792 return this; /* this should never happen! */
1798 /* this function is able to hide closed footnotes */
1799 LyXParagraph * LyXParagraph::Previous()
1801 LyXParagraph * tmp = previous;
1806 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1807 tmp = tmp->previous;
1809 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1810 tmp = tmp->previous;
1811 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1812 return tmp->next->Previous();
1822 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1825 void LyXParagraph::BreakParagraph(int pos, int flag)
1829 size_type i, pos_end, pos_first;
1831 int i, pos_end, pos_first;
1833 /* create a new paragraph */
1834 LyXParagraph * par = ParFromPos(pos);
1835 LyXParagraph * firstpar = FirstPhysicalPar();
1837 LyXParagraph * tmp = new LyXParagraph(par);
1839 tmp->footnoteflag = footnoteflag;
1840 tmp->footnotekind = footnotekind;
1842 /* this is an idea for a more userfriendly layout handling, I will
1843 * see what the users say */
1845 /* layout stays the same with latex-environments */
1847 tmp->SetOnlyLayout(firstpar->layout);
1848 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1851 if (Last() > pos || !Last() || flag == 2) {
1852 tmp->SetOnlyLayout(firstpar->layout);
1853 tmp->align = firstpar->align;
1854 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1856 tmp->line_bottom = firstpar->line_bottom;
1857 firstpar->line_bottom = false;
1858 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1859 firstpar->pagebreak_bottom = false;
1860 tmp->added_space_bottom = firstpar->added_space_bottom;
1861 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1863 tmp->depth = firstpar->depth;
1864 tmp->noindent = firstpar->noindent;
1866 /* copy everything behind the break-position
1867 to the new paragraph
1870 while (ParFromPos(pos_first) != par)
1874 pos_end = pos_first + par->text.size() - 1;
1876 pos_end = pos_first + par->last - 1;
1877 /* make sure there is enough memory for the now larger
1878 paragraph. This is not neccessary, because
1879 InsertFromMinibuffer will enlarge the memory (it uses
1880 InsertChar of course). But doing it by hand
1881 is MUCH faster! (only one time, not thousend times!!) */
1882 tmp->Enlarge(0, pos_end - pos);
1884 for (i = pos; i <= pos_end; i++) {
1885 par->CutIntoMinibuffer(i - pos_first);
1886 tmp->InsertFromMinibuffer(i - pos);
1889 for (i = pos_end; i >= pos; i--)
1890 par->Erase(i - pos_first);
1892 /* free memory of the now shorter paragraph*/
1897 /* just an idea of me */
1899 tmp->line_top = firstpar->line_top;
1900 tmp->pagebreak_top = firstpar->pagebreak_top;
1901 tmp->added_space_top = firstpar->added_space_top;
1902 tmp->bibkey = firstpar->bibkey;
1904 /* layout stays the same with latex-environments */
1906 firstpar->SetOnlyLayout(tmp->layout);
1907 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1908 firstpar->depth = tmp->depth;
1914 void LyXParagraph::MakeSameLayout(LyXParagraph * par)
1916 par = par->FirstPhysicalPar();
1917 footnoteflag = par->footnoteflag;
1918 footnotekind = par->footnotekind;
1920 layout = par->layout;
1921 align = par-> align;
1922 SetLabelWidthString(par->labelwidthstring);
1924 line_bottom = par->line_bottom;
1925 pagebreak_bottom = par->pagebreak_bottom;
1926 added_space_bottom = par->added_space_bottom;
1928 line_top = par->line_top;
1929 pagebreak_top = par->pagebreak_top;
1930 added_space_top = par->added_space_top;
1932 pextra_type = par->pextra_type;
1933 pextra_width = par->pextra_width;
1934 pextra_widthp = par->pextra_widthp;
1935 pextra_alignment = par->pextra_alignment;
1936 pextra_hfill = par->pextra_hfill;
1937 pextra_start_minipage = par->pextra_start_minipage;
1939 noindent = par->noindent;
1944 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1946 LyXParagraph * tmppar = this;
1949 && tmppar->previous->footnoteflag ==
1950 LyXParagraph::CLOSED_FOOTNOTE)
1951 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1952 tmppar = tmppar->previous;
1955 return this; /* this should never happen! */
1961 LyXParagraph * LyXParagraph::Clone()
1963 /* create a new paragraph */
1964 LyXParagraph * result = new LyXParagraph();
1966 result->MakeSameLayout(this);
1968 /* this is because of the dummy layout of the paragraphs that
1970 result->layout = layout;
1972 /* table stuff -- begin*/
1974 result->table = table->Clone();
1977 /* table stuff -- end*/
1980 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1983 /* copy everything behind the break-position to the new paragraph */
1986 for (size_type i = 0; i < size(); i++) {
1987 CopyIntoMinibuffer(i);
1988 result->InsertFromMinibuffer(i);
1991 /* make shure there is enough memory for the now larger paragraph.
1992 * This is not neccessary, because InsertFromMinibuffer will enlarge
1993 * the memory (it uses InsertChar of course). But doing it by hand
1994 * is MUCH faster! (only one time, not thousend times!!) */
1995 result->Enlarge(0, last+2);
1996 for (int i = 0; i < last; i++) {
1997 CopyIntoMinibuffer(i);
1998 result->InsertFromMinibuffer(i);
2005 bool LyXParagraph::HasSameLayout(LyXParagraph * par)
2007 par = par->FirstPhysicalPar();
2010 par->footnoteflag == footnoteflag &&
2011 par->footnotekind == footnotekind &&
2013 par->layout == layout &&
2015 par->align == align &&
2017 par->line_bottom == line_bottom &&
2018 par->pagebreak_bottom == pagebreak_bottom &&
2019 par->added_space_bottom == added_space_bottom &&
2021 par->line_top == line_top &&
2022 par->pagebreak_top == pagebreak_top &&
2023 par->added_space_top == added_space_top &&
2025 par->pextra_type == pextra_type &&
2026 par->pextra_width == pextra_width &&
2027 par->pextra_widthp == pextra_widthp &&
2028 par->pextra_alignment == pextra_alignment &&
2029 par->pextra_hfill == pextra_hfill &&
2030 par->pextra_start_minipage == pextra_start_minipage &&
2032 par->table == table && // what means: NO TABLE AT ALL
2034 par->noindent == noindent &&
2035 par->depth == depth);
2039 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
2041 void LyXParagraph::BreakParagraphConservative(int pos)
2045 size_type i, pos_end, pos_first;
2047 int i, pos_end, pos_first;
2050 /* create a new paragraph */
2051 LyXParagraph * par = ParFromPos(pos);
2053 LyXParagraph * tmp = new LyXParagraph(par);
2055 tmp->MakeSameLayout(par);
2058 /* copy everything behind the break-position to the new
2061 while (ParFromPos(pos_first) != par)
2064 pos_end = pos_first + par->text.size() - 1;
2066 pos_end = pos_first + par->last - 1;
2068 /* make shure there is enough memory for the now larger
2069 paragraph. This is not neccessary, because
2070 InsertFromMinibuffer will enlarge the memory (it uses
2071 InsertChar of course). But doing it by hand
2072 is MUCH faster! (only one time, not thousend times!!) */
2074 tmp->Enlarge(0, pos_end - pos);
2076 for (i = pos; i <= pos_end; i++) {
2078 par->CutIntoMinibuffer(i - pos_first);
2079 tmp->InsertFromMinibuffer(i - pos);
2081 for (i = pos_end; i >= pos; i--)
2082 par->Erase(i - pos_first);
2084 /* free memory of the now shorter paragraph*/
2091 /* be carefull, this does not make any check at all */
2092 void LyXParagraph::PasteParagraph()
2094 /* copy the next paragraph to this one */
2095 LyXParagraph * the_next = Next();
2097 LyXParagraph * firstpar = FirstPhysicalPar();
2099 /* first the DTP-stuff */
2100 firstpar->line_bottom = the_next->line_bottom;
2101 firstpar->added_space_bottom = the_next->added_space_bottom;
2102 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
2105 size_type pos_end = the_next->text.size() - 1;
2106 size_type pos_insert = Last();
2109 int pos_end = the_next->last - 1;
2110 int pos_insert = Last();
2111 /* enlarge the paragraph. This is faster than enlarge it
2112 * every 10th insertion. */
2114 Enlarge(pos_insert, pos_end);
2118 /* ok, now copy the paragraph */
2119 for (i = 0; i <= pos_end; i++) {
2120 the_next->CutIntoMinibuffer(i);
2121 InsertFromMinibuffer(pos_insert + i);
2124 /* delete the next paragraph */
2129 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
2131 void LyXParagraph::OpenFootnote(int pos)
2134 LyXParagraph * par = ParFromPos(pos);
2136 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2137 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
2143 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
2145 void LyXParagraph::CloseFootnote(int pos)
2148 LyXParagraph * par = ParFromPos(pos);
2150 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
2151 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
2157 LyXTextClass::LayoutList::size_type LyXParagraph::GetLayout()
2159 return FirstPhysicalPar()->layout;
2163 char LyXParagraph::GetDepth()
2165 return FirstPhysicalPar()->depth;
2169 char LyXParagraph::GetAlign()
2171 return FirstPhysicalPar()->align;
2175 string LyXParagraph::GetLabestring()
2177 return FirstPhysicalPar()->labelstring;
2181 int LyXParagraph::GetFirstCounter(int i)
2183 return FirstPhysicalPar()->counter[i];
2187 /* the next two functions are for the manual labels */
2188 string LyXParagraph::GetLabelWidthString()
2190 if (!FirstPhysicalPar()->labelwidthstring.empty())
2191 return FirstPhysicalPar()->labelwidthstring;
2193 return _("Senseless with this layout!");
2197 void LyXParagraph::SetLabelWidthString(string const & s)
2199 LyXParagraph * par = FirstPhysicalPar();
2201 par->labelwidthstring = s;
2205 void LyXParagraph::SetOnlyLayout(LyXTextClass::LayoutList::size_type new_layout)
2207 LyXParagraph * par = FirstPhysicalPar();
2208 LyXParagraph * ppar = 0;
2209 LyXParagraph * npar = 0;
2211 par->layout = new_layout;
2212 /* table stuff -- begin*/
2215 /* table stuff -- end*/
2216 if (par->pextra_type == PEXTRA_NONE) {
2217 if (par->Previous()) {
2218 ppar = par->Previous()->FirstPhysicalPar();
2221 && (ppar->depth > par->depth))
2222 ppar = ppar->Previous()->FirstPhysicalPar();
2225 npar = par->Next()->NextAfterFootnote();
2228 && (npar->depth > par->depth))
2229 npar = npar->Next()->NextAfterFootnote();
2231 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
2233 p1 = ppar->pextra_width,
2234 p2 = ppar->pextra_widthp;
2235 ppar->SetPExtraType(ppar->pextra_type,
2236 p1.c_str(),p2.c_str());
2238 if ((par->pextra_type == PEXTRA_NONE) &&
2239 npar && (npar->pextra_type != PEXTRA_NONE)) {
2241 p1 = npar->pextra_width,
2242 p2 = npar->pextra_widthp;
2243 npar->SetPExtraType(npar->pextra_type,
2244 p1.c_str(),p2.c_str());
2250 void LyXParagraph::SetLayout(LyXTextClass::LayoutList::size_type new_layout)
2253 * par = FirstPhysicalPar(),
2257 par->layout = new_layout;
2258 par->labelwidthstring.clear();
2259 par->align = LYX_ALIGN_LAYOUT;
2260 par->added_space_top = VSpace(VSpace::NONE);
2261 par->added_space_bottom = VSpace(VSpace::NONE);
2262 /* table stuff -- begin*/
2265 /* table stuff -- end*/
2266 if (par->pextra_type == PEXTRA_NONE) {
2267 if (par->Previous()) {
2268 ppar = par->Previous()->FirstPhysicalPar();
2271 && (ppar->depth > par->depth))
2272 ppar = ppar->Previous()->FirstPhysicalPar();
2275 npar = par->Next()->NextAfterFootnote();
2278 && (npar->depth > par->depth))
2279 npar = npar->Next()->NextAfterFootnote();
2281 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
2283 p1 = ppar->pextra_width,
2284 p2 = ppar->pextra_widthp;
2285 ppar->SetPExtraType(ppar->pextra_type,
2286 p1.c_str(),p2.c_str());
2288 if ((par->pextra_type == PEXTRA_NONE) &&
2289 npar && (npar->pextra_type != PEXTRA_NONE)) {
2291 p1 = npar->pextra_width,
2292 p2 = npar->pextra_widthp;
2293 npar->SetPExtraType(npar->pextra_type,
2294 p1.c_str(),p2.c_str());
2300 /* if the layout of a paragraph contains a manual label, the beginning of the
2301 * main body is the beginning of the second word. This is what the par-
2302 * function returns. If the layout does not contain a label, the main
2303 * body always starts with position 0. This differentiation is necessary,
2304 * because there cannot be a newline or a blank <= the beginning of the
2305 * main body in TeX. */
2307 int LyXParagraph::BeginningOfMainBody()
2309 if (FirstPhysicalPar() != this)
2313 // Unroll the first two cycles of the loop
2314 // and remember the previous character to remove unnecessary GetChar() calls
2318 && GetChar(i) != LYX_META_NEWLINE) {
2320 char previous_char, temp;
2322 && (previous_char = GetChar(i)) != LYX_META_NEWLINE) {
2323 // Yes, this ^ is supposed to be "=" not "=="
2326 && previous_char != ' '
2327 && (temp = GetChar(i)) != LYX_META_NEWLINE) {
2329 previous_char = temp;
2334 if (i == 0 && i == size() &&
2335 !(footnoteflag==LyXParagraph::NO_FOOTNOTE
2336 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
2337 i++; /* the cursor should not jump
2338 * to the main body if there
2343 && GetChar(i) != LYX_META_NEWLINE) {
2345 char previous_char, temp;
2347 && (previous_char = GetChar(i)) != LYX_META_NEWLINE) {
2348 // Yes, this ^ is supposed to be "=" not "=="
2351 && previous_char != ' '
2352 && (temp = GetChar(i)) != LYX_META_NEWLINE) {
2354 previous_char = temp;
2359 if (i==0 && i == last &&
2360 !(footnoteflag==LyXParagraph::NO_FOOTNOTE
2361 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
2363 i++; /* the cursor should not jump
2364 * to the main body if there
2371 LyXParagraph * LyXParagraph::DepthHook(int deth)
2373 LyXParagraph * newpar = this;
2378 newpar = newpar->FirstPhysicalPar()->Previous();
2379 } while (newpar && newpar->GetDepth() > deth
2380 && newpar->footnoteflag == footnoteflag);
2383 if (Previous() || GetDepth())
2384 lyxerr << "ERROR (LyXParagraph::DepthHook): "
2388 return newpar->FirstPhysicalPar();
2392 int LyXParagraph::AutoDeleteInsets()
2396 for (InsetList::iterator it = insetlist.begin();
2397 it != insetlist.end(); ++it) {
2398 if ((*it).inset->AutoDelete()) {
2405 InsetTable * tmpi = insettable;
2406 InsetTable * tmpi2 = tmpi;
2412 if (tmpi2->inset->AutoDelete()) {
2417 lyxerr << "ERROR (LyXParagraph::AutoDeleteInsets): "
2418 "cannot auto-delete insets" << endl;
2426 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
2428 Inset * LyXParagraph::ReturnNextInsetPointer(int & pos)
2432 InsetTable * tmp = 0;
2433 for (InsetList::iterator it = insetlist.begin();
2434 it != insetlist.end(); ++it) {
2435 if ((*it).pos >= pos && (!tmp || (*it).pos < tmp->pos)) {
2446 InsetTable * tmpi = insettable;
2447 InsetTable * tmpi2 = 0;
2449 if (tmpi->pos >= pos) {
2450 if (!tmpi2 || tmpi->pos < tmpi2->pos)
2457 return tmpi2->inset;
2465 /* returns -1 if inset not found */
2466 int LyXParagraph::GetPositionOfInset(Inset * inset)
2469 for (InsetList::iterator it = insetlist.begin();
2470 it != insetlist.end(); ++it) {
2471 if ((*it).inset == inset) {
2475 // Think about footnotes
2476 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
2477 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2478 int further = NextAfterFootnote()->GetPositionOfInset(inset);
2481 return size() + 1 + further;
2484 return last + 1 + further;
2489 /* find the entry */
2490 InsetTable * tmpi = insettable;
2491 while (tmpi && tmpi->inset != inset) {
2494 if (tmpi && tmpi->inset)
2497 /* think about footnotes */
2498 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
2499 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2501 NextAfterFootnote()->GetPositionOfInset(inset);
2504 return text.size() + 1 + further;
2507 return last + 1 + further;
2516 void LyXParagraph::readSimpleWholeFile(FILE * myfile)
2520 FileInfo fileInfo(fileno(myfile));
2521 long file_size = fileInfo.getSize();
2522 /* it is horrible, I know, but faster.
2523 * I should not use InsertString for that :-( */
2525 /* I will write a better insertion in the future */
2526 Enlarge(0, file_size + 10);
2530 if (!feof(myfile)) {
2535 InsertChar(text.size(), c);
2539 } while (!feof(myfile));
2545 LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow,
2546 string & foot, TexRow & foot_texrow,
2549 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
2550 LyXParagraph * par = next;
2551 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), layout);
2553 bool further_blank_line = false;
2555 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
2557 if (start_of_appendix) {
2558 file += "\\appendix\n";
2562 if (tex_code_break_column && style.isCommand()){
2567 if (pagebreak_top) {
2568 file += "\\newpage";
2569 further_blank_line = true;
2571 if (added_space_top.kind() != VSpace::NONE) {
2572 file += added_space_top.asLatexCommand();
2573 further_blank_line = true;
2577 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
2578 file += "\\vspace{-1\\parskip}";
2579 further_blank_line = true;
2582 if (further_blank_line){
2587 switch (style.latextype) {
2590 file += style.latexname();
2591 file += style.latexparam();
2593 case LATEX_ITEM_ENVIRONMENT:
2595 bibkey->Latex(file, false);
2599 case LATEX_LIST_ENVIRONMENT:
2606 bool need_par = SimpleTeXOnePar(file, texrow);
2608 // Spit out footnotes
2609 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2610 && par->footnoteflag != footnoteflag) {
2611 par = par->TeXFootnote(file, texrow,
2612 foot, foot_texrow, foot_count);
2613 par->SimpleTeXOnePar(file, texrow);
2617 // Make sure that \\par is done with the font of the last
2618 // character if this has another size as the default.
2619 // This is necessary because LaTeX (and LyX on the screen)
2620 // calculates the space between the baselines according
2621 // to this font. (Matthias)
2622 LyXFont font = getFont(Last()-1);
2624 if (style.resfont.size() != font.size()) {
2626 file += font.latexSize();
2630 } else if (textclasslist.Style(GetCurrentTextClass(),
2631 GetLayout()).isCommand()){
2632 if (style.resfont.size() != font.size()) {
2634 file += font.latexSize();
2638 } else if (style.resfont.size() != font.size()){
2639 file += "{\\" + font.latexSize() + " \\par}";
2642 switch (style.latextype) {
2643 case LATEX_ITEM_ENVIRONMENT:
2644 case LATEX_LIST_ENVIRONMENT:
2645 if (par && (depth < par->depth)) {
2650 case LATEX_ENVIRONMENT:
2651 // if its the last paragraph of the current environment
2652 // skip it otherwise fall through
2654 && (par->layout != layout
2655 || par->depth != depth
2656 || par->pextra_type != pextra_type))
2659 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2660 && footnotekind != LyXParagraph::FOOTNOTE
2661 && footnotekind != LyXParagraph::MARGIN
2665 // don't insert this if we would be adding it
2666 // before or after a table in a float. This
2667 // little trick is needed in order to allow
2668 // use of tables in \subfigures or \subtables.
2674 further_blank_line = false;
2676 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2677 further_blank_line = true;
2680 if (added_space_bottom.kind() != VSpace::NONE) {
2681 file += added_space_bottom.asLatexCommand();
2682 further_blank_line = true;
2685 if (pagebreak_bottom) {
2686 file += "\\newpage";
2687 further_blank_line = true;
2690 if (further_blank_line){
2695 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2696 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2701 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2706 // This one spits out the text of the paragraph
2707 bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow)
2709 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2712 return SimpleTeXOneTablePar(file, texrow);
2716 size_type main_body;
2721 bool return_value = false;
2723 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), GetLayout());
2726 /* maybe we have to create a optional argument */
2727 if (style.labeltype != LABEL_MANUAL)
2730 main_body = BeginningOfMainBody();
2732 if (main_body > 0) {
2734 basefont = getFont(-2); // Get label font
2736 basefont = getFont(-1); // Get layout font
2748 if (style.isCommand()) {
2751 } else if (align != LYX_ALIGN_LAYOUT) {
2754 return_value = true;
2758 // Which font is currently active?
2759 LyXFont running_font = basefont;
2760 // Do we have an open font change?
2761 bool open_font = false;
2763 texrow.start(this, 0);
2766 for (size_type i = 0; i < size(); ++i) {
2768 for (int i = 0; i < last; ++i) {
2771 // First char in paragraph or after label?
2772 if (i == main_body && !IsDummy()) {
2773 if (main_body > 0) {
2775 column += running_font.latexWriteEndChanges(file, basefont);
2778 basefont = getFont(-1); // Now use the layout font
2779 running_font = basefont;
2783 if (style.isCommand()) {
2786 } else if (align != LYX_ALIGN_LAYOUT) {
2789 return_value = true;
2793 file += "\\noindent ";
2797 case LYX_ALIGN_NONE:
2798 case LYX_ALIGN_BLOCK:
2799 case LYX_ALIGN_LAYOUT:
2800 case LYX_ALIGN_SPECIAL: break;
2801 case LYX_ALIGN_LEFT:
2802 file += "\\raggedright ";
2805 case LYX_ALIGN_RIGHT:
2806 file += "\\raggedleft ";
2809 case LYX_ALIGN_CENTER:
2810 file += "\\centering ";
2818 // Fully instantiated font
2819 LyXFont font = getFont(i);
2821 // Spaces at end of font change are simulated to be
2822 // outside font change, i.e. we write "\textXX{text} "
2823 // rather than "\textXX{text }". (Asger)
2825 if (open_font && c == ' ' && i <= size() - 2
2826 && !getFont(i+1).equalExceptLatex(running_font)
2827 && !getFont(i+1).equalExceptLatex(font)) {
2828 font = getFont(i+1);
2831 if (open_font && c == ' ' && i <= last-2
2832 && !getFont(i+1).equalExceptLatex(running_font)
2833 && !getFont(i+1).equalExceptLatex(font)) {
2834 font = getFont(i+1);
2837 // We end font definition before blanks
2838 if (!font.equalExceptLatex(running_font) && open_font) {
2839 column += running_font.latexWriteEndChanges(file, basefont);
2840 running_font = basefont;
2844 // Blanks are printed before start of fontswitch
2846 // Do not print the separation of the optional argument
2847 if (i != main_body - 1) {
2848 SimpleTeXBlanks(file, texrow, i, column, font, style);
2852 // Do we need to change font?
2853 if (!font.equalExceptLatex(running_font)
2854 && i != main_body-1) {
2855 column += font.latexWriteStartChanges(file, basefont);
2856 running_font = font;
2860 if (c == LYX_META_NEWLINE) {
2861 // newlines are handled differently here than
2862 // the default in SimpleTeXSpecialChars().
2863 if (!style.newline_allowed
2864 || font.latex() == LyXFont::ON) {
2868 column += running_font.latexWriteEndChanges(file, basefont);
2871 basefont = getFont(-1);
2872 running_font = basefont;
2873 if (font.family() ==
2874 LyXFont::TYPEWRITER_FAMILY) {
2880 texrow.start(this, i+1);
2883 SimpleTeXSpecialChars(file, texrow,
2884 font, running_font, basefont,
2885 open_font, style, i, column, c);
2889 // If we have an open font definition, we have to close it
2891 running_font.latexWriteEndChanges(file, basefont);
2895 /* needed if there is an optional argument but no contents */
2896 if (main_body > 0 && main_body == size()) {
2898 return_value = false;
2901 /* needed if there is an optional argument but no contents */
2902 if (main_body > 0 && main_body == last) {
2904 return_value = false;
2907 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2908 return return_value;
2912 // This one spits out the text of a table paragraph
2913 bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow)
2915 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2919 bool return_value = false;
2920 int current_cell_number = -1;
2922 LyXLayout const & style =
2923 textclasslist.Style(GetCurrentTextClass(), GetLayout());
2924 LyXFont basefont = getFont(-1); // Get layout font
2925 // Which font is currently active?
2926 LyXFont running_font = basefont;
2927 // Do we have an open font change?
2928 bool open_font = false;
2931 if (!IsDummy()) { // it is dummy if it is in a float!!!
2932 if (style.isCommand()) {
2935 } else if (align != LYX_ALIGN_LAYOUT) {
2938 return_value = true;
2941 file += "\\noindent ";
2945 case LYX_ALIGN_NONE:
2946 case LYX_ALIGN_BLOCK:
2947 case LYX_ALIGN_LAYOUT:
2948 case LYX_ALIGN_SPECIAL: break;
2949 case LYX_ALIGN_LEFT:
2950 file += "\\raggedright ";
2953 case LYX_ALIGN_RIGHT:
2954 file += "\\raggedleft ";
2957 case LYX_ALIGN_CENTER:
2958 file += "\\centering ";
2963 current_cell_number = -1;
2964 tmp = table->TexEndOfCell(file,current_cell_number);
2965 for (; tmp >0 ; --tmp)
2968 texrow.start(this, 0);
2971 for (size_type i = 0; i < size(); ++i) {
2973 for (int i = 0; i < last; ++i) {
2976 if (table->IsContRow(current_cell_number+1)) {
2977 if (c == LYX_META_NEWLINE)
2978 current_cell_number++;
2983 // Fully instantiated font
2984 LyXFont font = getFont(i);
2986 // Spaces at end of font change are simulated to be outside font change.
2987 // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
2989 if (open_font && c == ' ' && i <= size() - 2
2991 if (open_font && c == ' ' && i <= last-2
2993 && getFont(i+1) != running_font && getFont(i+1) != font) {
2994 font = getFont(i+1);
2997 // We end font definition before blanks
2998 if (font != running_font && open_font) {
2999 column += running_font.latexWriteEndChanges(file, basefont);
3000 running_font = basefont;
3003 // Blanks are printed before start of fontswitch
3005 SimpleTeXBlanks(file, texrow, i, column, font, style);
3007 // Do we need to change font?
3008 if (font != running_font) {
3009 column += font.latexWriteStartChanges(file, basefont);
3010 running_font = font;
3013 // Do we need to turn on LaTeX mode?
3014 if (font.latex() != running_font.latex()) {
3015 if (font.latex() == LyXFont::ON
3016 && style.needprotect) {
3017 file += "\\protect ";
3021 if (c == LYX_META_NEWLINE) {
3022 // special case for inside a table
3023 // different from default case in SimpleTeXSpecialChars()
3025 column += running_font.latexWriteEndChanges(file, basefont);
3028 basefont = getFont(-1);
3029 running_font = basefont;
3030 current_cell_number++;
3031 if (table->CellHasContRow(current_cell_number) >= 0) {
3032 TeXContTableRows(file, i+1, current_cell_number, column, texrow);
3034 // if this cell follow only ContRows till end don't
3035 // put the EndOfCell because it is put after the
3037 if (table->ShouldBeVeryLastCell(current_cell_number)) {
3038 current_cell_number--;
3041 int tmp = table->TexEndOfCell(file, current_cell_number);
3044 } else if (tmp < 0) {
3050 texrow.start(this, i+1);
3052 SimpleTeXSpecialChars(file, texrow,
3053 font, running_font, basefont,
3054 open_font, style, i, column, c);
3058 // If we have an open font definition, we have to close it
3060 running_font.latexWriteEndChanges(file, basefont);
3062 current_cell_number++;
3063 tmp = table->TexEndOfCell(file, current_cell_number);
3064 for (; tmp > 0; --tmp)
3066 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
3067 return return_value;
3071 // This one spits out the text off ContRows in tables
3073 bool LyXParagraph::TeXContTableRows(string & file,
3074 LyXParagraph::size_type i,
3075 int current_cell_number,
3076 int & column, TexRow & texrow)
3078 bool LyXParagraph::TeXContTableRows(string & file, int i,
3079 int current_cell_number,
3080 int & column, TexRow & texrow)
3083 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
3089 bool return_value = false;
3090 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), GetLayout());
3093 basefont = getFont(-1); // Get layout font
3094 // Which font is currently active?
3095 LyXFont running_font = basefont;
3096 // Do we have an open font change?
3097 bool open_font = false;
3100 size_type lastpos = i;
3104 int cell = table->CellHasContRow(current_cell_number);
3105 current_cell_number++;
3107 // first find the right position
3110 for (; (i < size()) && (current_cell_number<cell); ++i) {
3112 for (; (i < last) && (current_cell_number<cell); ++i) {
3115 if (c == LYX_META_NEWLINE)
3116 current_cell_number++;
3120 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3124 } else if ((c != ' ') && (c != LYX_META_NEWLINE)) {
3128 for (; i < size() && (c = GetChar(i)) != LYX_META_NEWLINE;
3131 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE);
3136 // Fully instantiated font
3137 LyXFont font = getFont(i);
3139 // Spaces at end of font change are simulated to be outside font change.
3140 // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
3142 if (open_font && c == ' ' && i <= size() - 2
3143 && getFont(i + 1) != running_font
3144 && getFont(i + 1) != font) {
3146 if (open_font && c == ' ' && i <= last - 2
3147 && getFont(i + 1) != running_font
3148 && getFont(i + 1) != font) {
3150 font = getFont(i + 1);
3153 // We end font definition before blanks
3154 if (font != running_font && open_font) {
3155 column += running_font.latexWriteEndChanges(file, basefont);
3156 running_font = basefont;
3159 // Blanks are printed before start of fontswitch
3161 SimpleTeXBlanks(file, texrow, i, column, font, style);
3163 // Do we need to change font?
3164 if (font != running_font) {
3165 column += font.latexWriteStartChanges(file, basefont);
3166 running_font = font;
3169 // Do we need to turn on LaTeX mode?
3170 if (font.latex() != running_font.latex()) {
3171 if (font.latex() == LyXFont::ON
3172 && style.needprotect)
3174 file += "\\protect ";
3178 SimpleTeXSpecialChars(file, texrow, font, running_font, basefont,
3179 open_font, style, i, column, c);
3181 // If we have an open font definition, we have to close it
3183 running_font.latexWriteEndChanges(file, basefont);
3186 basefont = getFont(-1);
3187 running_font = basefont;
3188 cell = table->CellHasContRow(current_cell_number);
3190 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
3191 return return_value;
3195 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
3197 bool retval = false;
3199 case LYX_META_HFILL:
3200 sgml_string.clear();
3202 case LYX_META_PROTECTED_SEPARATOR:
3205 case LYX_META_NEWLINE:
3209 sgml_string = "&";
3212 sgml_string = "<";
3215 sgml_string = ">";
3218 sgml_string = "$";
3221 sgml_string = "#";
3224 sgml_string = "%";
3227 sgml_string = "[";
3230 sgml_string = "]";
3233 sgml_string = "{";
3236 sgml_string = "}";
3239 sgml_string = "˜";
3242 sgml_string = """;
3245 sgml_string = "\";
3251 case '\0': /* Ignore :-) */
3252 sgml_string.clear();
3261 void LyXParagraph::SimpleDocBookOneTablePar(string & file, string & extra,
3262 int & desc_on, int depth)
3266 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
3268 int current_cell_number = -1;
3269 LyXFont font1,font2;
3273 size_type main_body;
3277 string emph = "emphasis";
3278 bool emph_flag=false;
3279 int char_line_count=0;
3281 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), GetLayout());
3283 if (style.labeltype != LABEL_MANUAL)
3286 main_body = BeginningOfMainBody();
3288 /* gets paragraph main font */
3290 font1 = style.labelfont;
3294 char_line_count = depth;
3295 addNewlineAndDepth(file, depth);
3296 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
3297 file += "<INFORMALTABLE>";
3298 addNewlineAndDepth(file, ++depth);
3300 current_cell_number = -1;
3301 tmp = table->DocBookEndOfCell(file,current_cell_number, depth);
3303 /* parsing main loop */
3305 for (size_type i = 0; i < size(); ++i) {
3307 for (int i = 0; i < last; ++i) {
3310 if (table->IsContRow(current_cell_number+1)) {
3311 if (c == LYX_META_NEWLINE)
3312 current_cell_number++;
3317 // Fully instantiated font
3320 /* handle <emphasis> tag */
3321 if (font1.emph() != font2.emph() && i) {
3322 if (font2.emph() == LyXFont::ON) {
3323 file += "<emphasis>";
3325 } else if (emph_flag) {
3326 file += "</emphasis>";
3330 if (c == LYX_META_NEWLINE) {
3331 // we have only to control for emphasis open here!
3333 file += "</emphasis>";
3336 font1 = font2 = getFont(-1);
3337 current_cell_number++;
3338 if (table->CellHasContRow(current_cell_number) >= 0) {
3339 DocBookContTableRows(file, extra, desc_on, i+1,
3340 current_cell_number,
3343 // if this cell follow only ContRows till end don't
3344 // put the EndOfCell because it is put after the
3346 if (table->ShouldBeVeryLastCell(current_cell_number)) {
3347 current_cell_number--;
3350 tmp=table->DocBookEndOfCell(file, current_cell_number,
3355 } else if (c == LYX_META_INSET) {
3356 inset = GetInset(i);
3358 inset->DocBook(tmp_out);
3360 // This code needs some explanation:
3361 // Two insets are treated specially
3362 // label if it is the first element in a command paragraph
3364 // graphics inside tables or figure floats can't go on
3365 // title (the equivalente in latex for this case is caption
3366 // and title should come first
3369 if(desc_on != 3 || i != 0) {
3370 if(tmp_out[0] == '@') {
3372 extra += frontStrip(tmp_out, '@');
3374 file += frontStrip(tmp_out, '@');
3378 } else if (font2.latex() == LyXFont::ON) {
3379 // "TeX"-Mode on ==> SGML-Mode on.
3385 if (linuxDocConvertChar(c, sgml_string)
3386 && !style.free_spacing) {
3387 // in freespacing mode, spaces are
3388 // non-breaking characters
3393 file += "</term><listitem><para>";
3399 file += sgml_string;
3405 /* needed if there is an optional argument but no contents */
3407 if (main_body > 0 && main_body == size()) {
3411 if (main_body > 0 && main_body == last) {
3416 file += "</emphasis>";
3419 current_cell_number++;
3420 tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
3421 /* resets description flag correctly */
3424 /* <term> not closed... */
3428 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3429 file += "</INFORMALTABLE>";
3431 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
3436 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
3437 int & desc_on, LyXParagraph::size_type i,
3438 int current_cell_number, int &column)
3441 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
3442 int & desc_on, int i,
3443 int current_cell_number, int &column)
3450 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
3453 LyXFont font1,font2;
3457 size_type main_body;
3463 string emph="emphasis";
3464 bool emph_flag=false;
3465 int char_line_count=0;
3467 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), GetLayout());
3469 if (style.labeltype != LABEL_MANUAL)
3472 main_body = BeginningOfMainBody();
3474 /* gets paragraph main font */
3476 font1 = style.labelfont;
3481 cell = table->CellHasContRow(current_cell_number);
3482 current_cell_number++;
3484 // first find the right position
3487 for (; i < size() && current_cell_number < cell; ++i) {
3489 for (; i < last && (current_cell_number < cell); ++i) {
3492 if (c == LYX_META_NEWLINE)
3493 current_cell_number++;
3497 // I don't know how to handle this so I comment it
3498 // for the moment (Jug)
3499 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3500 // file += " \\\\\n";
3503 if ((c != ' ') && (c != LYX_META_NEWLINE)) {
3507 for (; i < size() && (c = GetChar(i)) != LYX_META_NEWLINE;
3510 for (; i < last && ((c = GetChar(i)) != LYX_META_NEWLINE);
3515 // Fully instantiated font
3518 /* handle <emphasis> tag */
3519 if (font1.emph() != font2.emph() && i) {
3520 if (font2.emph() == LyXFont::ON) {
3521 file += "<emphasis>";
3523 } else if (emph_flag) {
3524 file += "</emphasis>";
3528 if (c == LYX_META_INSET) {
3529 inset = GetInset(i);
3531 inset->DocBook(tmp_out);
3533 // This code needs some explanation:
3534 // Two insets are treated specially
3535 // label if it is the first element in a command paragraph
3537 // graphics inside tables or figure floats can't go on
3538 // title (the equivalente in latex for this case is caption
3539 // and title should come first
3542 if(desc_on != 3 || i != 0) {
3543 if(tmp_out[0]=='@') {
3545 extra += frontStrip(tmp_out, '@');
3547 file += frontStrip(tmp_out, '@');
3551 } else if (font2.latex() == LyXFont::ON) {
3552 // "TeX"-Mode on ==> SGML-Mode on.
3558 if (linuxDocConvertChar(c, sgml_string)
3559 && !style.free_spacing) {
3560 // in freespacing mode, spaces are
3561 // non-breaking characters
3566 file += "</term><listitem><para>";
3572 file += sgml_string;
3576 // we have only to control for emphasis open here!
3578 file += "</emphasis>";
3581 font1 = font2 = getFont(-1);
3582 cell = table->CellHasContRow(current_cell_number);
3584 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3588 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
3589 LyXParagraph::size_type const i, int & column, LyXFont const & font,
3590 LyXLayout const & style)
3592 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
3593 int const i, int & column, LyXFont const & font,
3594 LyXLayout const & style)
3597 if (column > tex_code_break_column
3599 && GetChar(i - 1) != ' '
3605 // In LaTeX mode, we don't want to
3606 // break lines since some commands
3608 && ! (font.latex() == LyXFont::ON)
3609 // same in FreeSpacing mode
3610 && !style.free_spacing
3611 // In typewriter mode, we want to avoid
3612 // ! . ? : at the end of a line
3613 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3614 && (GetChar(i-1) == '.'
3615 || GetChar(i-1) == '?'
3616 || GetChar(i-1) == ':'
3617 || GetChar(i-1) == '!'))) {
3618 if (tex_code_break_column == 0) {
3619 // in batchmode we need LaTeX to still
3620 // see it as a space not as an extra '\n'
3626 texrow.start(this, i+1);
3628 } else if (font.latex() == LyXFont::OFF) {
3629 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3639 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
3640 LyXFont & font, LyXFont & running_font,
3643 LyXLayout const & style,
3644 LyXParagraph::size_type & i, int &column, char const c)
3646 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
3647 LyXFont & font, LyXFont & running_font,
3650 LyXLayout const & style,
3651 int & i, int &column, char const c)
3654 // Two major modes: LaTeX or plain
3655 // Handle here those cases common to both modes
3656 // and then split to handle the two modes separately.
3658 case LYX_META_INSET: {
3659 Inset * inset = GetInset(i);
3661 int len = file.length();
3662 int tmp = inset->Latex(file, style.isCommand());
3667 column += file.length() - len;
3676 case LYX_META_NEWLINE:
3678 column += running_font.latexWriteEndChanges(file, basefont);
3681 basefont = getFont(-1);
3682 running_font = basefont;
3685 case LYX_META_HFILL:
3686 file += "\\hfill{}";
3691 // And now for the special cases within each mode
3692 // Are we in LaTeX mode?
3693 if (font.latex() == LyXFont::ON) {
3694 // at present we only have one option
3695 // but I'll leave it as a switch statement
3696 // so its simpler to extend. (ARRae)
3698 case LYX_META_PROTECTED_SEPARATOR:
3703 // make sure that we will not print
3704 // error generating chars to the tex
3705 // file. This test would not be needed
3706 // if it were done in the buffer
3714 // Plain mode (i.e. not LaTeX)
3716 case LYX_META_PROTECTED_SEPARATOR:
3721 file += "\\textbackslash{}";
3725 case '°': case '±': case '²': case '³':
3726 case '×': case '÷': case '¹': case 'ª':
3727 case 'º': case '¬': case 'µ':
3728 if (current_view->currentBuffer()->params.inputenc == "latin1") {
3729 file += "\\ensuremath{";
3738 case '|': case '<': case '>':
3739 // In T1 encoding, these characters exist
3740 if (lyxrc->fontenc == "T1") {
3742 //... but we should avoid ligatures
3743 if ((c == '>' || c == '<')
3749 && GetChar(i+1) == c){
3750 file += "\\textcompwordmark{}";
3755 // Typewriter font also has them
3756 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3760 // Otherwise, we use what LaTeX
3764 file += "\\textless{}";
3768 file += "\\textgreater{}";
3772 file += "\\textbar{}";
3778 case '-': // "--" in Typewriter mode -> "-{}-"
3784 && GetChar(i + 1) == '-'
3785 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3794 file += "\\char`\\\"{}";
3799 if (current_view->currentBuffer()->params.inputenc == "default") {
3800 file += "\\pounds{}";
3808 case '%': case '#': case '{':
3822 case '*': case '[': case ']':
3823 // avoid being mistaken for optional arguments
3831 /* blanks are printed before font switching */
3832 // Sure? I am not! (try nice-latex)
3833 // I am sure it's correct. LyX might be smarter
3834 // in the future, but for now, nothing wrong is
3839 /* idea for labels --- begin*/
3847 && font.family() != LyXFont::TYPEWRITER_FAMILY
3848 && GetChar(i + 1) == 'y'
3849 && GetChar(i + 2) == 'X') {
3861 && font.family() != LyXFont::TYPEWRITER_FAMILY
3862 && GetChar(i + 1) == 'e'
3863 && GetChar(i + 2) == 'X') {
3868 /* check for LaTeX2e */
3875 && font.family() != LyXFont::TYPEWRITER_FAMILY
3876 && GetChar(i + 1) == 'a'
3877 && GetChar(i + 2) == 'T'
3878 && GetChar(i + 3) == 'e'
3879 && GetChar(i + 4) == 'X'
3880 && GetChar(i + 5) == '2'
3881 && GetChar(i + 6) == 'e') {
3882 file += "\\LaTeXe{}";
3886 /* check for LaTeX */
3893 && font.family() != LyXFont::TYPEWRITER_FAMILY
3894 && GetChar(i + 1) == 'a'
3895 && GetChar(i + 2) == 'T'
3896 && GetChar(i + 3) == 'e'
3897 && GetChar(i + 4) == 'X') {
3898 file += "\\LaTeX{}";
3901 /* idea for labels --- end*/
3902 } else if (c != '\0') {
3912 bool LyXParagraph::RoffContTableRows(FILE * fp,
3913 LyXParagraph::size_type i,
3916 bool LyXParagraph::RoffContTableRows(FILE * fp, int i, int actcell)
3922 LyXFont font1 = LyXFont(LyXFont::ALL_INHERIT);
3928 string fname2 = TmpFileName(string(), "RAT2");
3930 int cell = table->CellHasContRow(actcell);
3933 // first find the right position
3936 for (; i < size() && actcell < cell; ++i) {
3938 for (; i < last && actcell < cell; ++i) {
3941 if (c == LYX_META_NEWLINE)
3946 if ((c != ' ') && (c != LYX_META_NEWLINE))
3949 for (; i < size() && (c = GetChar(i)) != LYX_META_NEWLINE;
3952 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE);
3955 font2 = GetFontSettings(i);
3956 if (font1.latex() != font2.latex()) {
3957 if (font2.latex() != LyXFont::OFF)
3962 case LYX_META_INSET:
3963 if ((inset = GetInset(i))) {
3964 if (!(fp2=fopen(fname2.c_str(),"w+"))) {
3965 WriteAlert(_("LYX_ERROR:"), _("Cannot open temporary file:"), fname2);
3968 inset->Latex(fp2,-1);
3981 case LYX_META_NEWLINE:
3983 case LYX_META_HFILL:
3985 case LYX_META_PROTECTED_SEPARATOR:
3988 fprintf(fp, "\\\\");
3992 fprintf(fp, "%c", c);
3994 lyxerr.debug() << "RoffAsciiTable: NULL char in structure." << endl;
3998 cell = table->CellHasContRow(actcell);
4003 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
4004 string & foot, TexRow & foot_texrow,
4007 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
4008 LyXParagraph * par = this;
4010 while (par && par->depth == depth) {
4012 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
4013 if (textclasslist.Style(GetCurrentTextClass(),
4014 par->layout).isEnvironment()
4015 || par->pextra_type != PEXTRA_NONE)
4017 par = par->TeXEnvironment(file, texrow,
4021 par = par->TeXOnePar(file, texrow,
4026 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
4032 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
4033 string & foot, TexRow & foot_texrow,
4036 bool eindent_open = false;
4037 bool foot_this_level = false;
4038 // flags when footnotetext should be appended to file.
4039 static bool minipage_open = false;
4040 static int minipage_open_depth = 0;
4041 char par_sep = current_view->currentBuffer()->params.paragraph_separation;
4043 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
4045 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
4047 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), layout);
4049 if (pextra_type == PEXTRA_INDENT) {
4050 if (!pextra_width.empty()) {
4051 file += "\\begin{LyXParagraphIndent}{"
4052 + pextra_width + "}\n";
4054 //float ib = atof(pextra_widthp.c_str())/100;
4055 // string can't handle floats at present (971109)
4056 // so I'll do a conversion by hand knowing that
4057 // the limits are 0.0 to 1.0. ARRae.
4058 file += "\\begin{LyXParagraphIndent}{";
4059 switch (pextra_widthp.length()) {
4065 file += pextra_widthp;
4069 file += pextra_widthp;
4071 file += "\\columnwidth}\n";
4074 eindent_open = true;
4076 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
4077 if (pextra_hfill && Previous() &&
4078 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
4079 file += "\\hfill{}\n";
4082 if (par_sep == LYX_PARSEP_INDENT) {
4083 file += "{\\setlength\\parindent{0pt}\n";
4086 file += "\\begin{minipage}";
4087 switch(pextra_alignment) {
4088 case MINIPAGE_ALIGN_TOP:
4091 case MINIPAGE_ALIGN_MIDDLE:
4094 case MINIPAGE_ALIGN_BOTTOM:
4098 if (!pextra_width.empty()) {
4100 file += pextra_width + "}\n";
4102 //float ib = atof(par->pextra_width.c_str())/100;
4103 // string can't handle floats at present
4104 // so I'll do a conversion by hand knowing that
4105 // the limits are 0.0 to 1.0. ARRae.
4107 switch (pextra_widthp.length()) {
4113 file += pextra_widthp;
4117 file += pextra_widthp;
4119 file += "\\columnwidth}\n";
4122 if (par_sep == LYX_PARSEP_INDENT) {
4123 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
4126 minipage_open = true;
4127 minipage_open_depth = depth;
4130 #ifdef WITH_WARNINGS
4131 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
4132 //I disabled it because it breaks when lists span on several
4135 if (style.isEnvironment()){
4136 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
4137 #ifdef FANCY_FOOTNOTE_CODE
4138 if (foot_count < 0) {
4139 // flag that footnote[mark][text] should be
4140 // used for any footnotes from now on
4142 foot_this_level = true;
4145 file += "\\begin{" + style.latexname() + "}{"
4146 + labelwidthstring + "}\n";
4147 } else if (style.labeltype == LABEL_BIBLIO) {
4149 file += "\\begin{" + style.latexname() + "}{"
4150 + bibitemWidthest() + "}\n";
4151 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
4152 #ifdef FANCY_FOOTNOTE_CODE
4153 if (foot_count < 0) {
4154 // flag that footnote[mark][text] should be
4155 // used for any footnotes from now on
4157 foot_this_level = true;
4160 file += "\\begin{" + style.latexname() + '}'
4161 + style.latexparam() + '\n';
4163 file += "\\begin{" + style.latexname() + '}'
4164 + style.latexparam() + '\n';
4167 LyXParagraph * par = this;
4169 par = par->TeXOnePar(file, texrow,
4170 foot, foot_texrow, foot_count);
4172 if (minipage_open && par && !style.isEnvironment() &&
4173 (par->pextra_type == PEXTRA_MINIPAGE) &&
4174 par->pextra_start_minipage) {
4175 file += "\\end{minipage}\n";
4177 if (par_sep == LYX_PARSEP_INDENT) {
4181 minipage_open = false;
4183 if (par && par->depth > depth) {
4184 if (textclasslist.Style(GetCurrentTextClass(),
4185 par->layout).isParagraph()
4187 && !suffixIs(file, "\n\n")) {
4188 // There should be at least one '\n' already
4189 // but we need there to be two for Standard
4190 // paragraphs that are depth-increment'ed to be
4191 // output correctly. However, tables can also be
4192 // paragraphs so don't adjust them. ARRae
4196 par = par->TeXDeeper(file, texrow,
4197 foot, foot_texrow, foot_count);
4199 if (par && par->layout == layout && par->depth == depth &&
4200 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
4201 if (par->pextra_hfill && par->Previous() &&
4202 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
4203 file += "\\hfill{}\n";
4206 if (par_sep == LYX_PARSEP_INDENT) {
4207 file += "{\\setlength\\parindent{0pt}\n";
4210 file += "\\begin{minipage}";
4211 switch(par->pextra_alignment) {
4212 case MINIPAGE_ALIGN_TOP:
4215 case MINIPAGE_ALIGN_MIDDLE:
4218 case MINIPAGE_ALIGN_BOTTOM:
4222 if (!par->pextra_width.empty()) {
4224 file += par->pextra_width;
4227 //float ib = atof(par->pextra_widthp.c_str())/100;
4228 // string can't handle floats at present
4229 // so I'll do a conversion by hand knowing that
4230 // the limits are 0.0 to 1.0. ARRae.
4232 switch (par->pextra_widthp.length()) {
4238 file += par->pextra_widthp;
4242 file += par->pextra_widthp;
4244 file += "\\columnwidth}\n";
4247 if (par_sep == LYX_PARSEP_INDENT) {
4248 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
4251 minipage_open = true;
4252 minipage_open_depth = par->depth;
4255 && par->layout == layout
4256 && par->depth == depth
4257 && par->pextra_type == pextra_type);
4259 if (style.isEnvironment()) {
4260 file += "\\end{" + style.latexname() + '}';
4261 // maybe this should go after the minipage closes?
4262 if (foot_this_level) {
4263 if (foot_count >= 1) {
4264 if (foot_count > 1) {
4265 file += "\\addtocounter{footnote}{-";
4266 file += tostr(foot_count - 1);
4270 texrow += foot_texrow;
4272 foot_texrow.reset();
4277 if (minipage_open && (minipage_open_depth == depth) &&
4278 (!par || par->pextra_start_minipage ||
4279 par->pextra_type != PEXTRA_MINIPAGE)) {
4280 file += "\\end{minipage}\n";
4282 if (par_sep == LYX_PARSEP_INDENT) {
4286 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
4287 file += "\\medskip\n\n";
4291 minipage_open = false;
4294 file += "\\end{LyXParagraphIndent}\n";
4297 if (!(par && (par->pextra_type==PEXTRA_MINIPAGE)
4298 && par->pextra_hfill)) {
4302 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
4303 return par; // ale970302
4307 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
4308 string & foot, TexRow & foot_texrow,
4311 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
4312 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
4313 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4314 "No footnote!" << endl;
4316 LyXParagraph * par = this;
4317 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
4318 previous->GetLayout());
4320 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
4321 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4322 "Float other than footnote in command"
4323 " with moving argument is illegal" << endl;
4326 if (footnotekind != LyXParagraph::FOOTNOTE
4327 && footnotekind != LyXParagraph::MARGIN
4329 && !suffixIs(file, '\n')) {
4330 // we need to ensure that real floats like tables and figures
4331 // have their \begin{} on a new line otherwise we can get
4332 // incorrect results when using the endfloat.sty package
4333 // especially if two floats follow one another. ARRae 981022
4334 // NOTE: if the file is length 0 it must have just been
4335 // written out so we assume it ended with a '\n'
4340 BufferParams * params = ¤t_view->currentBuffer()->params;
4341 bool footer_in_body = true;
4342 switch (footnotekind) {
4343 case LyXParagraph::FOOTNOTE:
4344 if (style.intitle) {
4345 file += "\\thanks{\n";
4346 footer_in_body = false;
4348 if (foot_count == -1) {
4349 // we're at depth 0 so we can use:
4350 file += "\\footnote{%\n";
4351 footer_in_body = false;
4353 file += "\\footnotemark{}%\n";
4355 // we only need this when there are
4356 // multiple footnotes
4357 foot += "\\stepcounter{footnote}";
4359 foot += "\\footnotetext{%\n";
4360 foot_texrow.start(this,0);
4361 foot_texrow.newline();
4366 case LyXParagraph::MARGIN:
4367 file += "\\marginpar{\n";
4369 case LyXParagraph::FIG:
4370 if (pextra_type == PEXTRA_FLOATFLT
4371 && (!pextra_width.empty()
4372 || !pextra_widthp.empty())) {
4374 if (!pextra_width.empty())
4375 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
4376 pextra_width.c_str());
4378 sprintf(bufr, "\\begin{floatingfigure}{%f\\textwidth}\n",
4379 atoi(pextra_widthp.c_str())/100.0);
4382 file += "\\begin{figure}";
4383 if (!params->float_placement.empty()) {
4385 file += params->float_placement;
4392 case LyXParagraph::TAB:
4393 file += "\\begin{table}";
4394 if (!params->float_placement.empty()) {
4396 file += params->float_placement;
4402 case LyXParagraph::WIDE_FIG:
4403 file += "\\begin{figure*}";
4404 if (!params->float_placement.empty()) {
4406 file += params->float_placement;
4412 case LyXParagraph::WIDE_TAB:
4413 file += "\\begin{table*}";
4414 if (!params->float_placement.empty()) {
4416 file += params->float_placement;
4422 case LyXParagraph::ALGORITHM:
4423 file += "\\begin{algorithm}\n";
4428 if (footnotekind != LyXParagraph::FOOTNOTE
4429 || !footer_in_body) {
4430 // Process text for all floats except footnotes in body
4432 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
4435 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4437 if (style.isEnvironment()
4438 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4439 // Allows the use of minipages within float environments.
4440 // Shouldn't be circular because we don't support
4441 // footnotes inside floats (yet). ARRae
4442 par = par->TeXEnvironment(file, texrow,
4446 par = par->TeXOnePar(file, texrow,
4451 if (par && !par->IsDummy() && par->depth > depth) {
4452 par = par->TeXDeeper(file, texrow,
4456 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4458 // process footnotes > depth 0 or in environments separately
4459 // NOTE: Currently don't support footnotes within footnotes
4460 // even though that is possible using the \footnotemark
4462 TexRow dummy_texrow;
4463 int dummy_count = 0;
4465 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
4468 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4470 if (style.isEnvironment()
4471 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4472 // Allows the use of minipages within float environments.
4473 // Shouldn't be circular because we don't support
4474 // footnotes inside floats (yet). ARRae
4475 par = par->TeXEnvironment(foot, foot_texrow,
4476 dummy, dummy_texrow,
4479 par = par->TeXOnePar(foot, foot_texrow,
4480 dummy, dummy_texrow,
4484 if (par && !par->IsDummy() && par->depth > depth) {
4485 par = par->TeXDeeper(foot, foot_texrow,
4486 dummy, dummy_texrow,
4489 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4491 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4492 "Footnote in a Footnote -- not supported"
4497 switch (footnotekind) {
4498 case LyXParagraph::FOOTNOTE:
4499 if (footer_in_body) {
4500 // This helps tell which of the multiple
4501 // footnotetexts an error was in.
4503 foot_texrow.newline();
4508 case LyXParagraph::MARGIN:
4511 case LyXParagraph::FIG:
4512 if (pextra_type == PEXTRA_FLOATFLT
4513 && (!pextra_width.empty()
4514 || !pextra_widthp.empty()))
4515 file += "\\end{floatingfigure}";
4517 file += "\\end{figure}";
4519 case LyXParagraph::TAB:
4520 file += "\\end{table}";
4522 case LyXParagraph::WIDE_FIG:
4523 file += "\\end{figure*}";
4525 case LyXParagraph::WIDE_TAB:
4526 file += "\\end{table*}";
4528 case LyXParagraph::ALGORITHM:
4529 file += "\\end{algorithm}";
4533 if (footnotekind != LyXParagraph::FOOTNOTE
4534 && footnotekind != LyXParagraph::MARGIN) {
4535 // we need to ensure that real floats like tables and figures
4536 // have their \end{} on a line of their own otherwise we can
4537 // get incorrect results when using the endfloat.sty package.
4542 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4547 void LyXParagraph::SetPExtraType(int type, char const * width,
4548 char const * widthp)
4551 pextra_width = width;
4552 pextra_widthp = widthp;
4554 if (textclasslist.Style(GetCurrentTextClass(),
4555 layout).isEnvironment()) {
4560 while (par && (par->layout == layout) && (par->depth == depth)) {
4562 par = par->Previous();
4564 par = par->FirstPhysicalPar();
4565 while (par && par->depth > depth) {
4566 par = par->Previous();
4568 par = par->FirstPhysicalPar();
4572 while (par && (par->layout == layout) && (par->depth == depth)) {
4573 par->pextra_type = type;
4574 par->pextra_width = width;
4575 par->pextra_widthp = widthp;
4576 par = par->NextAfterFootnote();
4577 if (par && (par->depth > depth))
4578 par->SetPExtraType(type,width,widthp);
4579 while (par && ((par->depth > depth) || par->IsDummy()))
4580 par = par->NextAfterFootnote();
4585 void LyXParagraph::UnsetPExtraType()
4587 if (pextra_type == PEXTRA_NONE)
4590 pextra_type = PEXTRA_NONE;
4591 pextra_width.clear();
4592 pextra_widthp.clear();
4594 if (textclasslist.Style(GetCurrentTextClass(),
4595 layout).isEnvironment()) {
4600 while (par && (par->layout == layout) && (par->depth == depth)) {
4602 par = par->Previous();
4604 par = par->FirstPhysicalPar();
4605 while (par && par->depth > depth) {
4606 par = par->Previous();
4608 par = par->FirstPhysicalPar();
4612 while (par && (par->layout == layout) && (par->depth == depth)) {
4613 par->pextra_type = PEXTRA_NONE;
4614 par->pextra_width.clear();
4615 par->pextra_widthp.clear();
4616 par = par->NextAfterFootnote();
4617 if (par && (par->depth > depth))
4618 par->UnsetPExtraType();
4619 while (par && ((par->depth > depth) || par->IsDummy()))
4620 par = par->NextAfterFootnote();