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->buffer()->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);
700 //text.erase(pos, 1);
702 // Shift rest of text
703 for (int i = pos; i < last - 1; i++) {
709 /* erase entries in the tables */
710 for(FontList::iterator it = fontlist.begin();
711 it != fontlist.end(); ++it) {
712 if (pos >= (*it).pos && pos <= (*it).pos_end) {
713 if ((*it).pos == (*it).pos_end) {
720 /* update all other entries */
721 for(FontList::iterator it = fontlist.begin();
722 it != fontlist.end(); ++it) {
725 if ((*it).pos_end >= pos)
729 /* update the inset table */
730 for(InsetList::iterator it = insetlist.begin();
731 it != insetlist.end(); ++it) {
736 /* erase entries in the tables */
738 FontTable * tmp = fonttable;
739 FontTable * prev = 0;
740 while (tmp && !found) {
741 if (pos >= tmp->pos && pos <= tmp->pos_end)
749 if (found && tmp->pos == tmp->pos_end) {
750 /* if it is a multi-character font entry, we just make
751 * it smaller (see update below), otherwise we should
754 prev->next = tmp->next;
756 fonttable = tmp->next;
761 /* update all other entries */
767 if (tmp->pos_end >= pos)
772 /* update the inset table */
773 InsetTable * tmpi = insettable;
781 lyxerr << "ERROR (LyXParagraph::Erase): "
782 "can't erase non-existant char." << endl;
788 /* pos is needed to specify the paragraph correctly. Remember the
789 * closed footnotes */
790 void LyXParagraph::Enlarge(int pos, int number)
792 /* > because last is the next unused position, and you can
793 * use it if you want */
795 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
796 NextAfterFootnote()->Enlarge(pos - last - 1, number);
798 lyxerr << "ERROR (LyXParagraph::Enlarge): "
799 "position does not exist." << endl;
803 if (size - last < number) {
804 size += number - size + last + STEP_SIZE_PAR;
805 char * tmp = new char[size];
806 for (int i = 0; i < last; ++i)
816 /* make the allocated memory fit to the needed size */
817 /* used to make a paragraph smaller */
818 void LyXParagraph::FitSize()
820 if (size - last > STEP_SIZE_PAR) {
821 size = last + STEP_SIZE_PAR;
822 char * tmp = new char[size];
823 for (int i = 0; i < last; ++i)
832 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
834 void LyXParagraph::InsertChar(int pos, char c)
838 /* > because last is the next unused position, and you can
839 * use it if you want */
842 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
843 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
846 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
847 "position does not exist." << endl;
850 text.insert(text.begin() + pos, c);
851 //text.insert(pos, c);
853 /* > because last is the next unused position, and you can
854 * use it if you want */
857 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
858 NextAfterFootnote()->InsertChar(pos - last - 1, c);
860 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
861 "position does not exist." << endl;
864 // Are we full? If so, enlarge.
866 size += STEP_SIZE_PAR;
867 char * tmp = new char[size];
868 for (int i = 0; i < last; i++)
874 // Shift rest of character
875 for (int i = last; i>pos; i--) {
876 text[i] = text[i - 1];
883 // update the font table
884 for(FontList::iterator it = fontlist.begin();
885 it != fontlist.end(); ++it) {
886 if ((*it).pos >= pos)
888 if ((*it).pos_end >= pos)
891 // update the inset table
892 for(InsetList::iterator it = insetlist.begin();
893 it != insetlist.end(); ++it) {
894 if ((*it).pos >= pos)
898 /* update the font table */
899 FontTable * tmp = fonttable;
903 if (tmp->pos_end >= pos)
908 /* update the inset table */
909 InsetTable * tmpi = insettable;
911 if (tmpi->pos >= pos)
919 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
922 void LyXParagraph::InsertInset(int pos, Inset * inset)
925 /* > because last is the next unused position, and you can
926 * use it if you want */
930 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
932 ->InsertInset(pos - text.size() - 1, inset);
934 lyxerr << "ERROR (LyXParagraph::InsertInset): "
935 "position does not exist: " << pos << endl;
941 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
943 ->InsertInset(pos - last - 1, inset);
945 lyxerr << "ERROR (LyXParagraph::InsertInset): "
946 "position does not exist: " << pos << endl;
950 if (text[pos] != LYX_META_INSET) {
951 lyxerr << "ERROR (LyXParagraph::InsertInset): "
952 "there is no LYX_META_INSET" << endl;
961 insetlist.push_back(tmp);
966 /* add a new entry in the inset table */
967 InsetTable * tmpi = new InsetTable;
970 tmpi->next = insettable;
977 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
979 Inset * LyXParagraph::GetInset(int pos)
985 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
986 return NextAfterFootnote()
987 ->GetInset(pos - text.size() - 1);
989 lyxerr << "ERROR (LyXParagraph::GetInset): "
990 "position does not exist: "
998 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
999 return NextAfterFootnote()->GetInset(pos - last - 1);
1001 lyxerr << "ERROR (LyXParagraph::GetInset): "
1002 "position does not exist: "
1009 /* find the inset */
1010 for(InsetList::iterator it = insetlist.begin();
1011 it != insetlist.end(); ++it) {
1012 if ((*it).pos == pos) {
1016 lyxerr << "ERROR (LyXParagraph::GetInset): "
1017 "Inset does not exist: " << pos << endl;
1018 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
1019 // Did this commenting out introduce a bug? So far I have not
1020 // seen any, please enlighten me. (Lgb)
1021 // My guess is that since the inset does not exist, we might
1022 // as well replace it with a space to prevent crashes. (Asger)
1025 /* find the inset */
1026 InsetTable * tmpi = insettable;
1028 while (tmpi && tmpi->pos != pos)
1034 lyxerr << "ERROR (LyXParagraph::GetInset): "
1035 "Inset does not exist: " << pos << endl;
1036 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
1037 // Did this commenting out introduce a bug? So far I have not
1038 // seen any, please enlighten me. (Lgb)
1039 // My guess is that since the inset does not exist, we might
1040 // as well replace it with a space to prevent crashes. (Asger)
1047 // Gets uninstantiated font setting at position.
1048 // Optimized after profiling. (Asger)
1050 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos)
1052 LyXFont LyXParagraph::GetFontSettings(int pos)
1058 for(FontList::iterator it = fontlist.begin();
1059 it != fontlist.end(); ++it) {
1060 if (pos >= (*it).pos && pos <= (*it).pos_end)
1064 FontTable * tmp = fonttable;
1066 if (pos >= tmp->pos && pos <= tmp->pos_end)
1072 /* > because last is the next unused position, and you can
1073 * use it if you want */
1074 else if (pos > size()) {
1076 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1077 return NextAfterFootnote()
1078 ->GetFontSettings(pos - text.size() - 1);
1080 // Why is it an error to ask for the font of a
1081 // position that does not exist? Would it be
1082 // enough for this to be anable on debug?
1083 // We want strict error checking, but it's ok to only
1084 // have it when debugging. (Asger)
1085 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
1086 "position does not exist. "
1087 << pos << " (" << static_cast<int>(pos)
1091 return GetFontSettings(pos - 1);
1096 for(FontList::iterator it = fontlist.begin();
1097 it != fontlist.end(); ++it) {
1098 if (pos >= (*it).pos && pos <= (*it).pos_end)
1102 FontTable * tmp = fonttable;
1104 if (pos >= tmp->pos && pos <= tmp->pos_end)
1110 /* > because last is the next unused position, and you can
1111 * use it if you want */
1112 else if (pos > last) {
1114 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1115 return NextAfterFootnote()
1116 ->GetFontSettings(pos - last - 1);
1118 // Why is it an error to ask for the font of a
1119 // position that does not exist? Would it be
1120 // enough for this to be anable on debug?
1121 // We want strict error checking, but it's ok to only
1122 // have it when debugging. (Asger)
1123 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
1124 "position does not exist. " << pos << endl;
1127 return GetFontSettings(pos - 1);
1130 return LyXFont(LyXFont::ALL_INHERIT);
1134 // Gets the fully instantiated font at a given position in a paragraph
1135 // This is basically the same function as LyXText::GetFont() in text2.C.
1136 // The difference is that this one is used for generating the LaTeX file,
1137 // and thus cosmetic "improvements" are disallowed: This has to deliver
1138 // the true picture of the buffer. (Asger)
1139 // If position is -1, we get the layout font of the paragraph.
1140 // If position is -2, we get the font of the manual label of the paragraph.
1142 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos)
1144 LyXFont LyXParagraph::getFont(int pos)
1148 LyXLayout const & layout = textclasslist.Style(GetCurrentTextClass(),
1151 LyXParagraph::size_type main_body = 0;
1155 if (layout.labeltype == LABEL_MANUAL)
1156 main_body = BeginningOfMainBody();
1160 if (pos < main_body)
1161 layoutfont = layout.labelfont;
1163 layoutfont = layout.font;
1164 tmpfont = GetFontSettings(pos);
1165 tmpfont.realize(layoutfont);
1167 // process layoutfont for pos == -1 and labelfont for pos < -1
1169 tmpfont = layout.font;
1171 tmpfont = layout.labelfont;
1174 // check for environment font information
1175 char par_depth = GetDepth();
1176 LyXParagraph * par = this;
1177 while (par && par_depth && !tmpfont.resolved()) {
1178 par = par->DepthHook(par_depth - 1);
1180 tmpfont.realize(textclasslist.
1181 Style(GetCurrentTextClass(),
1182 par->GetLayout()).font);
1183 par_depth = par->GetDepth();
1187 tmpfont.realize(textclasslist.TextClass(GetCurrentTextClass()).defaultfont());
1192 /// Returns the height of the highest font in range
1194 LyXFont::FONT_SIZE LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos, LyXParagraph::size_type endpos) const
1196 LyXFont::FONT_SIZE LyXParagraph::HighestFontInRange(int startpos, int endpos) const
1199 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
1201 for(FontList::const_iterator cit = fontlist.begin();
1202 cit != fontlist.end(); ++cit) {
1203 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
1204 LyXFont::FONT_SIZE size = (*cit).font.size();
1205 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
1210 FontTable * tmp = fonttable;
1212 if (startpos <= tmp->pos_end && endpos >= tmp->pos) {
1213 LyXFont::FONT_SIZE size = tmp->font.size();
1214 if (size > maxsize && size<=LyXFont::SIZE_HUGER)
1225 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
1227 char LyXParagraph::GetChar(int pos)
1230 #ifdef DEVEL_VERSION
1231 /* a workaround to 'fix' some bugs in text-class */
1233 // This function is important. It should not work around bugs.
1234 // Let's find the bugs instead and fix them. (Asger)
1235 lyxerr << "FATAL ERROR (LyXParagraph::GetChar):"
1236 " bad position " << pos << endl;
1245 /* > because last is the next unused position, and you can
1246 * use it if you want */
1247 else if (pos > size()) {
1248 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1249 return NextAfterFootnote()
1250 ->GetChar(pos - text.size() - 1);
1252 lyxerr << "ERROR (LyXParagraph::GetChar): "
1253 "position does not exist."
1254 << pos << " (" << static_cast<int>(pos)
1262 /* > because last is the next unused position, and you can
1263 * use it if you want */
1264 else if (pos > last) {
1265 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1266 return NextAfterFootnote()->GetChar(pos - last - 1);
1268 lyxerr << "ERROR (LyXParagraph::GetChar): "
1269 "position does not exist." << pos << endl;
1273 /* we should have a footnote environment */
1274 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
1275 // Notice that LyX does request the
1276 // last char from time to time. (Asger)
1277 //lyxerr << "ERROR (LyXParagraph::GetChar): "
1278 // "expected footnote." << endl;
1281 switch (next->footnotekind) {
1282 case LyXParagraph::FOOTNOTE:
1283 return LYX_META_FOOTNOTE;
1284 case LyXParagraph::MARGIN:
1285 return LYX_META_MARGIN;
1286 case LyXParagraph::FIG:
1287 case LyXParagraph::WIDE_FIG:
1288 return LYX_META_FIG;
1289 case LyXParagraph::TAB:
1290 case LyXParagraph::WIDE_TAB:
1291 return LYX_META_TAB;
1292 case LyXParagraph::ALGORITHM:
1293 return LYX_META_ALGORITHM;
1295 return '\0'; // to shut up gcc
1301 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos)
1303 string LyXParagraph::GetWord(int & lastpos)
1306 //Added 98/9/21 by REH
1307 // return an string of the current word, and the end of the word
1310 // the current word is defined as starting at the first character from
1311 // the immediate left of lastpospos which meets the definition of IsLetter(),
1312 // continuing to the last character to the right of this meeting
1316 // i just left this in from GetChar()
1318 #ifdef DEVEL_VERSION
1319 /* a workaround to 'fix' some bugs in text-class */
1321 // This function is important. It should not work around bugs.
1322 // Let's find the bugs instead and fix them. (Asger)
1323 lyxerr << "FATAL ERROR (LyXParagraph::GetWord):"
1324 " bad position " << lastpos << endl;
1334 //i think the devcode aborts before this, but why not be
1336 if (lastpos < 0) lastpos=0;
1339 // move back until we have a letter
1341 //there's no real reason to have firstpos & lastpos as
1342 //separate variables as this is written, but maybe someon
1343 // will want to return firstpos in the future.
1345 //since someone might have typed a punctuation first
1346 int firstpos = lastpos;
1348 while ((firstpos >=0) && !IsLetter(firstpos))
1351 // now find the beginning by looking for a nonletter
1353 while ((firstpos>=0) && IsLetter(firstpos))
1356 // the above is now pointing to the preceeding non-letter
1360 // so copy characters into theword until we get a nonletter
1361 // note that this can easily exceed lastpos, wich means
1362 // that if used in the middle of a word, the whole word
1365 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1373 LyXParagraph::size_type LyXParagraph::Last()
1375 int LyXParagraph::Last()
1379 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1380 return text.size() + NextAfterFootnote()->Last() + 1;
1381 /* the 1 is the symbol
1386 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1387 return last + NextAfterFootnote()->Last() + 1;
1388 /* the 1 is the symbol
1397 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
1399 LyXParagraph * LyXParagraph::ParFromPos(int pos)
1403 /* > because last is the next unused position, and you can
1404 * use it if you want */
1407 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1408 return NextAfterFootnote()
1409 ->ParFromPos(pos - text.size() - 1);
1411 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1412 "position does not exist." << endl;
1416 /* > because last is the next unused position, and you can
1417 * use it if you want */
1420 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1421 return NextAfterFootnote()->ParFromPos(pos - last - 1);
1423 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1424 "position does not exist." << endl;
1434 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos)
1436 int LyXParagraph::PositionInParFromPos(int pos)
1439 /* > because last is the next unused position, and you can
1440 * use it if you want */
1444 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1445 return NextAfterFootnote()
1446 ->PositionInParFromPos(pos - text.size() - 1);
1449 "ERROR (LyXParagraph::PositionInParFromPos): "
1450 "position does not exist." << endl;
1456 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1457 return NextAfterFootnote()
1458 ->PositionInParFromPos(pos - last - 1);
1461 "ERROR (LyXParagraph::PositionInParFromPos): "
1462 "position does not exist." << endl;
1472 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1473 LyXFont const & font)
1475 void LyXParagraph::SetFont(int pos, LyXFont const & font)
1478 /* > because last is the next unused position, and you can
1479 * use it if you want */
1482 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1483 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1486 lyxerr << "ERROR (LyXParagraph::SetFont): "
1487 "position does not exist." << endl;
1493 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1494 NextAfterFootnote()->SetFont(pos - last - 1, font);
1496 lyxerr << "ERROR (LyXParagraph::SetFont): "
1497 "position does not exist." << endl;
1502 LyXFont patternfont(LyXFont::ALL_INHERIT);
1504 // First, reduce font against layout/label font
1505 // Update: The SetCharFont() routine in text2.C already reduces font, so
1506 // we don't need to do that here. (Asger)
1507 // No need to simplify this because it will disappear in a new kernel. (Asger)
1509 // Next search font table
1510 for(FontList::iterator it = fontlist.begin();
1511 it != fontlist.end(); ++it) {
1512 if (pos >= (*it).pos && pos <= (*it).pos_end) {
1514 // we found a font entry. maybe we have to
1515 // split it and create a new one
1517 if ((*it).pos != (*it).pos_end) {
1518 // more than one character
1519 if (pos == (*it).pos) {
1520 // maybe we could enlarge
1521 // the left fonttable
1522 for(FontList::iterator fit = fontlist.begin();
1523 fit != fontlist.end(); ++fit) {
1524 if (pos - 1 >= (*fit).pos
1525 && pos - 1 <= (*fit).pos_end
1526 && (*fit).font == font) {
1534 // Add a new entry in the
1535 // fonttable for the position
1538 tmp.pos_end = (*it).pos_end;
1539 tmp.font = (*it).font;
1540 (*it).pos_end = pos;
1541 fontlist.push_back(tmp);
1542 } else if (pos == (*it).pos_end) {
1543 // Add a new entry in the
1544 // fonttable for the position
1546 tmp.pos = (*it).pos;
1547 tmp.pos_end = (*it).pos_end - 1;
1548 tmp.font = (*it).font;
1549 (*it).pos = (*it).pos_end;
1550 fontlist.push_back(tmp);
1552 // Add a new entry in the
1553 // fonttable for the position
1555 tmp.pos = (*it).pos;
1556 tmp.pos_end = pos - 1;
1557 tmp.font = (*it).font;
1558 fontlist.push_back(tmp);
1561 tmp.pos_end = (*it).pos_end;
1562 tmp.font = (*it).font;
1563 fontlist.push_back(tmp);
1566 (*it).pos_end = pos;
1574 // if we did not find a font entry, but if the font at hand
1575 // is the same as default, we just forget it
1576 if (font == patternfont) return;
1578 // ok, we did not find a font entry. But maybe there is exactly
1579 // the needed font entry one position left
1580 for(FontList::iterator it = fontlist.begin();
1581 it != fontlist.end(); ++it) {
1582 if (pos - 1 >= (*it).pos && pos - 1 <= (*it).pos_end
1583 && (*it).font == font) {
1588 // Add a new entry in the
1589 // fonttable for the position
1593 tmp.font = patternfont;
1594 fontlist.push_back(tmp);
1596 // Next search font table
1600 FontTable * tmp = fonttable;
1601 while (tmp && !found) {
1602 if (pos >= tmp->pos && pos <= tmp->pos_end)
1609 /* if we did not find a font entry, but if the font at hand
1610 * is the same as default, we just forget it */
1611 if (font == patternfont)
1614 /* ok, we did not find a font entry. But maybe there is exactly
1615 * the needed font entry one position left */
1618 while (tmp2 && !found) {
1619 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1625 /* ok there is one. maybe it is exactly the needed font */
1626 if (tmp2->font == font) {
1627 /* put the position under the font */
1632 /* Add a new entry in the
1633 * fonttable for the position */
1634 tmp = new FontTable;
1637 tmp->font = patternfont;
1638 tmp->next = fonttable;
1641 /* we found a font entry. maybe we have to split it and create
1644 if (tmp->pos != tmp->pos_end) { /* more than one character */
1646 if (pos == tmp->pos) {
1647 /* maybe we could enlarge the left fonttable */
1651 while (tmp2 && !found) {
1652 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1658 /* Is there is one, and is it exactly the needed font? */
1659 if (found && tmp2->font == font) {
1660 /* put the position under the font */
1666 /* Add a new entry in the
1667 * fonttable for the position */
1668 tmp2 = new FontTable;
1669 tmp2->pos = pos + 1;
1670 tmp2->pos_end = tmp->pos_end;
1671 tmp2->font = tmp->font;
1673 tmp2->next = fonttable;
1676 else if (pos == tmp->pos_end) {
1677 /* Add a new entry in the
1678 * fonttable for the position */
1679 tmp2 = new FontTable;
1680 tmp2->pos = tmp->pos;
1681 tmp2->pos_end = tmp->pos_end - 1;
1682 tmp2->font = tmp->font;
1683 tmp->pos = tmp->pos_end;
1684 tmp2->next = fonttable;
1688 /* Add a new entry in the
1689 * fonttable for the position */
1690 tmp2 = new FontTable;
1691 tmp2->pos = tmp->pos;
1692 tmp2->pos_end = pos - 1;
1693 tmp2->font = tmp->font;
1694 tmp2->next = fonttable;
1697 tmp2 = new FontTable;
1698 tmp2->pos = pos + 1;
1699 tmp2->pos_end = tmp->pos_end;
1700 tmp2->font = tmp->font;
1701 tmp2->next = fonttable;
1714 /* this function is able to hide closed footnotes */
1715 LyXParagraph * LyXParagraph::Next()
1717 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1718 LyXParagraph * tmp = next;
1720 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1722 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1723 return tmp->Next(); /* there can be more than one
1724 footnote in a logical
1727 return next; /* this should never happen! */
1734 LyXParagraph * LyXParagraph::NextAfterFootnote()
1736 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1737 LyXParagraph * tmp = next;
1738 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1740 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1741 return tmp; /* there can be more than one footnote
1742 in a logical paragraph */
1744 return next; /* this should never happen! */
1751 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1754 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1756 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1757 tmp = tmp->previous;
1758 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1759 return tmp; /* there can be more than one footnote
1760 in a logical paragraph */
1762 return previous; /* this should never happen! */
1769 LyXParagraph * LyXParagraph::LastPhysicalPar()
1771 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1774 LyXParagraph * tmp = this;
1775 while (tmp->next && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1776 tmp = tmp->NextAfterFootnote();
1783 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1787 LyXParagraph * tmppar = this;
1789 while (tmppar && (tmppar->IsDummy()
1790 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1791 tmppar = tmppar->previous;
1794 return this; /* this should never happen! */
1800 /* this function is able to hide closed footnotes */
1801 LyXParagraph * LyXParagraph::Previous()
1803 LyXParagraph * tmp = previous;
1808 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1809 tmp = tmp->previous;
1811 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1812 tmp = tmp->previous;
1813 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1814 return tmp->next->Previous();
1824 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1827 void LyXParagraph::BreakParagraph(int pos, int flag)
1831 size_type i, pos_end, pos_first;
1833 int i, pos_end, pos_first;
1835 /* create a new paragraph */
1836 LyXParagraph * par = ParFromPos(pos);
1837 LyXParagraph * firstpar = FirstPhysicalPar();
1839 LyXParagraph * tmp = new LyXParagraph(par);
1841 tmp->footnoteflag = footnoteflag;
1842 tmp->footnotekind = footnotekind;
1844 /* this is an idea for a more userfriendly layout handling, I will
1845 * see what the users say */
1847 /* layout stays the same with latex-environments */
1849 tmp->SetOnlyLayout(firstpar->layout);
1850 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1853 if (Last() > pos || !Last() || flag == 2) {
1854 tmp->SetOnlyLayout(firstpar->layout);
1855 tmp->align = firstpar->align;
1856 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1858 tmp->line_bottom = firstpar->line_bottom;
1859 firstpar->line_bottom = false;
1860 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1861 firstpar->pagebreak_bottom = false;
1862 tmp->added_space_bottom = firstpar->added_space_bottom;
1863 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1865 tmp->depth = firstpar->depth;
1866 tmp->noindent = firstpar->noindent;
1868 /* copy everything behind the break-position
1869 to the new paragraph
1872 while (ParFromPos(pos_first) != par)
1876 pos_end = pos_first + par->text.size() - 1;
1877 tmp->text.reserve(pos_end - pos);
1879 pos_end = pos_first + par->last - 1;
1880 /* make sure there is enough memory for the now larger
1881 paragraph. This is not neccessary, because
1882 InsertFromMinibuffer will enlarge the memory (it uses
1883 InsertChar of course). But doing it by hand
1884 is MUCH faster! (only one time, not thousend times!!) */
1885 tmp->Enlarge(0, pos_end - pos);
1887 for (i = pos; i <= pos_end; i++) {
1888 par->CutIntoMinibuffer(i - pos_first);
1889 tmp->InsertFromMinibuffer(i - pos);
1892 for (i = pos_end; i >= pos; i--)
1893 par->Erase(i - pos_first);
1895 par->text.resize(par->text.size());
1897 /* free memory of the now shorter paragraph*/
1902 /* just an idea of me */
1904 tmp->line_top = firstpar->line_top;
1905 tmp->pagebreak_top = firstpar->pagebreak_top;
1906 tmp->added_space_top = firstpar->added_space_top;
1907 tmp->bibkey = firstpar->bibkey;
1909 /* layout stays the same with latex-environments */
1911 firstpar->SetOnlyLayout(tmp->layout);
1912 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1913 firstpar->depth = tmp->depth;
1919 void LyXParagraph::MakeSameLayout(LyXParagraph * par)
1921 par = par->FirstPhysicalPar();
1922 footnoteflag = par->footnoteflag;
1923 footnotekind = par->footnotekind;
1925 layout = par->layout;
1926 align = par-> align;
1927 SetLabelWidthString(par->labelwidthstring);
1929 line_bottom = par->line_bottom;
1930 pagebreak_bottom = par->pagebreak_bottom;
1931 added_space_bottom = par->added_space_bottom;
1933 line_top = par->line_top;
1934 pagebreak_top = par->pagebreak_top;
1935 added_space_top = par->added_space_top;
1937 pextra_type = par->pextra_type;
1938 pextra_width = par->pextra_width;
1939 pextra_widthp = par->pextra_widthp;
1940 pextra_alignment = par->pextra_alignment;
1941 pextra_hfill = par->pextra_hfill;
1942 pextra_start_minipage = par->pextra_start_minipage;
1944 noindent = par->noindent;
1949 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1951 LyXParagraph * tmppar = this;
1954 && tmppar->previous->footnoteflag ==
1955 LyXParagraph::CLOSED_FOOTNOTE)
1956 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1957 tmppar = tmppar->previous;
1960 return this; /* this should never happen! */
1966 LyXParagraph * LyXParagraph::Clone()
1968 /* create a new paragraph */
1969 LyXParagraph * result = new LyXParagraph;
1971 result->MakeSameLayout(this);
1973 /* this is because of the dummy layout of the paragraphs that
1975 result->layout = layout;
1977 /* table stuff -- begin*/
1979 result->table = table->Clone();
1982 /* table stuff -- end*/
1985 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1988 /* copy everything behind the break-position to the new paragraph */
1991 result->text.reserve(size());
1992 for (size_type i = 0; i < size(); i++) {
1993 CopyIntoMinibuffer(i);
1994 result->InsertFromMinibuffer(i);
1997 /* make shure there is enough memory for the now larger paragraph.
1998 * This is not neccessary, because InsertFromMinibuffer will enlarge
1999 * the memory (it uses InsertChar of course). But doing it by hand
2000 * is MUCH faster! (only one time, not thousend times!!) */
2001 result->Enlarge(0, last+2);
2002 for (int i = 0; i < last; i++) {
2003 CopyIntoMinibuffer(i);
2004 result->InsertFromMinibuffer(i);
2011 bool LyXParagraph::HasSameLayout(LyXParagraph * par)
2013 par = par->FirstPhysicalPar();
2016 par->footnoteflag == footnoteflag &&
2017 par->footnotekind == footnotekind &&
2019 par->layout == layout &&
2021 par->align == align &&
2023 par->line_bottom == line_bottom &&
2024 par->pagebreak_bottom == pagebreak_bottom &&
2025 par->added_space_bottom == added_space_bottom &&
2027 par->line_top == line_top &&
2028 par->pagebreak_top == pagebreak_top &&
2029 par->added_space_top == added_space_top &&
2031 par->pextra_type == pextra_type &&
2032 par->pextra_width == pextra_width &&
2033 par->pextra_widthp == pextra_widthp &&
2034 par->pextra_alignment == pextra_alignment &&
2035 par->pextra_hfill == pextra_hfill &&
2036 par->pextra_start_minipage == pextra_start_minipage &&
2038 par->table == table && // what means: NO TABLE AT ALL
2040 par->noindent == noindent &&
2041 par->depth == depth);
2045 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
2047 void LyXParagraph::BreakParagraphConservative(int pos)
2051 size_type i, pos_end, pos_first;
2053 int i, pos_end, pos_first;
2056 /* create a new paragraph */
2057 LyXParagraph * par = ParFromPos(pos);
2059 LyXParagraph * tmp = new LyXParagraph(par);
2061 tmp->MakeSameLayout(par);
2064 /* copy everything behind the break-position to the new
2067 while (ParFromPos(pos_first) != par)
2070 pos_end = pos_first + par->text.size() - 1;
2072 pos_end = pos_first + par->last - 1;
2074 /* make shure there is enough memory for the now larger
2075 paragraph. This is not neccessary, because
2076 InsertFromMinibuffer will enlarge the memory (it uses
2077 InsertChar of course). But doing it by hand
2078 is MUCH faster! (only one time, not thousend times!!) */
2080 tmp->text.reserve(pos_end - pos);
2082 tmp->Enlarge(0, pos_end - pos);
2084 for (i = pos; i <= pos_end; i++) {
2086 par->CutIntoMinibuffer(i - pos_first);
2087 tmp->InsertFromMinibuffer(i - pos);
2089 for (i = pos_end; i >= pos; i--)
2090 par->Erase(i - pos_first);
2092 par->text.resize(par->text.size());
2094 /* free memory of the now shorter paragraph*/
2101 /* be carefull, this does not make any check at all */
2102 void LyXParagraph::PasteParagraph()
2104 /* copy the next paragraph to this one */
2105 LyXParagraph * the_next = Next();
2107 LyXParagraph * firstpar = FirstPhysicalPar();
2109 /* first the DTP-stuff */
2110 firstpar->line_bottom = the_next->line_bottom;
2111 firstpar->added_space_bottom = the_next->added_space_bottom;
2112 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
2115 size_type pos_end = the_next->text.size() - 1;
2116 size_type pos_insert = Last();
2119 int pos_end = the_next->last - 1;
2120 int pos_insert = Last();
2121 /* enlarge the paragraph. This is faster than enlarge it
2122 * every 10th insertion. */
2124 Enlarge(pos_insert, pos_end);
2128 /* ok, now copy the paragraph */
2129 for (i = 0; i <= pos_end; i++) {
2130 the_next->CutIntoMinibuffer(i);
2131 InsertFromMinibuffer(pos_insert + i);
2134 /* delete the next paragraph */
2139 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
2141 void LyXParagraph::OpenFootnote(int pos)
2144 LyXParagraph * par = ParFromPos(pos);
2146 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2147 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
2153 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
2155 void LyXParagraph::CloseFootnote(int pos)
2158 LyXParagraph * par = ParFromPos(pos);
2160 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
2161 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
2167 LyXTextClass::LayoutList::size_type LyXParagraph::GetLayout()
2169 return FirstPhysicalPar()->layout;
2173 char LyXParagraph::GetDepth()
2175 return FirstPhysicalPar()->depth;
2179 char LyXParagraph::GetAlign()
2181 return FirstPhysicalPar()->align;
2185 string LyXParagraph::GetLabestring()
2187 return FirstPhysicalPar()->labelstring;
2191 int LyXParagraph::GetFirstCounter(int i)
2193 return FirstPhysicalPar()->counter[i];
2197 /* the next two functions are for the manual labels */
2198 string LyXParagraph::GetLabelWidthString()
2200 if (!FirstPhysicalPar()->labelwidthstring.empty())
2201 return FirstPhysicalPar()->labelwidthstring;
2203 return _("Senseless with this layout!");
2207 void LyXParagraph::SetLabelWidthString(string const & s)
2209 LyXParagraph * par = FirstPhysicalPar();
2211 par->labelwidthstring = s;
2215 void LyXParagraph::SetOnlyLayout(LyXTextClass::LayoutList::size_type new_layout)
2217 LyXParagraph * par = FirstPhysicalPar();
2218 LyXParagraph * ppar = 0;
2219 LyXParagraph * npar = 0;
2221 par->layout = new_layout;
2222 /* table stuff -- begin*/
2225 /* table stuff -- end*/
2226 if (par->pextra_type == PEXTRA_NONE) {
2227 if (par->Previous()) {
2228 ppar = par->Previous()->FirstPhysicalPar();
2231 && (ppar->depth > par->depth))
2232 ppar = ppar->Previous()->FirstPhysicalPar();
2235 npar = par->Next()->NextAfterFootnote();
2238 && (npar->depth > par->depth))
2239 npar = npar->Next()->NextAfterFootnote();
2241 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
2243 p1 = ppar->pextra_width,
2244 p2 = ppar->pextra_widthp;
2245 ppar->SetPExtraType(ppar->pextra_type,
2246 p1.c_str(),p2.c_str());
2248 if ((par->pextra_type == PEXTRA_NONE) &&
2249 npar && (npar->pextra_type != PEXTRA_NONE)) {
2251 p1 = npar->pextra_width,
2252 p2 = npar->pextra_widthp;
2253 npar->SetPExtraType(npar->pextra_type,
2254 p1.c_str(),p2.c_str());
2260 void LyXParagraph::SetLayout(LyXTextClass::LayoutList::size_type new_layout)
2263 * par = FirstPhysicalPar(),
2267 par->layout = new_layout;
2268 par->labelwidthstring.clear();
2269 par->align = LYX_ALIGN_LAYOUT;
2270 par->added_space_top = VSpace(VSpace::NONE);
2271 par->added_space_bottom = VSpace(VSpace::NONE);
2272 /* table stuff -- begin*/
2275 /* table stuff -- end*/
2276 if (par->pextra_type == PEXTRA_NONE) {
2277 if (par->Previous()) {
2278 ppar = par->Previous()->FirstPhysicalPar();
2281 && (ppar->depth > par->depth))
2282 ppar = ppar->Previous()->FirstPhysicalPar();
2285 npar = par->Next()->NextAfterFootnote();
2288 && (npar->depth > par->depth))
2289 npar = npar->Next()->NextAfterFootnote();
2291 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
2293 p1 = ppar->pextra_width,
2294 p2 = ppar->pextra_widthp;
2295 ppar->SetPExtraType(ppar->pextra_type,
2296 p1.c_str(),p2.c_str());
2298 if ((par->pextra_type == PEXTRA_NONE) &&
2299 npar && (npar->pextra_type != PEXTRA_NONE)) {
2301 p1 = npar->pextra_width,
2302 p2 = npar->pextra_widthp;
2303 npar->SetPExtraType(npar->pextra_type,
2304 p1.c_str(),p2.c_str());
2310 /* if the layout of a paragraph contains a manual label, the beginning of the
2311 * main body is the beginning of the second word. This is what the par-
2312 * function returns. If the layout does not contain a label, the main
2313 * body always starts with position 0. This differentiation is necessary,
2314 * because there cannot be a newline or a blank <= the beginning of the
2315 * main body in TeX. */
2317 int LyXParagraph::BeginningOfMainBody()
2319 if (FirstPhysicalPar() != this)
2323 // Unroll the first two cycles of the loop
2324 // and remember the previous character to remove unnecessary GetChar() calls
2328 && GetChar(i) != LYX_META_NEWLINE) {
2330 char previous_char, temp;
2332 && (previous_char = GetChar(i)) != LYX_META_NEWLINE) {
2333 // Yes, this ^ is supposed to be "=" not "=="
2336 && previous_char != ' '
2337 && (temp = GetChar(i)) != LYX_META_NEWLINE) {
2339 previous_char = temp;
2344 if (i == 0 && i == size() &&
2345 !(footnoteflag==LyXParagraph::NO_FOOTNOTE
2346 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
2347 i++; /* the cursor should not jump
2348 * to the main body if there
2353 && GetChar(i) != LYX_META_NEWLINE) {
2355 char previous_char, temp;
2357 && (previous_char = GetChar(i)) != LYX_META_NEWLINE) {
2358 // Yes, this ^ is supposed to be "=" not "=="
2361 && previous_char != ' '
2362 && (temp = GetChar(i)) != LYX_META_NEWLINE) {
2364 previous_char = temp;
2369 if (i==0 && i == last &&
2370 !(footnoteflag==LyXParagraph::NO_FOOTNOTE
2371 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
2373 i++; /* the cursor should not jump
2374 * to the main body if there
2381 LyXParagraph * LyXParagraph::DepthHook(int deth)
2383 LyXParagraph * newpar = this;
2388 newpar = newpar->FirstPhysicalPar()->Previous();
2389 } while (newpar && newpar->GetDepth() > deth
2390 && newpar->footnoteflag == footnoteflag);
2393 if (Previous() || GetDepth())
2394 lyxerr << "ERROR (LyXParagraph::DepthHook): "
2398 return newpar->FirstPhysicalPar();
2402 int LyXParagraph::AutoDeleteInsets()
2406 for (InsetList::iterator it = insetlist.begin();
2407 it != insetlist.end(); ++it) {
2408 if ((*it).inset->AutoDelete()) {
2415 InsetTable * tmpi = insettable;
2416 InsetTable * tmpi2 = tmpi;
2422 if (tmpi2->inset->AutoDelete()) {
2427 lyxerr << "ERROR (LyXParagraph::AutoDeleteInsets): "
2428 "cannot auto-delete insets" << endl;
2436 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
2438 Inset * LyXParagraph::ReturnNextInsetPointer(int & pos)
2442 InsetTable * tmp = 0;
2443 for (InsetList::iterator it = insetlist.begin();
2444 it != insetlist.end(); ++it) {
2445 if ((*it).pos >= pos && (!tmp || (*it).pos < tmp->pos)) {
2456 InsetTable * tmpi = insettable;
2457 InsetTable * tmpi2 = 0;
2459 if (tmpi->pos >= pos) {
2460 if (!tmpi2 || tmpi->pos < tmpi2->pos)
2467 return tmpi2->inset;
2475 /* returns -1 if inset not found */
2476 int LyXParagraph::GetPositionOfInset(Inset * inset)
2479 for (InsetList::iterator it = insetlist.begin();
2480 it != insetlist.end(); ++it) {
2481 if ((*it).inset == inset) {
2485 // Think about footnotes
2486 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
2487 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2488 int further = NextAfterFootnote()->GetPositionOfInset(inset);
2491 return size() + 1 + further;
2494 return last + 1 + further;
2499 /* find the entry */
2500 InsetTable * tmpi = insettable;
2501 while (tmpi && tmpi->inset != inset) {
2504 if (tmpi && tmpi->inset)
2507 /* think about footnotes */
2508 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
2509 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2511 NextAfterFootnote()->GetPositionOfInset(inset);
2514 return text.size() + 1 + further;
2517 return last + 1 + further;
2526 void LyXParagraph::readSimpleWholeFile(FILE * myfile)
2530 FileInfo fileInfo(fileno(myfile));
2531 long file_size = fileInfo.getSize();
2532 /* it is horrible, I know, but faster.
2533 * I should not use InsertString for that :-( */
2535 /* I will write a better insertion in the future */
2536 Enlarge(0, file_size + 10);
2540 if (!feof(myfile)) {
2545 InsertChar(text.size(), c);
2549 } while (!feof(myfile));
2555 LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow,
2556 string & foot, TexRow & foot_texrow,
2559 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
2560 LyXParagraph * par = next;
2561 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), layout);
2563 bool further_blank_line = false;
2565 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
2567 if (start_of_appendix) {
2568 file += "\\appendix\n";
2572 if (tex_code_break_column && style.isCommand()){
2577 if (pagebreak_top) {
2578 file += "\\newpage";
2579 further_blank_line = true;
2581 if (added_space_top.kind() != VSpace::NONE) {
2582 file += added_space_top.asLatexCommand();
2583 further_blank_line = true;
2587 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
2588 file += "\\vspace{-1\\parskip}";
2589 further_blank_line = true;
2592 if (further_blank_line){
2597 switch (style.latextype) {
2600 file += style.latexname();
2601 file += style.latexparam();
2603 case LATEX_ITEM_ENVIRONMENT:
2605 bibkey->Latex(file, false);
2609 case LATEX_LIST_ENVIRONMENT:
2616 bool need_par = SimpleTeXOnePar(file, texrow);
2618 // Spit out footnotes
2619 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2620 && par->footnoteflag != footnoteflag) {
2621 par = par->TeXFootnote(file, texrow,
2622 foot, foot_texrow, foot_count);
2623 par->SimpleTeXOnePar(file, texrow);
2627 // Make sure that \\par is done with the font of the last
2628 // character if this has another size as the default.
2629 // This is necessary because LaTeX (and LyX on the screen)
2630 // calculates the space between the baselines according
2631 // to this font. (Matthias)
2632 LyXFont font = getFont(Last()-1);
2634 if (style.resfont.size() != font.size()) {
2636 file += font.latexSize();
2640 } else if (textclasslist.Style(GetCurrentTextClass(),
2641 GetLayout()).isCommand()){
2642 if (style.resfont.size() != font.size()) {
2644 file += font.latexSize();
2648 } else if (style.resfont.size() != font.size()){
2649 file += "{\\" + font.latexSize() + " \\par}";
2652 switch (style.latextype) {
2653 case LATEX_ITEM_ENVIRONMENT:
2654 case LATEX_LIST_ENVIRONMENT:
2655 if (par && (depth < par->depth)) {
2660 case LATEX_ENVIRONMENT:
2661 // if its the last paragraph of the current environment
2662 // skip it otherwise fall through
2664 && (par->layout != layout
2665 || par->depth != depth
2666 || par->pextra_type != pextra_type))
2669 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2670 && footnotekind != LyXParagraph::FOOTNOTE
2671 && footnotekind != LyXParagraph::MARGIN
2675 // don't insert this if we would be adding it
2676 // before or after a table in a float. This
2677 // little trick is needed in order to allow
2678 // use of tables in \subfigures or \subtables.
2684 further_blank_line = false;
2686 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2687 further_blank_line = true;
2690 if (added_space_bottom.kind() != VSpace::NONE) {
2691 file += added_space_bottom.asLatexCommand();
2692 further_blank_line = true;
2695 if (pagebreak_bottom) {
2696 file += "\\newpage";
2697 further_blank_line = true;
2700 if (further_blank_line){
2705 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2706 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2711 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2716 // This one spits out the text of the paragraph
2717 bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow)
2719 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2722 return SimpleTeXOneTablePar(file, texrow);
2726 size_type main_body;
2731 bool return_value = false;
2733 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), GetLayout());
2736 /* maybe we have to create a optional argument */
2737 if (style.labeltype != LABEL_MANUAL)
2740 main_body = BeginningOfMainBody();
2742 if (main_body > 0) {
2744 basefont = getFont(-2); // Get label font
2746 basefont = getFont(-1); // Get layout font
2758 if (style.isCommand()) {
2761 } else if (align != LYX_ALIGN_LAYOUT) {
2764 return_value = true;
2768 // Which font is currently active?
2769 LyXFont running_font = basefont;
2770 // Do we have an open font change?
2771 bool open_font = false;
2773 texrow.start(this, 0);
2776 for (size_type i = 0; i < size(); ++i) {
2778 for (int i = 0; i < last; ++i) {
2781 // First char in paragraph or after label?
2782 if (i == main_body && !IsDummy()) {
2783 if (main_body > 0) {
2785 column += running_font.latexWriteEndChanges(file, basefont);
2788 basefont = getFont(-1); // Now use the layout font
2789 running_font = basefont;
2793 if (style.isCommand()) {
2796 } else if (align != LYX_ALIGN_LAYOUT) {
2799 return_value = true;
2803 file += "\\noindent ";
2807 case LYX_ALIGN_NONE:
2808 case LYX_ALIGN_BLOCK:
2809 case LYX_ALIGN_LAYOUT:
2810 case LYX_ALIGN_SPECIAL: break;
2811 case LYX_ALIGN_LEFT:
2812 file += "\\raggedright ";
2815 case LYX_ALIGN_RIGHT:
2816 file += "\\raggedleft ";
2819 case LYX_ALIGN_CENTER:
2820 file += "\\centering ";
2828 // Fully instantiated font
2829 LyXFont font = getFont(i);
2831 // Spaces at end of font change are simulated to be
2832 // outside font change, i.e. we write "\textXX{text} "
2833 // rather than "\textXX{text }". (Asger)
2835 if (open_font && c == ' ' && i <= size() - 2
2836 && !getFont(i+1).equalExceptLatex(running_font)
2837 && !getFont(i+1).equalExceptLatex(font)) {
2838 font = getFont(i+1);
2841 if (open_font && c == ' ' && i <= last-2
2842 && !getFont(i+1).equalExceptLatex(running_font)
2843 && !getFont(i+1).equalExceptLatex(font)) {
2844 font = getFont(i+1);
2847 // We end font definition before blanks
2848 if (!font.equalExceptLatex(running_font) && open_font) {
2849 column += running_font.latexWriteEndChanges(file, basefont);
2850 running_font = basefont;
2854 // Blanks are printed before start of fontswitch
2856 // Do not print the separation of the optional argument
2857 if (i != main_body - 1) {
2858 SimpleTeXBlanks(file, texrow, i, column, font, style);
2862 // Do we need to change font?
2863 if (!font.equalExceptLatex(running_font)
2864 && i != main_body-1) {
2865 column += font.latexWriteStartChanges(file, basefont);
2866 running_font = font;
2870 if (c == LYX_META_NEWLINE) {
2871 // newlines are handled differently here than
2872 // the default in SimpleTeXSpecialChars().
2873 if (!style.newline_allowed
2874 || font.latex() == LyXFont::ON) {
2878 column += running_font.latexWriteEndChanges(file, basefont);
2881 basefont = getFont(-1);
2882 running_font = basefont;
2883 if (font.family() ==
2884 LyXFont::TYPEWRITER_FAMILY) {
2890 texrow.start(this, i+1);
2893 SimpleTeXSpecialChars(file, texrow,
2894 font, running_font, basefont,
2895 open_font, style, i, column, c);
2899 // If we have an open font definition, we have to close it
2901 running_font.latexWriteEndChanges(file, basefont);
2905 /* needed if there is an optional argument but no contents */
2906 if (main_body > 0 && main_body == size()) {
2908 return_value = false;
2911 /* needed if there is an optional argument but no contents */
2912 if (main_body > 0 && main_body == last) {
2914 return_value = false;
2917 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2918 return return_value;
2922 // This one spits out the text of a table paragraph
2923 bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow)
2925 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2929 bool return_value = false;
2930 int current_cell_number = -1;
2932 LyXLayout const & style =
2933 textclasslist.Style(GetCurrentTextClass(), GetLayout());
2934 LyXFont basefont = getFont(-1); // Get layout font
2935 // Which font is currently active?
2936 LyXFont running_font = basefont;
2937 // Do we have an open font change?
2938 bool open_font = false;
2941 if (!IsDummy()) { // it is dummy if it is in a float!!!
2942 if (style.isCommand()) {
2945 } else if (align != LYX_ALIGN_LAYOUT) {
2948 return_value = true;
2951 file += "\\noindent ";
2955 case LYX_ALIGN_NONE:
2956 case LYX_ALIGN_BLOCK:
2957 case LYX_ALIGN_LAYOUT:
2958 case LYX_ALIGN_SPECIAL: break;
2959 case LYX_ALIGN_LEFT:
2960 file += "\\raggedright ";
2963 case LYX_ALIGN_RIGHT:
2964 file += "\\raggedleft ";
2967 case LYX_ALIGN_CENTER:
2968 file += "\\centering ";
2973 current_cell_number = -1;
2974 tmp = table->TexEndOfCell(file,current_cell_number);
2975 for (; tmp >0 ; --tmp)
2978 texrow.start(this, 0);
2981 for (size_type i = 0; i < size(); ++i) {
2983 for (int i = 0; i < last; ++i) {
2986 if (table->IsContRow(current_cell_number+1)) {
2987 if (c == LYX_META_NEWLINE)
2988 current_cell_number++;
2993 // Fully instantiated font
2994 LyXFont font = getFont(i);
2996 // Spaces at end of font change are simulated to be outside font change.
2997 // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
2999 if (open_font && c == ' ' && i <= size() - 2
3001 if (open_font && c == ' ' && i <= last-2
3003 && getFont(i+1) != running_font && getFont(i+1) != font) {
3004 font = getFont(i+1);
3007 // We end font definition before blanks
3008 if (font != running_font && open_font) {
3009 column += running_font.latexWriteEndChanges(file, basefont);
3010 running_font = basefont;
3013 // Blanks are printed before start of fontswitch
3015 SimpleTeXBlanks(file, texrow, i, column, font, style);
3017 // Do we need to change font?
3018 if (font != running_font) {
3019 column += font.latexWriteStartChanges(file, basefont);
3020 running_font = font;
3023 // Do we need to turn on LaTeX mode?
3024 if (font.latex() != running_font.latex()) {
3025 if (font.latex() == LyXFont::ON
3026 && style.needprotect) {
3027 file += "\\protect ";
3031 if (c == LYX_META_NEWLINE) {
3032 // special case for inside a table
3033 // different from default case in SimpleTeXSpecialChars()
3035 column += running_font.latexWriteEndChanges(file, basefont);
3038 basefont = getFont(-1);
3039 running_font = basefont;
3040 current_cell_number++;
3041 if (table->CellHasContRow(current_cell_number) >= 0) {
3042 TeXContTableRows(file, i+1, current_cell_number, column, texrow);
3044 // if this cell follow only ContRows till end don't
3045 // put the EndOfCell because it is put after the
3047 if (table->ShouldBeVeryLastCell(current_cell_number)) {
3048 current_cell_number--;
3051 int tmp = table->TexEndOfCell(file, current_cell_number);
3054 } else if (tmp < 0) {
3060 texrow.start(this, i+1);
3062 SimpleTeXSpecialChars(file, texrow,
3063 font, running_font, basefont,
3064 open_font, style, i, column, c);
3068 // If we have an open font definition, we have to close it
3070 running_font.latexWriteEndChanges(file, basefont);
3072 current_cell_number++;
3073 tmp = table->TexEndOfCell(file, current_cell_number);
3074 for (; tmp > 0; --tmp)
3076 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
3077 return return_value;
3081 // This one spits out the text off ContRows in tables
3083 bool LyXParagraph::TeXContTableRows(string & file,
3084 LyXParagraph::size_type i,
3085 int current_cell_number,
3086 int & column, TexRow & texrow)
3088 bool LyXParagraph::TeXContTableRows(string & file, int i,
3089 int current_cell_number,
3090 int & column, TexRow & texrow)
3093 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
3099 bool return_value = false;
3100 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), GetLayout());
3103 basefont = getFont(-1); // Get layout font
3104 // Which font is currently active?
3105 LyXFont running_font = basefont;
3106 // Do we have an open font change?
3107 bool open_font = false;
3110 size_type lastpos = i;
3114 int cell = table->CellHasContRow(current_cell_number);
3115 current_cell_number++;
3117 // first find the right position
3120 for (; (i < size()) && (current_cell_number<cell); ++i) {
3122 for (; (i < last) && (current_cell_number<cell); ++i) {
3125 if (c == LYX_META_NEWLINE)
3126 current_cell_number++;
3130 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3134 } else if ((c != ' ') && (c != LYX_META_NEWLINE)) {
3138 for (; i < size() && (c = GetChar(i)) != LYX_META_NEWLINE;
3141 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE);
3146 // Fully instantiated font
3147 LyXFont font = getFont(i);
3149 // Spaces at end of font change are simulated to be outside font change.
3150 // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
3152 if (open_font && c == ' ' && i <= size() - 2
3153 && getFont(i + 1) != running_font
3154 && getFont(i + 1) != font) {
3156 if (open_font && c == ' ' && i <= last - 2
3157 && getFont(i + 1) != running_font
3158 && getFont(i + 1) != font) {
3160 font = getFont(i + 1);
3163 // We end font definition before blanks
3164 if (font != running_font && open_font) {
3165 column += running_font.latexWriteEndChanges(file, basefont);
3166 running_font = basefont;
3169 // Blanks are printed before start of fontswitch
3171 SimpleTeXBlanks(file, texrow, i, column, font, style);
3173 // Do we need to change font?
3174 if (font != running_font) {
3175 column += font.latexWriteStartChanges(file, basefont);
3176 running_font = font;
3179 // Do we need to turn on LaTeX mode?
3180 if (font.latex() != running_font.latex()) {
3181 if (font.latex() == LyXFont::ON
3182 && style.needprotect)
3184 file += "\\protect ";
3188 SimpleTeXSpecialChars(file, texrow, font, running_font, basefont,
3189 open_font, style, i, column, c);
3191 // If we have an open font definition, we have to close it
3193 running_font.latexWriteEndChanges(file, basefont);
3196 basefont = getFont(-1);
3197 running_font = basefont;
3198 cell = table->CellHasContRow(current_cell_number);
3200 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
3201 return return_value;
3205 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
3207 bool retval = false;
3209 case LYX_META_HFILL:
3210 sgml_string.clear();
3212 case LYX_META_PROTECTED_SEPARATOR:
3215 case LYX_META_NEWLINE:
3219 sgml_string = "&";
3222 sgml_string = "<";
3225 sgml_string = ">";
3228 sgml_string = "$";
3231 sgml_string = "#";
3234 sgml_string = "%";
3237 sgml_string = "[";
3240 sgml_string = "]";
3243 sgml_string = "{";
3246 sgml_string = "}";
3249 sgml_string = "˜";
3252 sgml_string = """;
3255 sgml_string = "\";
3261 case '\0': /* Ignore :-) */
3262 sgml_string.clear();
3271 void LyXParagraph::SimpleDocBookOneTablePar(string & file, string & extra,
3272 int & desc_on, int depth)
3276 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
3278 int current_cell_number = -1;
3279 LyXFont font1,font2;
3283 size_type main_body;
3287 string emph = "emphasis";
3288 bool emph_flag=false;
3289 int char_line_count=0;
3291 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), GetLayout());
3293 if (style.labeltype != LABEL_MANUAL)
3296 main_body = BeginningOfMainBody();
3298 /* gets paragraph main font */
3300 font1 = style.labelfont;
3304 char_line_count = depth;
3305 addNewlineAndDepth(file, depth);
3306 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
3307 file += "<INFORMALTABLE>";
3308 addNewlineAndDepth(file, ++depth);
3310 current_cell_number = -1;
3311 tmp = table->DocBookEndOfCell(file,current_cell_number, depth);
3313 /* parsing main loop */
3315 for (size_type i = 0; i < size(); ++i) {
3317 for (int i = 0; i < last; ++i) {
3320 if (table->IsContRow(current_cell_number+1)) {
3321 if (c == LYX_META_NEWLINE)
3322 current_cell_number++;
3327 // Fully instantiated font
3330 /* handle <emphasis> tag */
3331 if (font1.emph() != font2.emph() && i) {
3332 if (font2.emph() == LyXFont::ON) {
3333 file += "<emphasis>";
3335 } else if (emph_flag) {
3336 file += "</emphasis>";
3340 if (c == LYX_META_NEWLINE) {
3341 // we have only to control for emphasis open here!
3343 file += "</emphasis>";
3346 font1 = font2 = getFont(-1);
3347 current_cell_number++;
3348 if (table->CellHasContRow(current_cell_number) >= 0) {
3349 DocBookContTableRows(file, extra, desc_on, i+1,
3350 current_cell_number,
3353 // if this cell follow only ContRows till end don't
3354 // put the EndOfCell because it is put after the
3356 if (table->ShouldBeVeryLastCell(current_cell_number)) {
3357 current_cell_number--;
3360 tmp=table->DocBookEndOfCell(file, current_cell_number,
3365 } else if (c == LYX_META_INSET) {
3366 inset = GetInset(i);
3368 inset->DocBook(tmp_out);
3370 // This code needs some explanation:
3371 // Two insets are treated specially
3372 // label if it is the first element in a command paragraph
3374 // graphics inside tables or figure floats can't go on
3375 // title (the equivalente in latex for this case is caption
3376 // and title should come first
3379 if(desc_on != 3 || i != 0) {
3380 if(tmp_out[0] == '@') {
3382 extra += frontStrip(tmp_out, '@');
3384 file += frontStrip(tmp_out, '@');
3388 } else if (font2.latex() == LyXFont::ON) {
3389 // "TeX"-Mode on ==> SGML-Mode on.
3395 if (linuxDocConvertChar(c, sgml_string)
3396 && !style.free_spacing) {
3397 // in freespacing mode, spaces are
3398 // non-breaking characters
3403 file += "</term><listitem><para>";
3409 file += sgml_string;
3415 /* needed if there is an optional argument but no contents */
3417 if (main_body > 0 && main_body == size()) {
3421 if (main_body > 0 && main_body == last) {
3426 file += "</emphasis>";
3429 current_cell_number++;
3430 tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
3431 /* resets description flag correctly */
3434 /* <term> not closed... */
3438 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3439 file += "</INFORMALTABLE>";
3441 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
3446 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
3447 int & desc_on, LyXParagraph::size_type i,
3448 int current_cell_number, int &column)
3451 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
3452 int & desc_on, int i,
3453 int current_cell_number, int &column)
3460 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
3463 LyXFont font1,font2;
3467 size_type main_body;
3473 string emph="emphasis";
3474 bool emph_flag=false;
3475 int char_line_count=0;
3477 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), GetLayout());
3479 if (style.labeltype != LABEL_MANUAL)
3482 main_body = BeginningOfMainBody();
3484 /* gets paragraph main font */
3486 font1 = style.labelfont;
3491 cell = table->CellHasContRow(current_cell_number);
3492 current_cell_number++;
3494 // first find the right position
3497 for (; i < size() && current_cell_number < cell; ++i) {
3499 for (; i < last && (current_cell_number < cell); ++i) {
3502 if (c == LYX_META_NEWLINE)
3503 current_cell_number++;
3507 // I don't know how to handle this so I comment it
3508 // for the moment (Jug)
3509 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3510 // file += " \\\\\n";
3513 if ((c != ' ') && (c != LYX_META_NEWLINE)) {
3517 for (; i < size() && (c = GetChar(i)) != LYX_META_NEWLINE;
3520 for (; i < last && ((c = GetChar(i)) != LYX_META_NEWLINE);
3525 // Fully instantiated font
3528 /* handle <emphasis> tag */
3529 if (font1.emph() != font2.emph() && i) {
3530 if (font2.emph() == LyXFont::ON) {
3531 file += "<emphasis>";
3533 } else if (emph_flag) {
3534 file += "</emphasis>";
3538 if (c == LYX_META_INSET) {
3539 inset = GetInset(i);
3541 inset->DocBook(tmp_out);
3543 // This code needs some explanation:
3544 // Two insets are treated specially
3545 // label if it is the first element in a command paragraph
3547 // graphics inside tables or figure floats can't go on
3548 // title (the equivalente in latex for this case is caption
3549 // and title should come first
3552 if(desc_on != 3 || i != 0) {
3553 if(tmp_out[0]=='@') {
3555 extra += frontStrip(tmp_out, '@');
3557 file += frontStrip(tmp_out, '@');
3561 } else if (font2.latex() == LyXFont::ON) {
3562 // "TeX"-Mode on ==> SGML-Mode on.
3568 if (linuxDocConvertChar(c, sgml_string)
3569 && !style.free_spacing) {
3570 // in freespacing mode, spaces are
3571 // non-breaking characters
3576 file += "</term><listitem><para>";
3582 file += sgml_string;
3586 // we have only to control for emphasis open here!
3588 file += "</emphasis>";
3591 font1 = font2 = getFont(-1);
3592 cell = table->CellHasContRow(current_cell_number);
3594 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3598 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
3599 LyXParagraph::size_type const i, int & column, LyXFont const & font,
3600 LyXLayout const & style)
3602 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
3603 int const i, int & column, LyXFont const & font,
3604 LyXLayout const & style)
3607 if (column > tex_code_break_column
3609 && GetChar(i - 1) != ' '
3615 // In LaTeX mode, we don't want to
3616 // break lines since some commands
3618 && ! (font.latex() == LyXFont::ON)
3619 // same in FreeSpacing mode
3620 && !style.free_spacing
3621 // In typewriter mode, we want to avoid
3622 // ! . ? : at the end of a line
3623 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3624 && (GetChar(i-1) == '.'
3625 || GetChar(i-1) == '?'
3626 || GetChar(i-1) == ':'
3627 || GetChar(i-1) == '!'))) {
3628 if (tex_code_break_column == 0) {
3629 // in batchmode we need LaTeX to still
3630 // see it as a space not as an extra '\n'
3636 texrow.start(this, i+1);
3638 } else if (font.latex() == LyXFont::OFF) {
3639 if (style.free_spacing) {
3649 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
3650 LyXFont & font, LyXFont & running_font,
3653 LyXLayout const & style,
3654 LyXParagraph::size_type & i, int &column, char const c)
3656 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
3657 LyXFont & font, LyXFont & running_font,
3660 LyXLayout const & style,
3661 int & i, int &column, char const c)
3664 // Two major modes: LaTeX or plain
3665 // Handle here those cases common to both modes
3666 // and then split to handle the two modes separately.
3668 case LYX_META_INSET: {
3669 Inset * inset = GetInset(i);
3671 int len = file.length();
3672 int tmp = inset->Latex(file, style.isCommand());
3677 column += file.length() - len;
3686 case LYX_META_NEWLINE:
3688 column += running_font.latexWriteEndChanges(file, basefont);
3691 basefont = getFont(-1);
3692 running_font = basefont;
3695 case LYX_META_HFILL:
3696 file += "\\hfill{}";
3701 // And now for the special cases within each mode
3702 // Are we in LaTeX mode?
3703 if (font.latex() == LyXFont::ON) {
3704 // at present we only have one option
3705 // but I'll leave it as a switch statement
3706 // so its simpler to extend. (ARRae)
3708 case LYX_META_PROTECTED_SEPARATOR:
3713 // make sure that we will not print
3714 // error generating chars to the tex
3715 // file. This test would not be needed
3716 // if it were done in the buffer
3724 // Plain mode (i.e. not LaTeX)
3726 case LYX_META_PROTECTED_SEPARATOR:
3731 file += "\\textbackslash{}";
3735 case '°': case '±': case '²': case '³':
3736 case '×': case '÷': case '¹': case 'ª':
3737 case 'º': case '¬': case 'µ':
3738 if (current_view->buffer()->params.inputenc == "latin1") {
3739 file += "\\ensuremath{";
3748 case '|': case '<': case '>':
3749 // In T1 encoding, these characters exist
3750 if (lyxrc->fontenc == "T1") {
3752 //... but we should avoid ligatures
3753 if ((c == '>' || c == '<')
3759 && GetChar(i+1) == c){
3760 file += "\\textcompwordmark{}";
3765 // Typewriter font also has them
3766 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3770 // Otherwise, we use what LaTeX
3774 file += "\\textless{}";
3778 file += "\\textgreater{}";
3782 file += "\\textbar{}";
3788 case '-': // "--" in Typewriter mode -> "-{}-"
3794 && GetChar(i + 1) == '-'
3795 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3804 file += "\\char`\\\"{}";
3809 if (current_view->buffer()->params.inputenc == "default") {
3810 file += "\\pounds{}";
3818 case '%': case '#': case '{':
3832 case '*': case '[': case ']':
3833 // avoid being mistaken for optional arguments
3841 /* blanks are printed before font switching */
3842 // Sure? I am not! (try nice-latex)
3843 // I am sure it's correct. LyX might be smarter
3844 // in the future, but for now, nothing wrong is
3849 /* idea for labels --- begin*/
3857 && font.family() != LyXFont::TYPEWRITER_FAMILY
3858 && GetChar(i + 1) == 'y'
3859 && GetChar(i + 2) == 'X') {
3871 && font.family() != LyXFont::TYPEWRITER_FAMILY
3872 && GetChar(i + 1) == 'e'
3873 && GetChar(i + 2) == 'X') {
3878 /* check for LaTeX2e */
3885 && font.family() != LyXFont::TYPEWRITER_FAMILY
3886 && GetChar(i + 1) == 'a'
3887 && GetChar(i + 2) == 'T'
3888 && GetChar(i + 3) == 'e'
3889 && GetChar(i + 4) == 'X'
3890 && GetChar(i + 5) == '2'
3891 && GetChar(i + 6) == 'e') {
3892 file += "\\LaTeXe{}";
3896 /* check for LaTeX */
3903 && font.family() != LyXFont::TYPEWRITER_FAMILY
3904 && GetChar(i + 1) == 'a'
3905 && GetChar(i + 2) == 'T'
3906 && GetChar(i + 3) == 'e'
3907 && GetChar(i + 4) == 'X') {
3908 file += "\\LaTeX{}";
3911 /* idea for labels --- end*/
3912 } else if (c != '\0') {
3922 bool LyXParagraph::RoffContTableRows(FILE * fp,
3923 LyXParagraph::size_type i,
3926 bool LyXParagraph::RoffContTableRows(FILE * fp, int i, int actcell)
3932 LyXFont font1 = LyXFont(LyXFont::ALL_INHERIT);
3938 string fname2 = TmpFileName(string(), "RAT2");
3940 int cell = table->CellHasContRow(actcell);
3943 // first find the right position
3946 for (; i < size() && actcell < cell; ++i) {
3948 for (; i < last && actcell < cell; ++i) {
3951 if (c == LYX_META_NEWLINE)
3956 if ((c != ' ') && (c != LYX_META_NEWLINE))
3959 for (; i < size() && (c = GetChar(i)) != LYX_META_NEWLINE;
3962 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE);
3965 font2 = GetFontSettings(i);
3966 if (font1.latex() != font2.latex()) {
3967 if (font2.latex() != LyXFont::OFF)
3972 case LYX_META_INSET:
3973 if ((inset = GetInset(i))) {
3974 if (!(fp2=fopen(fname2.c_str(),"w+"))) {
3975 WriteAlert(_("LYX_ERROR:"), _("Cannot open temporary file:"), fname2);
3978 inset->Latex(fp2,-1);
3991 case LYX_META_NEWLINE:
3993 case LYX_META_HFILL:
3995 case LYX_META_PROTECTED_SEPARATOR:
3998 fprintf(fp, "\\\\");
4002 fprintf(fp, "%c", c);
4004 lyxerr.debug() << "RoffAsciiTable: NULL char in structure." << endl;
4008 cell = table->CellHasContRow(actcell);
4013 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
4014 string & foot, TexRow & foot_texrow,
4017 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
4018 LyXParagraph * par = this;
4020 while (par && par->depth == depth) {
4022 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
4023 if (textclasslist.Style(GetCurrentTextClass(),
4024 par->layout).isEnvironment()
4025 || par->pextra_type != PEXTRA_NONE)
4027 par = par->TeXEnvironment(file, texrow,
4031 par = par->TeXOnePar(file, texrow,
4036 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
4042 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
4043 string & foot, TexRow & foot_texrow,
4046 bool eindent_open = false;
4047 bool foot_this_level = false;
4048 // flags when footnotetext should be appended to file.
4049 static bool minipage_open = false;
4050 static int minipage_open_depth = 0;
4051 char par_sep = current_view->buffer()->params.paragraph_separation;
4053 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
4055 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
4057 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(), layout);
4059 if (pextra_type == PEXTRA_INDENT) {
4060 if (!pextra_width.empty()) {
4061 file += "\\begin{LyXParagraphIndent}{"
4062 + pextra_width + "}\n";
4064 //float ib = atof(pextra_widthp.c_str())/100;
4065 // string can't handle floats at present (971109)
4066 // so I'll do a conversion by hand knowing that
4067 // the limits are 0.0 to 1.0. ARRae.
4068 file += "\\begin{LyXParagraphIndent}{";
4069 switch (pextra_widthp.length()) {
4075 file += pextra_widthp;
4079 file += pextra_widthp;
4081 file += "\\columnwidth}\n";
4084 eindent_open = true;
4086 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
4087 if (pextra_hfill && Previous() &&
4088 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
4089 file += "\\hfill{}\n";
4092 if (par_sep == LYX_PARSEP_INDENT) {
4093 file += "{\\setlength\\parindent{0pt}\n";
4096 file += "\\begin{minipage}";
4097 switch(pextra_alignment) {
4098 case MINIPAGE_ALIGN_TOP:
4101 case MINIPAGE_ALIGN_MIDDLE:
4104 case MINIPAGE_ALIGN_BOTTOM:
4108 if (!pextra_width.empty()) {
4110 file += pextra_width + "}\n";
4112 //float ib = atof(par->pextra_width.c_str())/100;
4113 // string can't handle floats at present
4114 // so I'll do a conversion by hand knowing that
4115 // the limits are 0.0 to 1.0. ARRae.
4117 switch (pextra_widthp.length()) {
4123 file += pextra_widthp;
4127 file += pextra_widthp;
4129 file += "\\columnwidth}\n";
4132 if (par_sep == LYX_PARSEP_INDENT) {
4133 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
4136 minipage_open = true;
4137 minipage_open_depth = depth;
4140 #ifdef WITH_WARNINGS
4141 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
4142 //I disabled it because it breaks when lists span on several
4145 if (style.isEnvironment()){
4146 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
4147 #ifdef FANCY_FOOTNOTE_CODE
4148 if (foot_count < 0) {
4149 // flag that footnote[mark][text] should be
4150 // used for any footnotes from now on
4152 foot_this_level = true;
4155 file += "\\begin{" + style.latexname() + "}{"
4156 + labelwidthstring + "}\n";
4157 } else if (style.labeltype == LABEL_BIBLIO) {
4159 file += "\\begin{" + style.latexname() + "}{"
4160 + bibitemWidthest() + "}\n";
4161 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
4162 #ifdef FANCY_FOOTNOTE_CODE
4163 if (foot_count < 0) {
4164 // flag that footnote[mark][text] should be
4165 // used for any footnotes from now on
4167 foot_this_level = true;
4170 file += "\\begin{" + style.latexname() + '}'
4171 + style.latexparam() + '\n';
4173 file += "\\begin{" + style.latexname() + '}'
4174 + style.latexparam() + '\n';
4177 LyXParagraph * par = this;
4179 par = par->TeXOnePar(file, texrow,
4180 foot, foot_texrow, foot_count);
4182 if (minipage_open && par && !style.isEnvironment() &&
4183 (par->pextra_type == PEXTRA_MINIPAGE) &&
4184 par->pextra_start_minipage) {
4185 file += "\\end{minipage}\n";
4187 if (par_sep == LYX_PARSEP_INDENT) {
4191 minipage_open = false;
4193 if (par && par->depth > depth) {
4194 if (textclasslist.Style(GetCurrentTextClass(),
4195 par->layout).isParagraph()
4197 && !suffixIs(file, "\n\n")) {
4198 // There should be at least one '\n' already
4199 // but we need there to be two for Standard
4200 // paragraphs that are depth-increment'ed to be
4201 // output correctly. However, tables can also be
4202 // paragraphs so don't adjust them. ARRae
4206 par = par->TeXDeeper(file, texrow,
4207 foot, foot_texrow, foot_count);
4209 if (par && par->layout == layout && par->depth == depth &&
4210 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
4211 if (par->pextra_hfill && par->Previous() &&
4212 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
4213 file += "\\hfill{}\n";
4216 if (par_sep == LYX_PARSEP_INDENT) {
4217 file += "{\\setlength\\parindent{0pt}\n";
4220 file += "\\begin{minipage}";
4221 switch(par->pextra_alignment) {
4222 case MINIPAGE_ALIGN_TOP:
4225 case MINIPAGE_ALIGN_MIDDLE:
4228 case MINIPAGE_ALIGN_BOTTOM:
4232 if (!par->pextra_width.empty()) {
4234 file += par->pextra_width;
4237 //float ib = atof(par->pextra_widthp.c_str())/100;
4238 // string can't handle floats at present
4239 // so I'll do a conversion by hand knowing that
4240 // the limits are 0.0 to 1.0. ARRae.
4242 switch (par->pextra_widthp.length()) {
4248 file += par->pextra_widthp;
4252 file += par->pextra_widthp;
4254 file += "\\columnwidth}\n";
4257 if (par_sep == LYX_PARSEP_INDENT) {
4258 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
4261 minipage_open = true;
4262 minipage_open_depth = par->depth;
4265 && par->layout == layout
4266 && par->depth == depth
4267 && par->pextra_type == pextra_type);
4269 if (style.isEnvironment()) {
4270 file += "\\end{" + style.latexname() + '}';
4271 // maybe this should go after the minipage closes?
4272 if (foot_this_level) {
4273 if (foot_count >= 1) {
4274 if (foot_count > 1) {
4275 file += "\\addtocounter{footnote}{-";
4276 file += tostr(foot_count - 1);
4280 texrow += foot_texrow;
4282 foot_texrow.reset();
4287 if (minipage_open && (minipage_open_depth == depth) &&
4288 (!par || par->pextra_start_minipage ||
4289 par->pextra_type != PEXTRA_MINIPAGE)) {
4290 file += "\\end{minipage}\n";
4292 if (par_sep == LYX_PARSEP_INDENT) {
4296 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
4297 file += "\\medskip\n\n";
4301 minipage_open = false;
4304 file += "\\end{LyXParagraphIndent}\n";
4307 if (!(par && (par->pextra_type==PEXTRA_MINIPAGE)
4308 && par->pextra_hfill)) {
4312 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
4313 return par; // ale970302
4317 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
4318 string & foot, TexRow & foot_texrow,
4321 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
4322 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
4323 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4324 "No footnote!" << endl;
4326 LyXParagraph * par = this;
4327 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
4328 previous->GetLayout());
4330 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
4331 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4332 "Float other than footnote in command"
4333 " with moving argument is illegal" << endl;
4336 if (footnotekind != LyXParagraph::FOOTNOTE
4337 && footnotekind != LyXParagraph::MARGIN
4339 && !suffixIs(file, '\n')) {
4340 // we need to ensure that real floats like tables and figures
4341 // have their \begin{} on a new line otherwise we can get
4342 // incorrect results when using the endfloat.sty package
4343 // especially if two floats follow one another. ARRae 981022
4344 // NOTE: if the file is length 0 it must have just been
4345 // written out so we assume it ended with a '\n'
4350 BufferParams * params = ¤t_view->buffer()->params;
4351 bool footer_in_body = true;
4352 switch (footnotekind) {
4353 case LyXParagraph::FOOTNOTE:
4354 if (style.intitle) {
4355 file += "\\thanks{\n";
4356 footer_in_body = false;
4358 if (foot_count == -1) {
4359 // we're at depth 0 so we can use:
4360 file += "\\footnote{%\n";
4361 footer_in_body = false;
4363 file += "\\footnotemark{}%\n";
4365 // we only need this when there are
4366 // multiple footnotes
4367 foot += "\\stepcounter{footnote}";
4369 foot += "\\footnotetext{%\n";
4370 foot_texrow.start(this,0);
4371 foot_texrow.newline();
4376 case LyXParagraph::MARGIN:
4377 file += "\\marginpar{\n";
4379 case LyXParagraph::FIG:
4380 if (pextra_type == PEXTRA_FLOATFLT
4381 && (!pextra_width.empty()
4382 || !pextra_widthp.empty())) {
4384 if (!pextra_width.empty())
4385 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
4386 pextra_width.c_str());
4388 sprintf(bufr, "\\begin{floatingfigure}{%f\\textwidth}\n",
4389 atoi(pextra_widthp.c_str())/100.0);
4392 file += "\\begin{figure}";
4393 if (!params->float_placement.empty()) {
4395 file += params->float_placement;
4402 case LyXParagraph::TAB:
4403 file += "\\begin{table}";
4404 if (!params->float_placement.empty()) {
4406 file += params->float_placement;
4412 case LyXParagraph::WIDE_FIG:
4413 file += "\\begin{figure*}";
4414 if (!params->float_placement.empty()) {
4416 file += params->float_placement;
4422 case LyXParagraph::WIDE_TAB:
4423 file += "\\begin{table*}";
4424 if (!params->float_placement.empty()) {
4426 file += params->float_placement;
4432 case LyXParagraph::ALGORITHM:
4433 file += "\\begin{algorithm}\n";
4438 if (footnotekind != LyXParagraph::FOOTNOTE
4439 || !footer_in_body) {
4440 // Process text for all floats except footnotes in body
4442 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
4445 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4447 if (style.isEnvironment()
4448 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4449 // Allows the use of minipages within float environments.
4450 // Shouldn't be circular because we don't support
4451 // footnotes inside floats (yet). ARRae
4452 par = par->TeXEnvironment(file, texrow,
4456 par = par->TeXOnePar(file, texrow,
4461 if (par && !par->IsDummy() && par->depth > depth) {
4462 par = par->TeXDeeper(file, texrow,
4466 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4468 // process footnotes > depth 0 or in environments separately
4469 // NOTE: Currently don't support footnotes within footnotes
4470 // even though that is possible using the \footnotemark
4472 TexRow dummy_texrow;
4473 int dummy_count = 0;
4475 LyXLayout const & style = textclasslist.Style(GetCurrentTextClass(),
4478 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
4480 if (style.isEnvironment()
4481 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
4482 // Allows the use of minipages within float environments.
4483 // Shouldn't be circular because we don't support
4484 // footnotes inside floats (yet). ARRae
4485 par = par->TeXEnvironment(foot, foot_texrow,
4486 dummy, dummy_texrow,
4489 par = par->TeXOnePar(foot, foot_texrow,
4490 dummy, dummy_texrow,
4494 if (par && !par->IsDummy() && par->depth > depth) {
4495 par = par->TeXDeeper(foot, foot_texrow,
4496 dummy, dummy_texrow,
4499 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
4501 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
4502 "Footnote in a Footnote -- not supported"
4507 switch (footnotekind) {
4508 case LyXParagraph::FOOTNOTE:
4509 if (footer_in_body) {
4510 // This helps tell which of the multiple
4511 // footnotetexts an error was in.
4513 foot_texrow.newline();
4518 case LyXParagraph::MARGIN:
4521 case LyXParagraph::FIG:
4522 if (pextra_type == PEXTRA_FLOATFLT
4523 && (!pextra_width.empty()
4524 || !pextra_widthp.empty()))
4525 file += "\\end{floatingfigure}";
4527 file += "\\end{figure}";
4529 case LyXParagraph::TAB:
4530 file += "\\end{table}";
4532 case LyXParagraph::WIDE_FIG:
4533 file += "\\end{figure*}";
4535 case LyXParagraph::WIDE_TAB:
4536 file += "\\end{table*}";
4538 case LyXParagraph::ALGORITHM:
4539 file += "\\end{algorithm}";
4543 if (footnotekind != LyXParagraph::FOOTNOTE
4544 && footnotekind != LyXParagraph::MARGIN) {
4545 // we need to ensure that real floats like tables and figures
4546 // have their \end{} on a line of their own otherwise we can
4547 // get incorrect results when using the endfloat.sty package.
4552 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
4557 void LyXParagraph::SetPExtraType(int type, char const * width,
4558 char const * widthp)
4561 pextra_width = width;
4562 pextra_widthp = widthp;
4564 if (textclasslist.Style(GetCurrentTextClass(),
4565 layout).isEnvironment()) {
4570 while (par && (par->layout == layout) && (par->depth == depth)) {
4572 par = par->Previous();
4574 par = par->FirstPhysicalPar();
4575 while (par && par->depth > depth) {
4576 par = par->Previous();
4578 par = par->FirstPhysicalPar();
4582 while (par && (par->layout == layout) && (par->depth == depth)) {
4583 par->pextra_type = type;
4584 par->pextra_width = width;
4585 par->pextra_widthp = widthp;
4586 par = par->NextAfterFootnote();
4587 if (par && (par->depth > depth))
4588 par->SetPExtraType(type,width,widthp);
4589 while (par && ((par->depth > depth) || par->IsDummy()))
4590 par = par->NextAfterFootnote();
4595 void LyXParagraph::UnsetPExtraType()
4597 if (pextra_type == PEXTRA_NONE)
4600 pextra_type = PEXTRA_NONE;
4601 pextra_width.clear();
4602 pextra_widthp.clear();
4604 if (textclasslist.Style(GetCurrentTextClass(),
4605 layout).isEnvironment()) {
4610 while (par && (par->layout == layout) && (par->depth == depth)) {
4612 par = par->Previous();
4614 par = par->FirstPhysicalPar();
4615 while (par && par->depth > depth) {
4616 par = par->Previous();
4618 par = par->FirstPhysicalPar();
4622 while (par && (par->layout == layout) && (par->depth == depth)) {
4623 par->pextra_type = PEXTRA_NONE;
4624 par->pextra_width.clear();
4625 par->pextra_widthp.clear();
4626 par = par->NextAfterFootnote();
4627 if (par && (par->depth > depth))
4628 par->UnsetPExtraType();
4629 while (par && ((par->depth > depth) || par->IsDummy()))
4630 par = par->NextAfterFootnote();