1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2000 The LyX Team.
9 * ====================================================== */
14 #pragma implementation "lyxparagraph.h"
21 #include "lyxparagraph.h"
22 #include "support/textutils.h"
25 #include "tex-strings.h"
26 #include "bufferparams.h"
27 #include "support/FileInfo.h"
28 #include "support/LAssert.h"
30 #include "LaTeXFeatures.h"
31 #include "insets/insetinclude.h"
32 #include "insets/insetbib.h"
33 #include "support/filetools.h"
34 #include "lyx_gui_misc.h"
38 #ifdef USE_OSTREAM_ONLY
39 #include "support/lyxmanip.h"
41 extern void addNewlineAndDepth(string & file, int depth); // Jug 990923
43 int tex_code_break_column = 72; // needs non-zero initialization. set later.
44 // this is a bad idea, but how can LyXParagraph find its buffer to get
45 // parameters? (JMarc)
46 extern BufferView * current_view;
51 extern string bibitemWidthest(Painter &);
53 // this is a minibuffer
54 static char minibuffer_char;
55 static LyXFont minibuffer_font;
56 static Inset * minibuffer_inset;
59 // Initialization of the counter for the paragraph id's,
60 // declared in lyxparagraph.h
61 unsigned int LyXParagraph::paragraph_id = 0;
64 LyXParagraph::LyXParagraph()
66 text.reserve(500); // is this number too big?
68 for (int i = 0; i < 10; ++i) setCounter(i , 0);
74 footnoteflag = LyXParagraph::NO_FOOTNOTE;
75 footnotekind = LyXParagraph::FOOTNOTE; // should not be needed
77 align = LYX_ALIGN_BLOCK;
79 /* table stuff -- begin*/
81 /* table stuff -- end*/
83 bibkey = 0; // ale970302
88 // This konstruktor inserts the new paragraph in a list.
89 LyXParagraph::LyXParagraph(LyXParagraph * par)
92 par->text.resize(par->text.size());
94 for (int i = 0; i < 10; ++i) setCounter(i, 0);
98 // double linked list begin
101 next->previous = this;
103 previous->next = this;
105 footnoteflag = LyXParagraph::NO_FOOTNOTE;
106 footnotekind = LyXParagraph::FOOTNOTE;
108 /* table stuff -- begin*/
110 /* table stuff -- end*/
111 id_ = paragraph_id++;
113 bibkey = 0; // ale970302
119 void LyXParagraph::writeFile(ostream & os, BufferParams const & params,
120 char footflag, char dth) const
122 LyXFont font1, font2;
127 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
129 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
131 // The beginning or the end of a footnote environment?
132 if (footflag != footnoteflag) {
133 footflag = footnoteflag;
135 os << "\n\\begin_float "
136 << string_footnotekinds[footnotekind]
139 os << "\n\\end_float ";
143 // The beginning or end of a deeper (i.e. nested) area?
146 while (depth > dth) {
147 os << "\n\\begin_deeper ";
151 while (depth < dth) {
152 os << "\n\\end_deeper ";
158 // First write the layout
160 << textclasslist.NameOfLayout(params.textclass, layout)
163 // Maybe some vertical spaces.
164 if (added_space_top.kind() != VSpace::NONE)
165 os << "\\added_space_top "
166 << added_space_top.asLyXCommand() << " ";
167 if (added_space_bottom.kind() != VSpace::NONE)
168 os << "\\added_space_bottom "
169 << added_space_bottom.asLyXCommand() << " ";
171 // The labelwidth string used in lists.
172 if (!labelwidthstring.empty())
173 os << "\\labelwidthstring "
174 << labelwidthstring << '\n';
176 // Lines above or below?
180 os << "\\line_bottom ";
182 // Pagebreaks above or below?
184 os << "\\pagebreak_top ";
185 if (pagebreak_bottom)
186 os << "\\pagebreak_bottom ";
188 // Start of appendix?
189 if (start_of_appendix)
190 os << "\\start_of_appendix ";
197 if (align != LYX_ALIGN_LAYOUT) {
199 case LYX_ALIGN_LEFT: h = 1; break;
200 case LYX_ALIGN_RIGHT: h = 2; break;
201 case LYX_ALIGN_CENTER: h = 3; break;
202 default: h = 0; break;
204 os << "\\align " << string_align[h] << " ";
206 if (pextra_type != PEXTRA_NONE) {
207 os << "\\pextra_type " << pextra_type;
208 if (pextra_type == PEXTRA_MINIPAGE) {
209 os << " \\pextra_alignment "
212 os << " \\pextra_hfill "
214 if (pextra_start_minipage)
215 os << " \\pextra_start_minipage "
216 << pextra_start_minipage;
218 if (!pextra_width.empty()) {
219 os << " \\pextra_width "
220 << VSpace(pextra_width).asLyXCommand();
221 } else if (!pextra_widthp.empty()) {
222 os << " \\pextra_widthp "
228 // Dummy layout. This means that a footnote ended.
229 os << "\n\\end_float ";
230 footflag = LyXParagraph::NO_FOOTNOTE;
233 // It might be a table.
235 os << "\\LyXTable\n";
243 font1 = LyXFont(LyXFont::ALL_INHERIT);
246 for (size_type i = 0; i < size(); ++i) {
252 // Write font changes
253 font2 = GetFontSettings(i);
254 if (font2 != font1) {
255 font2.lyxWriteChanges(font1, os);
264 Inset const * inset = GetInset(i);
266 if (inset->DirectWrite()) {
267 // international char, let it write
268 // code directly so it's shorter in
272 os << "\n\\begin_inset ";
274 os << "\n\\end_inset \n\n";
280 os << "\n\\newline \n";
284 os << "\n\\hfill \n";
288 case META_PROTECTED_SEPARATOR:
289 os << "\n\\protected_separator \n";
294 os << "\n\\backslash \n";
298 if (i + 1 < size() && GetChar(i + 1) == ' ') {
305 if ((column > 70 && c == ' ')
310 // this check is to amend a bug. LyX sometimes
311 // inserts '\0' this could cause problems.
315 lyxerr << "ERROR (LyXParagraph::writeFile):"
316 " NULL char in structure." << endl;
322 // now write the next paragraph
324 next->writeFile(os, params, footflag, dth);
328 void LyXParagraph::validate(LaTeXFeatures & features) const
330 // this will be useful later
331 LyXLayout const & layout =
332 textclasslist.Style(current_view->buffer()->params.textclass,
336 if (line_top || line_bottom)
337 features.lyxline = true;
340 features.layout[GetLayout()] = true;
343 for (FontList::const_iterator cit = fontlist.begin();
344 cit != fontlist.end(); ++cit) {
345 if ((*cit).font.noun() == LyXFont::ON) {
346 lyxerr[Debug::LATEX] << "font.noun: "
347 << (*cit).font.noun()
349 features.noun = true;
350 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
351 << (*cit).font.stateText()
354 switch ((*cit).font.color()) {
356 case LColor::inherit:
360 features.color = true;
361 lyxerr[Debug::LATEX] << "Color enabled. Font: "
362 << (*cit).font.stateText()
368 for (InsetList::const_iterator cit = insetlist.begin();
369 cit != insetlist.end(); ++cit) {
371 (*cit).inset->Validate(features);
374 if (table && table->IsLongTable())
375 features.longtable = true;
376 if (pextra_type == PEXTRA_INDENT)
377 features.LyXParagraphIndent = true;
378 if (pextra_type == PEXTRA_FLOATFLT)
379 features.floatflt = true;
380 if (layout.needprotect
381 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
382 features.NeedLyXFootnoteCode = true;
383 if ((current_view->buffer()->params.paragraph_separation == BufferParams::PARSEP_INDENT) &&
384 (pextra_type == LyXParagraph::PEXTRA_MINIPAGE))
385 features.NeedLyXMinipageIndent = true;
386 if (table && table->NeedRotating())
387 features.rotating = true;
388 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
389 features.algorithm = true;
393 // First few functions needed for cut and paste and paragraph breaking.
394 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos) const
396 minibuffer_char = GetChar(pos);
397 minibuffer_font = GetFontSettings(pos);
398 minibuffer_inset = 0;
399 if (minibuffer_char == LyXParagraph::META_INSET) {
401 minibuffer_inset = GetInset(pos)->Clone();
403 minibuffer_inset = 0;
404 minibuffer_char = ' ';
405 // This reflects what GetInset() does (ARRae)
411 void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos)
413 minibuffer_char = GetChar(pos);
414 minibuffer_font = GetFontSettings(pos);
415 minibuffer_inset = 0;
416 if (minibuffer_char == LyXParagraph::META_INSET) {
418 minibuffer_inset = GetInset(pos);
419 // This is a little hack since I want exactly
420 // the inset, not just a clone. Otherwise
421 // the inset would be deleted when calling Erase(pos)
423 for (InsetList::iterator it = insetlist.begin();
424 it != insetlist.end(); ++it) {
425 if ((*it).pos == pos) {
432 minibuffer_inset = 0;
433 minibuffer_char = ' ';
434 // This reflects what GetInset() does (ARRae)
439 // Erase(pos); now the caller is responsible for that.
443 void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
445 InsertChar(pos, minibuffer_char);
446 SetFont(pos, minibuffer_font);
447 if (minibuffer_char == LyXParagraph::META_INSET)
448 InsertInset(pos, minibuffer_inset);
455 void LyXParagraph::Clear()
460 pagebreak_top = false;
461 pagebreak_bottom = false;
463 added_space_top = VSpace(VSpace::NONE);
464 added_space_bottom = VSpace(VSpace::NONE);
466 align = LYX_ALIGN_LAYOUT;
470 pextra_type = PEXTRA_NONE;
471 pextra_width.clear();
472 pextra_widthp.clear();
473 pextra_alignment = MINIPAGE_ALIGN_TOP;
474 pextra_hfill = false;
475 pextra_start_minipage = false;
478 labelwidthstring.clear();
482 start_of_appendix = false;
486 // the destructor removes the new paragraph from the list
487 LyXParagraph::~LyXParagraph()
490 previous->next = next;
492 next->previous = previous;
494 for (InsetList::iterator it = insetlist.begin();
495 it != insetlist.end(); ++it) {
499 /* table stuff -- begin*/
501 /* table stuff -- end*/
508 void LyXParagraph::Erase(LyXParagraph::size_type pos)
510 // > because last is the next unused position, and you can
511 // use it if you want
513 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
514 NextAfterFootnote()->Erase(pos - text.size() - 1);
516 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
517 "position does not exist." << endl;
520 if (pos < size()) { // last is free for insertation, but should be empty
521 // if it is an inset, delete the inset entry
522 if (text[pos] == LyXParagraph::META_INSET) {
524 for (InsetList::iterator it = insetlist.begin();
525 it != insetlist.end(); ++it) {
526 if ((*it).pos == pos) {
533 text.erase(text.begin() + pos);
534 // Erase entries in the tables.
535 for (FontList::iterator it = fontlist.begin();
536 it != fontlist.end(); ++it) {
537 if (pos >= (*it).pos && pos <= (*it).pos_end) {
538 if ((*it).pos == (*it).pos_end) {
539 // If it is a multi-character font
540 // entry, we just make it smaller
541 // (see update below), otherwise we
548 // Update all other entries.
549 for (FontList::iterator it = fontlist.begin();
550 it != fontlist.end(); ++it) {
553 if ((*it).pos_end >= pos)
557 // Update the inset table.
558 for (InsetList::iterator it = insetlist.begin();
559 it != insetlist.end(); ++it) {
564 lyxerr << "ERROR (LyXParagraph::Erase): "
565 "can't erase non-existant char." << endl;
570 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
572 // > because last is the next unused position, and you can
573 // use it if you want
576 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
577 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
580 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
581 "position does not exist." << endl;
584 text.insert(text.begin() + pos, c);
585 // Update the font table.
586 for (FontList::iterator it = fontlist.begin();
587 it != fontlist.end(); ++it) {
588 if ((*it).pos >= pos)
590 if ((*it).pos_end >= pos)
594 // Update the inset table.
595 for (InsetList::iterator it = insetlist.begin();
596 it != insetlist.end(); ++it) {
597 if ((*it).pos >= pos)
603 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
606 // > because last is the next unused position, and you can
607 // use it if you want
610 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
612 ->InsertInset(pos - text.size() - 1, inset);
614 lyxerr << "ERROR (LyXParagraph::InsertInset): "
615 "position does not exist: " << pos << endl;
618 if (text[pos] != LyXParagraph::META_INSET) {
619 lyxerr << "ERROR (LyXParagraph::InsertInset): "
620 "there is no LyXParagraph::META_INSET" << endl;
625 // Add a new entry in the inset table.
626 InsetList::iterator it =
627 insetlist.insert(insetlist.begin(), InsetTable());
634 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
638 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
639 return NextAfterFootnote()
640 ->GetInset(pos - text.size() - 1);
642 lyxerr << "ERROR (LyXParagraph::GetInset): "
643 "position does not exist: "
649 for (InsetList::iterator it = insetlist.begin();
650 it != insetlist.end(); ++it) {
651 if ((*it).pos == pos) {
655 lyxerr << "ERROR (LyXParagraph::GetInset): "
656 "Inset does not exist: " << pos << endl;
657 text[pos] = ' '; // WHY!!! does this set the pos to ' '????
658 // Did this commenting out introduce a bug? So far I have not
659 // see any, please enlighten me. (Lgb)
660 // My guess is that since the inset does not exist, we might
661 // as well replace it with a space to prevent craches. (Asger)
666 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
670 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
671 return NextAfterFootnote()
672 ->GetInset(pos - text.size() - 1);
674 lyxerr << "ERROR (LyXParagraph::GetInset): "
675 "position does not exist: "
681 for (InsetList::const_iterator cit = insetlist.begin();
682 cit != insetlist.end(); ++cit) {
683 if ((*cit).pos == pos) {
687 lyxerr << "ERROR (LyXParagraph::GetInset): "
688 "Inset does not exist: " << pos << endl;
689 //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
690 // Did this commenting out introduce a bug? So far I have not
691 // see any, please enlighten me. (Lgb)
692 // My guess is that since the inset does not exist, we might
693 // as well replace it with a space to prevent craches. (Asger)
698 // Gets uninstantiated font setting at position.
699 // Optimized after profiling. (Asger)
700 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos) const
703 for (FontList::const_iterator cit = fontlist.begin();
704 cit != fontlist.end(); ++cit) {
705 if (pos >= (*cit).pos && pos <= (*cit).pos_end)
709 // > because last is the next unused position, and you can
710 // use it if you want
711 else if (pos > size()) {
713 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
714 return NextAfterFootnote()
715 ->GetFontSettings(pos - text.size() - 1);
717 // Why is it an error to ask for the font of a
718 // position that does not exist? Would it be
719 // enough for this to be enabled on debug?
720 // We want strict error checking, but it's ok to only
721 // have it when debugging. (Asger)
722 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
723 "position does not exist. "
724 << pos << " (" << static_cast<int>(pos)
728 return GetFontSettings(pos - 1);
730 return LyXFont(LyXFont::ALL_INHERIT);
734 // Gets the fully instantiated font at a given position in a paragraph
735 // This is basically the same function as LyXText::GetFont() in text2.C.
736 // The difference is that this one is used for generating the LaTeX file,
737 // and thus cosmetic "improvements" are disallowed: This has to deliver
738 // the true picture of the buffer. (Asger)
739 // If position is -1, we get the layout font of the paragraph.
740 // If position is -2, we get the font of the manual label of the paragraph.
741 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos) const
744 LyXLayout const & layout =
745 textclasslist.Style(current_view->buffer()->params.textclass,
747 LyXParagraph::size_type main_body = 0;
748 if (layout.labeltype == LABEL_MANUAL)
749 main_body = BeginningOfMainBody();
754 layoutfont = layout.labelfont;
756 layoutfont = layout.font;
757 tmpfont = GetFontSettings(pos);
758 tmpfont.realize(layoutfont);
760 // process layoutfont for pos == -1 and labelfont for pos < -1
762 tmpfont = layout.font;
764 tmpfont = layout.labelfont;
765 if (getParDirection() == LYX_DIR_RIGHT_TO_LEFT)
766 tmpfont.setDirection(LyXFont::RTL_DIR);
769 // check for environment font information
770 char par_depth = GetDepth();
771 LyXParagraph const * par = this;
772 while (par && par_depth && !tmpfont.resolved()) {
773 par = par->DepthHook(par_depth - 1);
775 tmpfont.realize(textclasslist.
776 Style(current_view->buffer()->params.textclass,
777 par->GetLayout()).font);
778 par_depth = par->GetDepth();
782 tmpfont.realize(textclasslist
783 .TextClass(current_view->buffer()->params.textclass)
789 /// Returns the height of the highest font in range
791 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
792 LyXParagraph::size_type endpos) const
794 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
795 for (FontList::const_iterator cit = fontlist.begin();
796 cit != fontlist.end(); ++cit) {
797 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
798 LyXFont::FONT_SIZE size = (*cit).font.size();
799 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
807 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
814 // > because last is the next unused position, and you can
815 // use it if you want
816 else if (pos > size()) {
817 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
818 return NextAfterFootnote()
819 ->GetChar(pos - text.size() - 1);
821 lyxerr << "ERROR (LyXParagraph::GetChar): "
822 "position does not exist."
823 << pos << " (" << static_cast<int>(pos)
825 // Assert(false); // This triggers sometimes...
830 // We should have a footnote environment.
831 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
832 // Notice that LyX does request the
833 // last char from time to time. (Asger)
834 //lyxerr << "ERROR (LyXParagraph::GetChar): "
835 // "expected footnote." << endl;
838 switch (next->footnotekind) {
839 case LyXParagraph::FOOTNOTE:
840 return LyXParagraph::META_FOOTNOTE;
841 case LyXParagraph::MARGIN:
842 return LyXParagraph::META_MARGIN;
843 case LyXParagraph::FIG:
844 case LyXParagraph::WIDE_FIG:
845 return LyXParagraph::META_FIG;
846 case LyXParagraph::TAB:
847 case LyXParagraph::WIDE_TAB:
848 return LyXParagraph::META_TAB;
849 case LyXParagraph::ALGORITHM:
850 return LyXParagraph::META_ALGORITHM;
852 return '\0'; // to shut up gcc
857 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
864 // > because last is the next unused position, and you can
865 // use it if you want
866 else if (pos > size()) {
867 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
868 return NextAfterFootnote()
869 ->GetChar(pos - text.size() - 1);
871 lyxerr << "ERROR (LyXParagraph::GetChar const): "
872 "position does not exist."
873 << pos << " (" << static_cast<int>(pos)
879 // We should have a footnote environment.
880 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
881 // Notice that LyX does request the
882 // last char from time to time. (Asger)
883 //lyxerr << "ERROR (LyXParagraph::GetChar): "
884 // "expected footnote." << endl;
887 switch (next->footnotekind) {
888 case LyXParagraph::FOOTNOTE:
889 return LyXParagraph::META_FOOTNOTE;
890 case LyXParagraph::MARGIN:
891 return LyXParagraph::META_MARGIN;
892 case LyXParagraph::FIG:
893 case LyXParagraph::WIDE_FIG:
894 return LyXParagraph::META_FIG;
895 case LyXParagraph::TAB:
896 case LyXParagraph::WIDE_TAB:
897 return LyXParagraph::META_TAB;
898 case LyXParagraph::ALGORITHM:
899 return LyXParagraph::META_ALGORITHM;
901 return '\0'; // to shut up gcc
906 // return an string of the current word, and the end of the word in lastpos.
907 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
911 // the current word is defined as starting at the first character
912 // from the immediate left of lastpospos which meets the definition
913 // of IsLetter(), continuing to the last character to the right
914 // of this meeting IsLetter.
920 // move back until we have a letter
922 //there's no real reason to have firstpos & lastpos as
923 //separate variables as this is written, but maybe someon
924 // will want to return firstpos in the future.
926 //since someone might have typed a punctuation first
927 int firstpos = lastpos;
929 while ((firstpos >= 0) && !IsLetter(firstpos))
932 // now find the beginning by looking for a nonletter
934 while ((firstpos>= 0) && IsLetter(firstpos))
937 // the above is now pointing to the preceeding non-letter
941 // so copy characters into theword until we get a nonletter
942 // note that this can easily exceed lastpos, wich means
943 // that if used in the middle of a word, the whole word
946 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
953 LyXParagraph::size_type LyXParagraph::Last() const
955 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
956 return text.size() + NextAfterFootnote()->Last() + 1;
957 // the 1 is the symbol
964 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
966 // > because last is the next unused position, and you can
967 // use it if you want
970 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
971 return NextAfterFootnote()
972 ->ParFromPos(pos - text.size() - 1);
974 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
975 "position does not exist." << endl;
982 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
984 // > because last is the next unused position, and you can
985 // use it if you want
988 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
989 return NextAfterFootnote()
990 ->PositionInParFromPos(pos - text.size() - 1);
993 "ERROR (LyXParagraph::PositionInParFromPos): "
994 "position does not exist." << endl;
1002 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
1003 LyXFont const & font)
1005 // > because last is the next unused position, and you can
1006 // use it if you want
1009 next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1010 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1013 lyxerr << "ERROR (LyXParagraph::SetFont): "
1014 "position does not exist." << endl;
1018 LyXFont patternfont(LyXFont::ALL_INHERIT);
1020 // First, reduce font against layout/label font
1021 // Update: The SetCharFont() routine in text2.C already
1022 // reduces font, so we don't need to do that here. (Asger)
1023 // No need to simplify this because it will disappear
1024 // in a new kernel. (Asger)
1025 // Next search font table
1026 FontList::iterator tmp = fontlist.begin();
1027 for (; tmp != fontlist.end(); ++tmp) {
1028 if (pos >= (*tmp).pos && pos <= (*tmp).pos_end) {
1032 if (tmp == fontlist.end()) { // !found
1033 // if we did not find a font entry, but if the font at hand
1034 // is the same as default, we just forget it
1035 if (font == patternfont) return;
1037 // ok, we did not find a font entry. But maybe there is exactly
1038 // the needed font ientry one position left
1039 FontList::iterator tmp2 = fontlist.begin();
1040 for (; tmp2 != fontlist.end(); ++tmp2) {
1041 if (pos - 1 >= (*tmp2).pos
1042 && pos - 1 <= (*tmp2).pos_end)
1045 if (tmp2 != fontlist.end()) {
1046 // ok there is one, maybe it is exactly
1048 if ((*tmp2).font == font) {
1049 // put the position under the font
1054 // Add a new entry in the
1055 // fontlist for the position
1059 ft.font = font; // or patternfont
1060 // It seems that using font instead of patternfont here
1061 // fixes all the problems. This also surfaces a "bug" in
1063 fontlist.insert(fontlist.begin(), ft);
1064 } else if ((*tmp).pos != (*tmp).pos_end) { // we found a font entry. maybe we have to split it and create a new one.
1066 // more than one character
1067 if (pos == (*tmp).pos) {
1068 // maybe we should enlarge the left fonttable
1069 FontList::iterator tmp2 = fontlist.begin();
1070 for (; tmp2 != fontlist.end(); ++tmp2) {
1071 if (pos - 1 >= (*tmp2).pos
1072 && pos - 1 <= (*tmp2).pos_end)
1075 // Is there is one, and is it exactly
1077 if (tmp2 != fontlist.end() &&
1078 (*tmp2).font == font) {
1079 // Put the position under the font
1085 // Add a new entry in the
1086 // fontlist for the position
1089 ft.pos_end = (*tmp).pos_end;
1090 ft.font = (*tmp).font;
1091 (*tmp).pos_end = pos;
1093 fontlist.insert(fontlist.begin(), ft);
1094 } else if (pos == (*tmp).pos_end) {
1095 // Add a new entry in the
1096 // fontlist for the position
1098 ft.pos = (*tmp).pos;
1099 ft.pos_end = (*tmp).pos_end - 1;
1100 ft.font = (*tmp).font;
1101 (*tmp).pos = (*tmp).pos_end;
1103 fontlist.insert(fontlist.begin(), ft);
1105 // Add a new entry in the
1106 // fontlist for the position
1108 ft.pos = (*tmp).pos;
1109 ft.pos_end = pos - 1;
1110 ft.font = (*tmp).font;
1114 ft2.pos_end = (*tmp).pos_end;
1115 ft2.font = (*tmp).font;
1118 (*tmp).pos_end = pos;
1121 fontlist.insert(fontlist.begin(), ft);
1122 fontlist.insert(fontlist.begin(), ft2);
1130 // This function is able to hide closed footnotes.
1131 LyXParagraph * LyXParagraph::Next()
1133 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1134 LyXParagraph * tmp = next;
1136 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1138 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1139 return tmp->Next(); /* there can be more than one
1140 footnote in a logical
1143 return next; // This should never happen!
1149 LyXParagraph * LyXParagraph::NextAfterFootnote()
1151 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1152 LyXParagraph * tmp = next;
1153 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1155 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1156 return tmp; /* there can be more than one footnote
1157 in a logical paragraph */
1159 return next; // This should never happen!
1165 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1167 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1168 LyXParagraph * tmp = next;
1169 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1171 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1172 return tmp; /* there can be more than one footnote
1173 in a logical paragraph */
1175 return next; // This should never happen!
1181 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1184 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1186 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1187 tmp = tmp->previous;
1188 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1189 return tmp; /* there can be more than one footnote
1190 in a logical paragraph */
1192 return previous; // This should never happen!
1198 LyXParagraph * LyXParagraph::LastPhysicalPar()
1200 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1203 LyXParagraph * tmp = this;
1205 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1206 tmp = tmp->NextAfterFootnote();
1213 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1217 LyXParagraph * tmppar = this;
1221 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1222 tmppar = tmppar->previous;
1231 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1235 LyXParagraph const * tmppar = this;
1239 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1240 tmppar = tmppar->previous;
1249 // This function is able to hide closed footnotes.
1250 LyXParagraph * LyXParagraph::Previous()
1252 LyXParagraph * tmp = previous;
1257 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1258 tmp = tmp->previous;
1260 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1261 tmp = tmp->previous;
1262 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1263 return tmp->next->Previous();
1272 // This function is able to hide closed footnotes.
1273 LyXParagraph const * LyXParagraph::Previous() const
1275 LyXParagraph * tmp = previous;
1280 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1281 tmp = tmp->previous;
1283 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1284 tmp = tmp->previous;
1285 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1286 return tmp->next->Previous();
1295 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1298 size_type i, pos_end, pos_first;
1299 // create a new paragraph
1300 LyXParagraph * par = ParFromPos(pos);
1301 LyXParagraph * firstpar = FirstPhysicalPar();
1303 LyXParagraph * tmp = new LyXParagraph(par);
1305 tmp->footnoteflag = footnoteflag;
1306 tmp->footnotekind = footnotekind;
1308 // this is an idea for a more userfriendly layout handling, I will
1309 // see what the users say
1311 // layout stays the same with latex-environments
1313 tmp->SetOnlyLayout(firstpar->layout);
1314 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1317 if (Last() > pos || !Last() || flag == 2) {
1318 tmp->SetOnlyLayout(firstpar->layout);
1319 tmp->align = firstpar->align;
1320 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1322 tmp->line_bottom = firstpar->line_bottom;
1323 firstpar->line_bottom = false;
1324 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1325 firstpar->pagebreak_bottom = false;
1326 tmp->added_space_bottom = firstpar->added_space_bottom;
1327 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1329 tmp->depth = firstpar->depth;
1330 tmp->noindent = firstpar->noindent;
1332 // copy everything behind the break-position
1333 // to the new paragraph
1335 while (ParFromPos(pos_first) != par)
1338 pos_end = pos_first + par->text.size() - 1;
1339 // The constructor has already reserved 500 elements
1340 //if (pos_end > pos)
1341 // tmp->text.reserve(pos_end - pos);
1343 for (i = pos; i <= pos_end; ++i) {
1344 par->CutIntoMinibuffer(i - pos_first);
1345 tmp->InsertFromMinibuffer(i - pos);
1347 tmp->text.resize(tmp->text.size());
1348 for (i = pos_end; i >= pos; --i)
1349 par->Erase(i - pos_first);
1351 par->text.resize(par->text.size());
1354 // just an idea of me
1356 tmp->line_top = firstpar->line_top;
1357 tmp->pagebreak_top = firstpar->pagebreak_top;
1358 tmp->added_space_top = firstpar->added_space_top;
1359 tmp->bibkey = firstpar->bibkey;
1361 // layout stays the same with latex-environments
1363 firstpar->SetOnlyLayout(tmp->layout);
1364 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1365 firstpar->depth = tmp->depth;
1371 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1373 par = par->FirstPhysicalPar();
1374 footnoteflag = par->footnoteflag;
1375 footnotekind = par->footnotekind;
1377 layout = par->layout;
1378 align = par-> align;
1379 SetLabelWidthString(par->labelwidthstring);
1381 line_bottom = par->line_bottom;
1382 pagebreak_bottom = par->pagebreak_bottom;
1383 added_space_bottom = par->added_space_bottom;
1385 line_top = par->line_top;
1386 pagebreak_top = par->pagebreak_top;
1387 added_space_top = par->added_space_top;
1389 pextra_type = par->pextra_type;
1390 pextra_width = par->pextra_width;
1391 pextra_widthp = par->pextra_widthp;
1392 pextra_alignment = par->pextra_alignment;
1393 pextra_hfill = par->pextra_hfill;
1394 pextra_start_minipage = par->pextra_start_minipage;
1396 noindent = par->noindent;
1401 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1403 LyXParagraph * tmppar = this;
1406 && tmppar->previous->footnoteflag ==
1407 LyXParagraph::CLOSED_FOOTNOTE)
1408 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1409 tmppar = tmppar->previous;
1412 return this; // This should never happen!
1418 LyXParagraph * LyXParagraph::Clone() const
1420 // create a new paragraph
1421 LyXParagraph * result = new LyXParagraph;
1423 result->MakeSameLayout(this);
1425 // this is because of the dummy layout of the paragraphs that
1427 result->layout = layout;
1429 /* table stuff -- begin*/
1431 result->table = table->Clone();
1434 /* table stuff -- end*/
1437 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1440 // copy everything behind the break-position to the new paragraph
1442 for (size_type i = 0; i < size(); ++i) {
1443 CopyIntoMinibuffer(i);
1444 result->InsertFromMinibuffer(i);
1446 result->text.resize(result->text.size());
1451 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1453 par = par->FirstPhysicalPar();
1456 par->footnoteflag == footnoteflag &&
1457 par->footnotekind == footnotekind &&
1459 par->layout == layout &&
1461 par->align == align &&
1463 par->line_bottom == line_bottom &&
1464 par->pagebreak_bottom == pagebreak_bottom &&
1465 par->added_space_bottom == added_space_bottom &&
1467 par->line_top == line_top &&
1468 par->pagebreak_top == pagebreak_top &&
1469 par->added_space_top == added_space_top &&
1471 par->pextra_type == pextra_type &&
1472 par->pextra_width == pextra_width &&
1473 par->pextra_widthp == pextra_widthp &&
1474 par->pextra_alignment == pextra_alignment &&
1475 par->pextra_hfill == pextra_hfill &&
1476 par->pextra_start_minipage == pextra_start_minipage &&
1478 par->table == table && // what means: NO TABLE AT ALL
1480 par->noindent == noindent &&
1481 par->depth == depth);
1485 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
1487 // create a new paragraph
1488 LyXParagraph * par = ParFromPos(pos);
1490 LyXParagraph * tmp = new LyXParagraph(par);
1492 tmp->MakeSameLayout(par);
1494 // When can pos < Last()?
1495 // I guess pos == Last() is possible.
1497 // copy everything behind the break-position to the new
1499 size_type pos_first = 0;
1500 while (ParFromPos(pos_first) != par)
1502 size_type pos_end = pos_first + par->text.size() - 1;
1503 // make sure there is enough memory for the now larger
1504 // paragraph. This is not neccessary, because
1505 // InsertFromMinibuffer will enlarge the memory (it uses
1506 // InsertChar of course). But doing it by hand
1507 // is MUCH faster! (only one time, not thousend times!!)
1508 // Not needed since the constructor aleady have
1509 // reserved 500 elements in text.
1510 //if (pos_end > pos)
1511 // tmp->text.reserve(pos_end - pos);
1513 for (size_type i = pos; i <= pos_end; ++i) {
1514 par->CutIntoMinibuffer(i - pos_first);
1515 tmp->InsertFromMinibuffer(i - pos);
1517 tmp->text.resize(tmp->text.size());
1518 for (size_type i = pos_end; i >= pos; --i)
1519 par->Erase(i - pos_first);
1521 par->text.resize(par->text.size());
1526 // Be carefull, this does not make any check at all.
1527 void LyXParagraph::PasteParagraph()
1529 // copy the next paragraph to this one
1530 LyXParagraph * the_next = Next();
1532 LyXParagraph * firstpar = FirstPhysicalPar();
1534 // first the DTP-stuff
1535 firstpar->line_bottom = the_next->line_bottom;
1536 firstpar->added_space_bottom = the_next->added_space_bottom;
1537 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1539 size_type pos_end = the_next->text.size() - 1;
1540 size_type pos_insert = Last();
1542 // ok, now copy the paragraph
1543 for (size_type i = 0; i <= pos_end; ++i) {
1544 the_next->CutIntoMinibuffer(i);
1545 InsertFromMinibuffer(pos_insert + i);
1548 // delete the next paragraph
1553 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1555 LyXParagraph * par = ParFromPos(pos);
1557 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1558 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1564 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1566 LyXParagraph * par = ParFromPos(pos);
1568 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1569 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1575 LyXTextClass::size_type LyXParagraph::GetLayout() const
1577 return FirstPhysicalPar()->layout;
1581 char LyXParagraph::GetDepth() const
1583 return FirstPhysicalPar()->depth;
1587 char LyXParagraph::GetAlign() const
1589 return FirstPhysicalPar()->align;
1593 string LyXParagraph::GetLabestring() const
1595 return FirstPhysicalPar()->labelstring;
1599 int LyXParagraph::GetFirstCounter(int i) const
1601 return FirstPhysicalPar()->counter_[i];
1605 // the next two functions are for the manual labels
1606 string LyXParagraph::GetLabelWidthString() const
1608 if (!FirstPhysicalPar()->labelwidthstring.empty())
1609 return FirstPhysicalPar()->labelwidthstring;
1611 return _("Senseless with this layout!");
1615 void LyXParagraph::SetLabelWidthString(string const & s)
1617 LyXParagraph * par = FirstPhysicalPar();
1619 par->labelwidthstring = s;
1623 void LyXParagraph::SetOnlyLayout(LyXTextClass::size_type new_layout)
1625 LyXParagraph * par = FirstPhysicalPar();
1626 LyXParagraph * ppar = 0;
1627 LyXParagraph * npar = 0;
1629 par->layout = new_layout;
1630 /* table stuff -- begin*/
1633 /* table stuff -- end*/
1634 if (par->pextra_type == PEXTRA_NONE) {
1635 if (par->Previous()) {
1636 ppar = par->Previous()->FirstPhysicalPar();
1639 && (ppar->depth > par->depth))
1640 ppar = ppar->Previous()->FirstPhysicalPar();
1643 npar = par->Next()->NextAfterFootnote();
1646 && (npar->depth > par->depth))
1647 npar = npar->Next()->NextAfterFootnote();
1649 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1651 p1 = ppar->pextra_width,
1652 p2 = ppar->pextra_widthp;
1653 ppar->SetPExtraType(ppar->pextra_type,
1654 p1.c_str(), p2.c_str());
1656 if ((par->pextra_type == PEXTRA_NONE) &&
1657 npar && (npar->pextra_type != PEXTRA_NONE)) {
1659 p1 = npar->pextra_width,
1660 p2 = npar->pextra_widthp;
1661 npar->SetPExtraType(npar->pextra_type,
1662 p1.c_str(), p2.c_str());
1668 void LyXParagraph::SetLayout(LyXTextClass::size_type new_layout)
1671 * par = FirstPhysicalPar(),
1675 par->layout = new_layout;
1676 par->labelwidthstring.clear();
1677 par->align = LYX_ALIGN_LAYOUT;
1678 par->added_space_top = VSpace(VSpace::NONE);
1679 par->added_space_bottom = VSpace(VSpace::NONE);
1680 /* table stuff -- begin*/
1683 /* table stuff -- end*/
1684 if (par->pextra_type == PEXTRA_NONE) {
1685 if (par->Previous()) {
1686 ppar = par->Previous()->FirstPhysicalPar();
1689 && (ppar->depth > par->depth))
1690 ppar = ppar->Previous()->FirstPhysicalPar();
1693 npar = par->Next()->NextAfterFootnote();
1696 && (npar->depth > par->depth))
1697 npar = npar->Next()->NextAfterFootnote();
1699 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1701 p1 = ppar->pextra_width,
1702 p2 = ppar->pextra_widthp;
1703 ppar->SetPExtraType(ppar->pextra_type,
1704 p1.c_str(), p2.c_str());
1706 if ((par->pextra_type == PEXTRA_NONE) &&
1707 npar && (npar->pextra_type != PEXTRA_NONE)) {
1709 p1 = npar->pextra_width,
1710 p2 = npar->pextra_widthp;
1711 npar->SetPExtraType(npar->pextra_type,
1712 p1.c_str(), p2.c_str());
1718 // if the layout of a paragraph contains a manual label, the beginning of the
1719 // main body is the beginning of the second word. This is what the par-
1720 // function returns. If the layout does not contain a label, the main
1721 // body always starts with position 0. This differentiation is necessary,
1722 // because there cannot be a newline or a blank <= the beginning of the
1723 // main body in TeX.
1725 int LyXParagraph::BeginningOfMainBody() const
1727 if (FirstPhysicalPar() != this)
1730 // Unroll the first two cycles of the loop
1731 // and remember the previous character to
1732 // remove unnecessary GetChar() calls
1735 && GetChar(i) != LyXParagraph::META_NEWLINE
1738 char previous_char = 0, temp = 0;
1740 && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1741 // Yes, this ^ is supposed to be "= " not "=="
1744 && previous_char != ' '
1745 && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1747 previous_char = temp;
1752 if (i == 0 && i == size() &&
1753 !(footnoteflag == LyXParagraph::NO_FOOTNOTE
1754 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1755 ++i; /* the cursor should not jump
1756 * to the main body if there
1762 LyXParagraph * LyXParagraph::DepthHook(int deth)
1764 LyXParagraph * newpar = this;
1769 newpar = newpar->FirstPhysicalPar()->Previous();
1770 } while (newpar && newpar->GetDepth() > deth
1771 && newpar->footnoteflag == footnoteflag);
1774 if (Previous() || GetDepth())
1775 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1779 return newpar->FirstPhysicalPar();
1783 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
1785 LyXParagraph const * newpar = this;
1790 newpar = newpar->FirstPhysicalPar()->Previous();
1791 } while (newpar && newpar->GetDepth() > deth
1792 && newpar->footnoteflag == footnoteflag);
1795 if (Previous() || GetDepth())
1796 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1800 return newpar->FirstPhysicalPar();
1804 int LyXParagraph::AutoDeleteInsets()
1806 vector<size_type> tmpvec;
1808 for (InsetList::iterator it = insetlist.begin();
1809 it != insetlist.end(); ++it) {
1810 if ((*it).inset && (*it).inset->AutoDelete()) {
1811 tmpvec.push_back((*it).pos);
1815 for (vector<size_type>::const_iterator cit = tmpvec.begin();
1816 cit != tmpvec.end(); ++cit) {
1823 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
1825 InsetList::iterator it2 = insetlist.end();
1826 for (InsetList::iterator it = insetlist.begin();
1827 it != insetlist.end(); ++it) {
1828 if ((*it).pos >= pos) {
1829 if (it2 == insetlist.end() || (*it).pos < (*it2).pos)
1833 if (it2 != insetlist.end()) {
1835 return (*it2).inset;
1841 // returns -1 if inset not found
1842 int LyXParagraph::GetPositionOfInset(Inset * inset) const
1845 for (InsetList::const_iterator cit = insetlist.begin();
1846 cit != insetlist.end(); ++cit) {
1847 if ((*cit).inset == inset) {
1851 // Think about footnotes.
1852 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
1853 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1855 NextAfterFootnote()->GetPositionOfInset(inset);
1857 return text.size() + 1 + further;
1863 void LyXParagraph::readSimpleWholeFile(istream & is)
1869 InsertChar(text.size(), c);
1874 #ifdef USE_OSTREAM_ONLY
1875 LyXParagraph * LyXParagraph::TeXOnePar(ostream & os, TexRow & texrow,
1876 ostream & foot, TexRow & foot_texrow,
1879 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
1880 LyXParagraph * par = next;
1881 LyXLayout const & style =
1882 textclasslist.Style(current_view->buffer()->params.textclass,
1885 bool further_blank_line = false;
1887 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1889 if (start_of_appendix) {
1890 os << "\\appendix\n";
1894 if (tex_code_break_column && style.isCommand()){
1899 if (pagebreak_top) {
1901 further_blank_line = true;
1903 if (added_space_top.kind() != VSpace::NONE) {
1904 os << added_space_top.asLatexCommand(current_view->buffer()->params);
1905 further_blank_line = true;
1909 os << "\\lyxline{\\" << getFont(0).latexSize() << '}'
1910 << "\\vspace{-1\\parskip}";
1911 further_blank_line = true;
1914 if (further_blank_line){
1919 LyXDirection direction = getParDirection();
1920 LyXDirection global_direction =
1921 current_view->buffer()->params.getDocumentDirection();
1922 if (direction != global_direction) {
1923 if (direction == LYX_DIR_LEFT_TO_RIGHT)
1924 os << "\\unsethebrew\n";
1926 os << "\\sethebrew\n";
1931 switch (style.latextype) {
1934 << style.latexname()
1935 << style.latexparam();
1937 case LATEX_ITEM_ENVIRONMENT:
1939 bibkey->Latex(os, false, false);
1943 case LATEX_LIST_ENVIRONMENT:
1950 bool need_par = SimpleTeXOnePar(os, texrow);
1952 // Spit out footnotes
1953 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
1954 && par->footnoteflag != footnoteflag) {
1955 par = par->TeXFootnote(os, texrow,
1956 foot, foot_texrow, foot_count,
1958 par->SimpleTeXOnePar(os, texrow);
1962 // Make sure that \\par is done with the font of the last
1963 // character if this has another size as the default.
1964 // This is necessary because LaTeX (and LyX on the screen)
1965 // calculates the space between the baselines according
1966 // to this font. (Matthias)
1967 LyXFont font = getFont(Last() - 1);
1969 if (style.resfont.size() != font.size()) {
1975 } else if (textclasslist.Style(current_view->buffer()->params.textclass,
1976 GetLayout()).isCommand()){
1977 if (style.resfont.size() != font.size()) {
1983 } else if (style.resfont.size() != font.size()){
1984 os << "{\\" << font.latexSize() << " \\par}";
1987 if (direction != global_direction)
1988 if (direction == LYX_DIR_LEFT_TO_RIGHT)
1989 os << "\\sethebrew";
1991 os << "\\unsethebrew";
1993 switch (style.latextype) {
1994 case LATEX_ITEM_ENVIRONMENT:
1995 case LATEX_LIST_ENVIRONMENT:
1996 if (par && (depth < par->depth)) {
2001 case LATEX_ENVIRONMENT:
2002 // if its the last paragraph of the current environment
2003 // skip it otherwise fall through
2005 && (par->layout != layout
2006 || par->depth != depth
2007 || par->pextra_type != pextra_type))
2010 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2011 && footnotekind != LyXParagraph::FOOTNOTE
2012 && footnotekind != LyXParagraph::MARGIN
2016 // don't insert this if we would be adding it
2017 // before or after a table in a float. This
2018 // little trick is needed in order to allow
2019 // use of tables in \subfigures or \subtables.
2025 further_blank_line = false;
2027 os << "\\lyxline{\\" << getFont(Last() - 1).latexSize() << '}';
2028 further_blank_line = true;
2031 if (added_space_bottom.kind() != VSpace::NONE) {
2032 os << added_space_bottom.asLatexCommand(current_view->buffer()->params);
2033 further_blank_line = true;
2036 if (pagebreak_bottom) {
2038 further_blank_line = true;
2041 if (further_blank_line){
2046 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2047 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2052 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2056 LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow,
2057 string & foot, TexRow & foot_texrow,
2060 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
2061 LyXParagraph * par = next;
2062 LyXLayout const & style =
2063 textclasslist.Style(current_view->buffer()->params.textclass,
2066 bool further_blank_line = false;
2068 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
2070 if (start_of_appendix) {
2071 file += "\\appendix\n";
2075 if (tex_code_break_column && style.isCommand()){
2080 if (pagebreak_top) {
2081 file += "\\newpage";
2082 further_blank_line = true;
2084 if (added_space_top.kind() != VSpace::NONE) {
2085 file += added_space_top.asLatexCommand(current_view->buffer()->params);
2086 further_blank_line = true;
2090 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
2091 file += "\\vspace{-1\\parskip}";
2092 further_blank_line = true;
2095 if (further_blank_line){
2100 LyXDirection direction = getParDirection();
2101 LyXDirection global_direction =
2102 current_view->buffer()->params.getDocumentDirection();
2103 if (direction != global_direction) {
2104 if (direction == LYX_DIR_LEFT_TO_RIGHT)
2105 file += "\\unsethebrew\n";
2107 file += "\\sethebrew\n";
2112 switch (style.latextype) {
2115 file += style.latexname();
2116 file += style.latexparam();
2118 case LATEX_ITEM_ENVIRONMENT:
2120 #ifdef USE_OSTREAM_ONLY
2123 bibkey->Latex(ost, false);
2124 file += ost.str().c_str();
2127 bibkey->Latex(ost, false);
2129 char * tmp = ost.str();
2134 bibkey->Latex(file, false);
2139 case LATEX_LIST_ENVIRONMENT:
2146 bool need_par = SimpleTeXOnePar(file, texrow);
2148 // Spit out footnotes
2149 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2150 && par->footnoteflag != footnoteflag) {
2151 par = par->TeXFootnote(file, texrow,
2152 foot, foot_texrow, foot_count,
2154 par->SimpleTeXOnePar(file, texrow);
2158 // Make sure that \\par is done with the font of the last
2159 // character if this has another size as the default.
2160 // This is necessary because LaTeX (and LyX on the screen)
2161 // calculates the space between the baselines according
2162 // to this font. (Matthias)
2163 LyXFont font = getFont(Last()-1);
2165 if (style.resfont.size() != font.size()) {
2167 file += font.latexSize();
2171 } else if (textclasslist.Style(current_view->buffer()->params.textclass,
2172 GetLayout()).isCommand()){
2173 if (style.resfont.size() != font.size()) {
2175 file += font.latexSize();
2179 } else if (style.resfont.size() != font.size()){
2180 file += "{\\" + font.latexSize() + " \\par}";
2183 if (direction != global_direction)
2184 if (direction == LYX_DIR_LEFT_TO_RIGHT)
2185 file += "\\sethebrew";
2187 file += "\\unsethebrew";
2189 switch (style.latextype) {
2190 case LATEX_ITEM_ENVIRONMENT:
2191 case LATEX_LIST_ENVIRONMENT:
2192 if (par && (depth < par->depth)) {
2197 case LATEX_ENVIRONMENT:
2198 // if its the last paragraph of the current environment
2199 // skip it otherwise fall through
2201 && (par->layout != layout
2202 || par->depth != depth
2203 || par->pextra_type != pextra_type))
2206 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2207 && footnotekind != LyXParagraph::FOOTNOTE
2208 && footnotekind != LyXParagraph::MARGIN
2212 // don't insert this if we would be adding it
2213 // before or after a table in a float. This
2214 // little trick is needed in order to allow
2215 // use of tables in \subfigures or \subtables.
2221 further_blank_line = false;
2223 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2224 further_blank_line = true;
2227 if (added_space_bottom.kind() != VSpace::NONE) {
2228 file += added_space_bottom.asLatexCommand(current_view->buffer()->params);
2229 further_blank_line = true;
2232 if (pagebreak_bottom) {
2233 file += "\\newpage";
2234 further_blank_line = true;
2237 if (further_blank_line){
2242 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2243 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2248 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2254 // This one spits out the text of the paragraph
2255 #ifdef USE_OSTREAM_ONLY
2256 bool LyXParagraph::SimpleTeXOnePar(ostream & os, TexRow & texrow)
2258 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2261 return SimpleTeXOneTablePar(os, texrow);
2263 bool return_value = false;
2265 LyXLayout const & style =
2266 textclasslist.Style(current_view->buffer()->params.textclass,
2268 LyXFont basefont, last_font;
2270 // Maybe we have to create a optional argument.
2271 size_type main_body;
2272 if (style.labeltype != LABEL_MANUAL)
2275 main_body = BeginningOfMainBody();
2277 if (main_body > 0) {
2279 basefont = getFont(-2); // Get label font
2281 basefont = getFont(-1); // Get layout font
2289 if (style.isCommand()) {
2292 } else if (align != LYX_ALIGN_LAYOUT) {
2295 return_value = true;
2299 // Which font is currently active?
2300 LyXFont running_font(basefont);
2301 // Do we have an open font change?
2302 bool open_font = false;
2304 texrow.start(this, 0);
2306 for (size_type i = 0; i < size(); ++i) {
2308 // First char in paragraph or after label?
2309 if (i == main_body && !IsDummy()) {
2310 if (main_body > 0) {
2312 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2315 basefont = getFont(-1); // Now use the layout font
2316 running_font = basefont;
2320 if (style.isCommand()) {
2323 } else if (align != LYX_ALIGN_LAYOUT) {
2326 return_value = true;
2330 os << "\\noindent ";
2334 case LYX_ALIGN_NONE:
2335 case LYX_ALIGN_BLOCK:
2336 case LYX_ALIGN_LAYOUT:
2337 case LYX_ALIGN_SPECIAL: break;
2338 case LYX_ALIGN_LEFT:
2339 os << "\\raggedright ";
2342 case LYX_ALIGN_RIGHT:
2343 os << "\\raggedleft ";
2346 case LYX_ALIGN_CENTER:
2347 os << "\\centering ";
2355 // Fully instantiated font
2356 LyXFont font = getFont(i);
2357 last_font = running_font;
2359 // Spaces at end of font change are simulated to be
2360 // outside font change, i.e. we write "\textXX{text} "
2361 // rather than "\textXX{text }". (Asger)
2362 if (open_font && c == ' ' && i <= size() - 2
2363 && !getFont(i+1).equalExceptLatex(running_font)
2364 && !getFont(i+1).equalExceptLatex(font)) {
2365 font = getFont(i + 1);
2367 // We end font definition before blanks
2368 if (!font.equalExceptLatex(running_font) && open_font) {
2369 column += running_font.latexWriteEndChanges(os,
2371 (i == main_body-1) ? basefont : font);
2372 running_font = basefont;
2376 // Blanks are printed before start of fontswitch
2378 // Do not print the separation of the optional argument
2379 if (i != main_body - 1) {
2380 SimpleTeXBlanks(os, texrow, i,
2381 column, font, style);
2385 // Do we need to change font?
2386 if (!font.equalExceptLatex(running_font)
2387 && i != main_body-1) {
2388 column += font.latexWriteStartChanges(os, basefont,
2390 running_font = font;
2394 if (c == LyXParagraph::META_NEWLINE) {
2395 // newlines are handled differently here than
2396 // the default in SimpleTeXSpecialChars().
2397 if (!style.newline_allowed
2398 || font.latex() == LyXFont::ON) {
2402 column += running_font.latexWriteEndChanges(os, basefont, basefont);
2405 basefont = getFont(-1);
2406 running_font = basefont;
2407 if (font.family() ==
2408 LyXFont::TYPEWRITER_FAMILY) {
2414 texrow.start(this, i + 1);
2417 SimpleTeXSpecialChars(os, texrow,
2418 font, running_font, basefont,
2419 open_font, style, i, column, c);
2423 // If we have an open font definition, we have to close it
2425 running_font.latexWriteEndChanges(os, basefont, basefont);
2428 // Needed if there is an optional argument but no contents.
2429 if (main_body > 0 && main_body == size()) {
2431 return_value = false;
2434 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2435 return return_value;
2438 bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow)
2440 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2443 return SimpleTeXOneTablePar(file, texrow);
2445 bool return_value = false;
2447 LyXLayout const & style =
2448 textclasslist.Style(current_view->buffer()->params.textclass,
2450 LyXFont basefont, last_font;
2452 // Maybe we have to create a optional argument.
2453 size_type main_body;
2454 if (style.labeltype != LABEL_MANUAL)
2457 main_body = BeginningOfMainBody();
2459 if (main_body > 0) {
2461 basefont = getFont(-2); // Get label font
2463 basefont = getFont(-1); // Get layout font
2471 if (style.isCommand()) {
2474 } else if (align != LYX_ALIGN_LAYOUT) {
2477 return_value = true;
2481 // Which font is currently active?
2482 LyXFont running_font = basefont;
2483 // Do we have an open font change?
2484 bool open_font = false;
2486 texrow.start(this, 0);
2488 for (size_type i = 0; i < size(); ++i) {
2490 // First char in paragraph or after label?
2491 if (i == main_body && !IsDummy()) {
2492 if (main_body > 0) {
2494 column += running_font.latexWriteEndChanges(file, basefont, basefont);
2497 basefont = getFont(-1); // Now use the layout font
2498 running_font = basefont;
2502 if (style.isCommand()) {
2505 } else if (align != LYX_ALIGN_LAYOUT) {
2508 return_value = true;
2512 file += "\\noindent ";
2516 case LYX_ALIGN_NONE:
2517 case LYX_ALIGN_BLOCK:
2518 case LYX_ALIGN_LAYOUT:
2519 case LYX_ALIGN_SPECIAL: break;
2520 case LYX_ALIGN_LEFT:
2521 file += "\\raggedright ";
2524 case LYX_ALIGN_RIGHT:
2525 file += "\\raggedleft ";
2528 case LYX_ALIGN_CENTER:
2529 file += "\\centering ";
2537 // Fully instantiated font
2538 LyXFont font = getFont(i);
2539 last_font = running_font;
2541 // Spaces at end of font change are simulated to be
2542 // outside font change, i.e. we write "\textXX{text} "
2543 // rather than "\textXX{text }". (Asger)
2544 if (open_font && c == ' ' && i <= size() - 2
2545 && !getFont(i+1).equalExceptLatex(running_font)
2546 && !getFont(i+1).equalExceptLatex(font)) {
2547 font = getFont(i + 1);
2549 // We end font definition before blanks
2550 if (!font.equalExceptLatex(running_font) && open_font) {
2551 column += running_font.latexWriteEndChanges(file,
2553 (i == main_body-1) ? basefont : font);
2554 running_font = basefont;
2558 // Blanks are printed before start of fontswitch
2560 // Do not print the separation of the optional argument
2561 if (i != main_body - 1) {
2562 SimpleTeXBlanks(file, texrow, i,
2563 column, font, style);
2567 // Do we need to change font?
2568 if (!font.equalExceptLatex(running_font)
2569 && i != main_body-1) {
2570 column += font.latexWriteStartChanges(file, basefont, last_font);
2571 running_font = font;
2575 if (c == LyXParagraph::META_NEWLINE) {
2576 // newlines are handled differently here than
2577 // the default in SimpleTeXSpecialChars().
2578 if (!style.newline_allowed
2579 || font.latex() == LyXFont::ON) {
2583 column += running_font.latexWriteEndChanges(file, basefont, basefont);
2586 basefont = getFont(-1);
2587 running_font = basefont;
2588 if (font.family() ==
2589 LyXFont::TYPEWRITER_FAMILY) {
2595 texrow.start(this, i + 1);
2598 SimpleTeXSpecialChars(file, texrow,
2599 font, running_font, basefont,
2600 open_font, style, i, column, c);
2604 // If we have an open font definition, we have to close it
2606 running_font.latexWriteEndChanges(file, basefont, basefont);
2609 // Needed if there is an optional argument but no contents.
2610 if (main_body > 0 && main_body == size()) {
2612 return_value = false;
2615 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2616 return return_value;
2621 #ifdef USE_OSTREAM_ONLY
2622 // This one spits out the text of a table paragraph
2623 bool LyXParagraph::SimpleTeXOneTablePar(ostream & os, TexRow & texrow)
2625 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2627 bool return_value = false;
2629 LyXLayout const & style =
2630 textclasslist.Style(current_view->buffer()->params.textclass,
2634 if (!IsDummy()) { // it is dummy if it is in a float!!!
2635 if (style.isCommand()) {
2638 } else if (align != LYX_ALIGN_LAYOUT) {
2641 return_value = true;
2644 os << "\\noindent ";
2648 case LYX_ALIGN_NONE:
2649 case LYX_ALIGN_BLOCK:
2650 case LYX_ALIGN_LAYOUT:
2651 case LYX_ALIGN_SPECIAL: break;
2652 case LYX_ALIGN_LEFT:
2653 os << "\\raggedright ";
2656 case LYX_ALIGN_RIGHT:
2657 os << "\\raggedleft ";
2660 case LYX_ALIGN_CENTER:
2661 os << "\\centering ";
2667 LyXFont basefont = getFont(-1); // Get layout font
2668 // Which font is currently active?
2669 LyXFont running_font = basefont;
2671 // Do we have an open font change?
2672 bool open_font = false;
2673 int current_cell_number = -1;
2674 int tmp = table->TexEndOfCell(os, current_cell_number);
2675 for (; tmp > 0 ; --tmp)
2678 texrow.start(this, 0);
2680 for (size_type i = 0; i < size(); ++i) {
2681 char c = GetChar(i);
2682 if (table->IsContRow(current_cell_number + 1)) {
2683 if (c == LyXParagraph::META_NEWLINE)
2684 ++current_cell_number;
2689 // Fully instantiated font
2690 LyXFont font = getFont(i);
2691 last_font = running_font;
2693 // Spaces at end of font change are simulated to be
2694 // outside font change.
2695 // i.e. we write "\textXX{text} " rather than
2696 // "\textXX{text }". (Asger)
2697 if (open_font && c == ' ' && i <= size() - 2
2698 && getFont(i + 1) != running_font
2699 && getFont(i + 1) != font) {
2700 font = getFont(i + 1);
2703 // We end font definition before blanks
2704 if (font != running_font && open_font) {
2705 column += running_font.latexWriteEndChanges(os,
2708 running_font = basefont;
2711 // Blanks are printed before start of fontswitch
2713 SimpleTeXBlanks(os, texrow, i, column, font, style);
2715 // Do we need to change font?
2716 if (font != running_font) {
2717 column += font.latexWriteStartChanges(os, basefont,
2719 running_font = font;
2722 // Do we need to turn on LaTeX mode?
2723 if (font.latex() != running_font.latex()) {
2724 if (font.latex() == LyXFont::ON
2725 && style.needprotect) {
2730 if (c == LyXParagraph::META_NEWLINE) {
2731 // special case for inside a table
2732 // different from default case in
2733 // SimpleTeXSpecialChars()
2735 column += running_font
2736 .latexWriteEndChanges(os, basefont,
2740 basefont = getFont(-1);
2741 running_font = basefont;
2742 ++current_cell_number;
2743 if (table->CellHasContRow(current_cell_number) >= 0) {
2744 TeXContTableRows(os, i + 1,
2745 current_cell_number,
2748 // if this cell follow only ContRows till end don't
2749 // put the EndOfCell because it is put after the
2751 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2752 --current_cell_number;
2755 int tmp = table->TexEndOfCell(os,
2756 current_cell_number);
2759 } else if (tmp < 0) {
2765 texrow.start(this, i + 1);
2767 SimpleTeXSpecialChars(os, texrow,
2768 font, running_font, basefont,
2769 open_font, style, i, column, c);
2773 // If we have an open font definition, we have to close it
2775 running_font.latexWriteEndChanges(os, basefont, basefont);
2777 ++current_cell_number;
2778 tmp = table->TexEndOfCell(os, current_cell_number);
2779 for (; tmp > 0; --tmp)
2781 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2782 return return_value;
2785 // This one spits out the text of a table paragraph
2786 bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow)
2788 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2790 bool return_value = false;
2792 LyXLayout const & style =
2793 textclasslist.Style(current_view->buffer()->params.textclass,
2797 if (!IsDummy()) { // it is dummy if it is in a float!!!
2798 if (style.isCommand()) {
2801 } else if (align != LYX_ALIGN_LAYOUT) {
2804 return_value = true;
2807 file += "\\noindent ";
2811 case LYX_ALIGN_NONE:
2812 case LYX_ALIGN_BLOCK:
2813 case LYX_ALIGN_LAYOUT:
2814 case LYX_ALIGN_SPECIAL: break;
2815 case LYX_ALIGN_LEFT:
2816 file += "\\raggedright ";
2819 case LYX_ALIGN_RIGHT:
2820 file += "\\raggedleft ";
2823 case LYX_ALIGN_CENTER:
2824 file += "\\centering ";
2830 LyXFont basefont = getFont(-1); // Get layout font
2831 // Which font is currently active?
2832 LyXFont running_font = basefont;
2834 // Do we have an open font change?
2835 bool open_font = false;
2836 int current_cell_number = -1;
2837 int tmp = table->TexEndOfCell(file, current_cell_number);
2838 for (; tmp > 0 ; --tmp)
2841 texrow.start(this, 0);
2843 for (size_type i = 0; i < size(); ++i) {
2844 char c = GetChar(i);
2845 if (table->IsContRow(current_cell_number + 1)) {
2846 if (c == LyXParagraph::META_NEWLINE)
2847 ++current_cell_number;
2852 // Fully instantiated font
2853 LyXFont font = getFont(i);
2854 last_font = running_font;
2856 // Spaces at end of font change are simulated to be
2857 // outside font change.
2858 // i.e. we write "\textXX{text} " rather than
2859 // "\textXX{text }". (Asger)
2860 if (open_font && c == ' ' && i <= size() - 2
2861 && getFont(i+1) != running_font && getFont(i+1) != font) {
2862 font = getFont(i+1);
2865 // We end font definition before blanks
2866 if (font != running_font && open_font) {
2867 column += running_font.latexWriteEndChanges(file,
2869 running_font = basefont;
2872 // Blanks are printed before start of fontswitch
2874 SimpleTeXBlanks(file, texrow, i, column, font, style);
2876 // Do we need to change font?
2877 if (font != running_font) {
2878 column += font.latexWriteStartChanges(file, basefont, last_font);
2879 running_font = font;
2882 // Do we need to turn on LaTeX mode?
2883 if (font.latex() != running_font.latex()) {
2884 if (font.latex() == LyXFont::ON
2885 && style.needprotect) {
2886 file += "\\protect ";
2890 if (c == LyXParagraph::META_NEWLINE) {
2891 // special case for inside a table
2892 // different from default case in
2893 // SimpleTeXSpecialChars()
2895 column += running_font
2896 .latexWriteEndChanges(file, basefont, basefont);
2899 basefont = getFont(-1);
2900 running_font = basefont;
2901 ++current_cell_number;
2902 if (table->CellHasContRow(current_cell_number) >= 0) {
2903 TeXContTableRows(file, i + 1,
2904 current_cell_number,
2907 // if this cell follow only ContRows till end don't
2908 // put the EndOfCell because it is put after the
2910 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2911 --current_cell_number;
2914 int tmp = table->TexEndOfCell(file,
2915 current_cell_number);
2918 } else if (tmp < 0) {
2924 texrow.start(this, i + 1);
2926 SimpleTeXSpecialChars(file, texrow,
2927 font, running_font, basefont,
2928 open_font, style, i, column, c);
2932 // If we have an open font definition, we have to close it
2934 running_font.latexWriteEndChanges(file, basefont, basefont);
2936 ++current_cell_number;
2937 tmp = table->TexEndOfCell(file, current_cell_number);
2938 for (; tmp > 0; --tmp)
2940 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2941 return return_value;
2946 #ifdef USE_OSTREAM_ONLY
2947 // This one spits out the text off ContRows in tables
2948 bool LyXParagraph::TeXContTableRows(ostream & os,
2949 LyXParagraph::size_type i,
2950 int current_cell_number,
2951 int & column, TexRow & texrow)
2953 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2959 bool return_value = false;
2960 LyXLayout const & style =
2961 textclasslist.Style(current_view->buffer()->params.textclass,
2963 LyXFont basefont = getFont(-1); // Get layout font
2965 // Which font is currently active?
2966 LyXFont running_font = basefont;
2967 // Do we have an open font change?
2968 bool open_font = false;
2970 size_type lastpos = i;
2971 int cell = table->CellHasContRow(current_cell_number);
2972 ++current_cell_number;
2974 // first find the right position
2976 for (; (i < size()) && (current_cell_number<cell); ++i) {
2978 if (c == LyXParagraph::META_NEWLINE)
2979 ++current_cell_number;
2983 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2987 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2992 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2996 // Fully instantiated font
2997 LyXFont font = getFont(i);
2998 last_font = running_font;
3000 // Spaces at end of font change are simulated to
3001 // be outside font change. i.e. we write
3002 // "\textXX{text} " rather than "\textXX{text }".
3004 if (open_font && c == ' ' && i <= size() - 2
3005 && getFont(i + 1) != running_font
3006 && getFont(i + 1) != font) {
3007 font = getFont(i + 1);
3010 // We end font definition before blanks
3011 if (font != running_font && open_font) {
3012 column += running_font.latexWriteEndChanges(os, basefont, font);
3013 running_font = basefont;
3016 // Blanks are printed before start of fontswitch
3018 SimpleTeXBlanks(os, texrow, i,
3019 column, font, style);
3021 // Do we need to change font?
3022 if (font != running_font) {
3024 font.latexWriteStartChanges(os,
3027 running_font = font;
3030 // Do we need to turn on LaTeX mode?
3031 if (font.latex() != running_font.latex()) {
3032 if (font.latex() == LyXFont::ON
3033 && style.needprotect) {
3038 SimpleTeXSpecialChars(os, texrow, font,
3039 running_font, basefont,
3040 open_font, style, i, column, c);
3042 // If we have an open font definition, we have to close it
3044 running_font.latexWriteEndChanges(os, basefont,
3048 basefont = getFont(-1);
3049 running_font = basefont;
3050 cell = table->CellHasContRow(current_cell_number);
3052 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
3053 return return_value;
3056 // This one spits out the text off ContRows in tables
3057 bool LyXParagraph::TeXContTableRows(string & file,
3058 LyXParagraph::size_type i,
3059 int current_cell_number,
3060 int & column, TexRow & texrow)
3062 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
3068 bool return_value = false;
3069 LyXLayout const & style =
3070 textclasslist.Style(current_view->buffer()->params.textclass,
3072 LyXFont basefont = getFont(-1); // Get layout font
3074 // Which font is currently active?
3075 LyXFont running_font = basefont;
3076 // Do we have an open font change?
3077 bool open_font = false;
3079 size_type lastpos = i;
3080 int cell = table->CellHasContRow(current_cell_number);
3081 ++current_cell_number;
3083 // first find the right position
3085 for (; (i < size()) && (current_cell_number<cell); ++i) {
3087 if (c == LyXParagraph::META_NEWLINE)
3088 ++current_cell_number;
3092 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3096 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
3101 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3105 // Fully instantiated font
3106 LyXFont font = getFont(i);
3107 last_font = running_font;
3109 // Spaces at end of font change are simulated to
3110 // be outside font change. i.e. we write
3111 // "\textXX{text} " rather than "\textXX{text }".
3113 if (open_font && c == ' ' && i <= size() - 2
3114 && getFont(i + 1) != running_font
3115 && getFont(i + 1) != font) {
3116 font = getFont(i + 1);
3119 // We end font definition before blanks
3120 if (font != running_font && open_font) {
3121 column += running_font.latexWriteEndChanges(file, basefont, font);
3122 running_font = basefont;
3125 // Blanks are printed before start of fontswitch
3127 SimpleTeXBlanks(file, texrow, i,
3128 column, font, style);
3130 // Do we need to change font?
3131 if (font != running_font) {
3133 font.latexWriteStartChanges(file,
3134 basefont, last_font);
3135 running_font = font;
3138 // Do we need to turn on LaTeX mode?
3139 if (font.latex() != running_font.latex()) {
3140 if (font.latex() == LyXFont::ON
3141 && style.needprotect)
3143 file += "\\protect ";
3147 SimpleTeXSpecialChars(file, texrow, font,
3148 running_font, basefont,
3149 open_font, style, i, column, c);
3151 // If we have an open font definition, we have to close it
3153 running_font.latexWriteEndChanges(file, basefont, basefont);
3156 basefont = getFont(-1);
3157 running_font = basefont;
3158 cell = table->CellHasContRow(current_cell_number);
3160 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
3161 return return_value;
3166 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
3168 bool retval = false;
3170 case LyXParagraph::META_HFILL:
3171 sgml_string.clear();
3174 case LyXParagraph::META_PROTECTED_SEPARATOR:
3178 case LyXParagraph::META_NEWLINE:
3182 sgml_string = "&";
3185 sgml_string = "<";
3188 sgml_string = ">";
3191 sgml_string = "$";
3194 sgml_string = "#";
3197 sgml_string = "%";
3200 sgml_string = "[";
3203 sgml_string = "]";
3206 sgml_string = "{";
3209 sgml_string = "}";
3212 sgml_string = "˜";
3215 sgml_string = """;
3218 sgml_string = "\";
3224 case '\0': // Ignore :-)
3225 sgml_string.clear();
3235 #ifdef USE_OSTREAM_ONLY
3236 void LyXParagraph::SimpleDocBookOneTablePar(ostream & os, string & extra,
3237 int & desc_on, int depth)
3240 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
3242 LyXFont font1, font2;
3245 size_type main_body;
3246 bool emph_flag = false;
3248 LyXLayout const & style =
3249 textclasslist.Style(current_view->buffer()->params.textclass,
3252 if (style.labeltype != LABEL_MANUAL)
3255 main_body = BeginningOfMainBody();
3257 // Gets paragraph main font.
3259 font1 = style.labelfont;
3263 int char_line_count = depth;
3264 os << newlineAndDepth(depth);
3265 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
3266 os << "<INFORMALTABLE>"
3267 << newlineAndDepth(++depth);
3269 int current_cell_number = -1;
3270 int tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
3272 // Parsing main loop.
3273 for (size_type i = 0; i < size(); ++i) {
3275 if (table->IsContRow(current_cell_number+1)) {
3276 if (c == LyXParagraph::META_NEWLINE)
3277 ++current_cell_number;
3282 // Fully instantiated font
3285 // Handle <emphasis> tag.
3286 if (font1.emph() != font2.emph() && i) {
3287 if (font2.emph() == LyXFont::ON) {
3290 } else if (emph_flag) {
3291 os << "</emphasis>";
3295 if (c == LyXParagraph::META_NEWLINE) {
3296 // We have only to control for emphasis open here!
3298 os << "</emphasis>";
3301 font1 = font2 = getFont(-1);
3302 ++current_cell_number;
3303 if (table->CellHasContRow(current_cell_number) >= 0) {
3304 DocBookContTableRows(os, extra, desc_on, i + 1,
3305 current_cell_number,
3308 // if this cell follow only ContRows till end don't
3309 // put the EndOfCell because it is put after the
3311 if (table->ShouldBeVeryLastCell(current_cell_number)) {
3312 --current_cell_number;
3315 tmp = table->DocBookEndOfCell(os,
3316 current_cell_number,
3321 } else if (c == LyXParagraph::META_INSET) {
3322 inset = GetInset(i);
3325 inset->DocBook(ost);
3326 string tmp_out = ost.str().c_str();
3329 inset->DocBook(ost);
3331 char * ctmp = ost.str();
3332 string tmp_out(ctmp);
3336 // This code needs some explanation:
3337 // Two insets are treated specially
3338 // label if it is the first element in a
3339 // command paragraph
3341 // graphics inside tables or figure floats
3343 // title (the equivalente in latex for this
3345 // and title should come first
3348 if(desc_on != 3 || i != 0) {
3349 if(tmp_out[0] == '@') {
3351 extra += frontStrip(tmp_out,
3354 os << frontStrip(tmp_out,
3359 } else if (font2.latex() == LyXFont::ON) {
3360 // "TeX"-Mode on == > SGML-Mode on.
3366 if (linuxDocConvertChar(c, sgml_string)
3367 && !style.free_spacing) {
3368 // in freespacing mode, spaces are
3369 // non-breaking characters
3374 << "</term><listitem><para>";
3386 // Needed if there is an optional argument but no contents.
3387 if (main_body > 0 && main_body == size()) {
3392 os << "</emphasis>";
3395 ++current_cell_number;
3396 tmp = table->DocBookEndOfCell(os, current_cell_number, depth);
3397 // Resets description flag correctly.
3400 // <term> not closed...
3404 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3405 os << "</INFORMALTABLE>";
3407 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
3411 void LyXParagraph::SimpleDocBookOneTablePar(string & file, string & extra,
3412 int & desc_on, int depth)
3415 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
3417 LyXFont font1, font2;
3420 size_type main_body;
3421 bool emph_flag = false;
3423 LyXLayout const & style =
3424 textclasslist.Style(current_view->buffer()->params.textclass,
3427 if (style.labeltype != LABEL_MANUAL)
3430 main_body = BeginningOfMainBody();
3432 // Gets paragraph main font.
3434 font1 = style.labelfont;
3438 int char_line_count = depth;
3439 addNewlineAndDepth(file, depth);
3440 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
3441 file += "<INFORMALTABLE>";
3442 addNewlineAndDepth(file, ++depth);
3444 int current_cell_number = -1;
3445 int tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
3447 // Parsing main loop.
3448 for (size_type i = 0; i < size(); ++i) {
3450 if (table->IsContRow(current_cell_number+1)) {
3451 if (c == LyXParagraph::META_NEWLINE)
3452 ++current_cell_number;
3457 // Fully instantiated font
3460 // Handle <emphasis> tag.
3461 if (font1.emph() != font2.emph() && i) {
3462 if (font2.emph() == LyXFont::ON) {
3463 file += "<emphasis>";
3465 } else if (emph_flag) {
3466 file += "</emphasis>";
3470 if (c == LyXParagraph::META_NEWLINE) {
3471 // We have only to control for emphasis open here!
3473 file += "</emphasis>";
3476 font1 = font2 = getFont(-1);
3477 ++current_cell_number;
3478 if (table->CellHasContRow(current_cell_number) >= 0) {
3479 DocBookContTableRows(file, extra, desc_on, i+1,
3480 current_cell_number,
3483 // if this cell follow only ContRows till end don't
3484 // put the EndOfCell because it is put after the
3486 if (table->ShouldBeVeryLastCell(current_cell_number)) {
3487 --current_cell_number;
3490 tmp = table->DocBookEndOfCell(file,
3491 current_cell_number,
3496 } else if (c == LyXParagraph::META_INSET) {
3497 inset = GetInset(i);
3498 #ifdef USE_OSTREAM_ONLY
3501 inset->DocBook(ost);
3502 string tmp_out = ost.str().c_str();
3505 inset->DocBook(ost);
3507 char * ctmp = ost.str();
3508 string tmp_out(ctmp);
3513 inset->DocBook(tmp_out);
3516 // This code needs some explanation:
3517 // Two insets are treated specially
3518 // label if it is the first element in a
3519 // command paragraph
3521 // graphics inside tables or figure floats
3523 // title (the equivalente in latex for this
3525 // and title should come first
3528 if(desc_on != 3 || i != 0) {
3529 if(tmp_out[0] == '@') {
3531 extra += frontStrip(tmp_out,
3534 file += frontStrip(tmp_out,
3539 } else if (font2.latex() == LyXFont::ON) {
3540 // "TeX"-Mode on == > SGML-Mode on.
3546 if (linuxDocConvertChar(c, sgml_string)
3547 && !style.free_spacing) {
3548 // in freespacing mode, spaces are
3549 // non-breaking characters
3554 file += "</term><listitem><para>";
3560 file += sgml_string;
3566 // Needed if there is an optional argument but no contents.
3567 if (main_body > 0 && main_body == size()) {
3572 file += "</emphasis>";
3575 ++current_cell_number;
3576 tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
3577 // Resets description flag correctly.
3580 // <term> not closed...
3584 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3585 file += "</INFORMALTABLE>";
3587 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
3593 #ifdef USE_OSTREAM_ONLY
3594 void LyXParagraph::DocBookContTableRows(ostream & os, string & extra,
3596 LyXParagraph::size_type i,
3597 int current_cell_number, int &column)
3602 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
3607 //string emph = "emphasis";
3608 bool emph_flag = false;
3609 int char_line_count = 0;
3611 LyXLayout const & style =
3612 textclasslist.Style(current_view->buffer()->params.textclass,
3615 size_type main_body;
3616 if (style.labeltype != LABEL_MANUAL)
3619 main_body = BeginningOfMainBody();
3621 // Gets paragraph main font.
3624 font1 = style.labelfont;
3628 size_type lastpos = i;
3629 int cell = table->CellHasContRow(current_cell_number);
3630 ++current_cell_number;
3632 // first find the right position
3634 for (; i < size() && current_cell_number < cell; ++i) {
3636 if (c == LyXParagraph::META_NEWLINE)
3637 ++current_cell_number;
3641 // I don't know how to handle this so I comment it
3642 // for the moment (Jug)
3643 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3644 // file += " \\\\\n";
3647 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
3652 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3656 // Fully instantiated font
3659 // Handle <emphasis> tag.
3660 if (font1.emph() != font2.emph() && i) {
3661 if (font2.emph() == LyXFont::ON) {
3664 } else if (emph_flag) {
3665 os << "</emphasis>";
3669 if (c == LyXParagraph::META_INSET) {
3670 inset = GetInset(i);
3673 inset->DocBook(ost);
3674 string tmp_out = ost.str().c_str();
3677 inset->DocBook(ost);
3679 char * ctmp = ost.str();
3680 string tmp_out(ctmp);
3684 // This code needs some explanation:
3685 // Two insets are treated specially
3686 // label if it is the first element in a
3687 // command paragraph
3689 // graphics inside tables or figure floats
3690 // can't go on title (the equivalente in
3691 // latex for this case is caption and title
3692 // should come first
3695 if(desc_on != 3 || i != 0) {
3696 if(tmp_out[0] == '@') {
3698 extra += frontStrip(tmp_out, '@');
3700 os << frontStrip(tmp_out, '@');
3704 } else if (font2.latex() == LyXFont::ON) {
3705 // "TeX"-Mode on == > SGML-Mode on.
3711 if (linuxDocConvertChar(c, sgml_string)
3712 && !style.free_spacing) {
3713 // in freespacing mode, spaces are
3714 // non-breaking characters
3719 << "</term><listitem><para>";
3729 // we have only to control for emphasis open here!
3731 os << "</emphasis>";
3734 font1 = font2 = getFont(-1);
3735 cell = table->CellHasContRow(current_cell_number);
3737 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3740 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
3742 LyXParagraph::size_type i,
3743 int current_cell_number, int &column)
3748 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
3753 //string emph = "emphasis";
3754 bool emph_flag= false;
3755 int char_line_count= 0;
3757 LyXLayout const & style =
3758 textclasslist.Style(current_view->buffer()->params.textclass,
3761 size_type main_body;
3762 if (style.labeltype != LABEL_MANUAL)
3765 main_body = BeginningOfMainBody();
3767 // Gets paragraph main font.
3770 font1 = style.labelfont;
3774 size_type lastpos = i;
3775 int cell = table->CellHasContRow(current_cell_number);
3776 ++current_cell_number;
3778 // first find the right position
3780 for (; i < size() && current_cell_number < cell; ++i) {
3782 if (c == LyXParagraph::META_NEWLINE)
3783 ++current_cell_number;
3787 // I don't know how to handle this so I comment it
3788 // for the moment (Jug)
3789 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
3790 // file += " \\\\\n";
3793 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
3798 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3802 // Fully instantiated font
3805 // Handle <emphasis> tag.
3806 if (font1.emph() != font2.emph() && i) {
3807 if (font2.emph() == LyXFont::ON) {
3808 file += "<emphasis>";
3810 } else if (emph_flag) {
3811 file += "</emphasis>";
3815 if (c == LyXParagraph::META_INSET) {
3816 inset = GetInset(i);
3817 #ifdef USE_OSTREAM_ONLY
3820 inset->DocBook(ost);
3821 string tmp_out = ost.str().c_str();
3824 inset->DocBook(ost);
3826 char * ctmp = ost.str();
3827 string tmp_out(ctmp);
3832 inset->DocBook(tmp_out);
3835 // This code needs some explanation:
3836 // Two insets are treated specially
3837 // label if it is the first element in a
3838 // command paragraph
3840 // graphics inside tables or figure floats
3841 // can't go on title (the equivalente in
3842 // latex for this case is caption and title
3843 // should come first
3846 if(desc_on != 3 || i != 0) {
3847 if(tmp_out[0] == '@') {
3849 extra += frontStrip(tmp_out, '@');
3851 file += frontStrip(tmp_out, '@');
3855 } else if (font2.latex() == LyXFont::ON) {
3856 // "TeX"-Mode on == > SGML-Mode on.
3862 if (linuxDocConvertChar(c, sgml_string)
3863 && !style.free_spacing) {
3864 // in freespacing mode, spaces are
3865 // non-breaking characters
3870 file += "</term><listitem><para>";
3876 file += sgml_string;
3880 // we have only to control for emphasis open here!
3882 file += "</emphasis>";
3885 font1 = font2 = getFont(-1);
3886 cell = table->CellHasContRow(current_cell_number);
3888 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
3893 #ifdef USE_OSTREAM_ONLY
3894 void LyXParagraph::SimpleTeXBlanks(ostream & os, TexRow & texrow,
3895 LyXParagraph::size_type const i,
3896 int & column, LyXFont const & font,
3897 LyXLayout const & style)
3899 if (column > tex_code_break_column
3901 && GetChar(i - 1) != ' '
3903 // In LaTeX mode, we don't want to
3904 // break lines since some commands
3906 && ! (font.latex() == LyXFont::ON)
3907 // same in FreeSpacing mode
3908 && !style.free_spacing
3909 // In typewriter mode, we want to avoid
3910 // ! . ? : at the end of a line
3911 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3912 && (GetChar(i-1) == '.'
3913 || GetChar(i-1) == '?'
3914 || GetChar(i-1) == ':'
3915 || GetChar(i-1) == '!'))) {
3916 if (tex_code_break_column == 0) {
3917 // in batchmode we need LaTeX to still
3918 // see it as a space not as an extra '\n'
3924 texrow.start(this, i + 1);
3926 } else if (font.latex() == LyXFont::OFF) {
3927 if (style.free_spacing) {
3935 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
3936 LyXParagraph::size_type const i,
3937 int & column, LyXFont const & font,
3938 LyXLayout const & style)
3940 if (column > tex_code_break_column
3942 && GetChar(i - 1) != ' '
3944 // In LaTeX mode, we don't want to
3945 // break lines since some commands
3947 && ! (font.latex() == LyXFont::ON)
3948 // same in FreeSpacing mode
3949 && !style.free_spacing
3950 // In typewriter mode, we want to avoid
3951 // ! . ? : at the end of a line
3952 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
3953 && (GetChar(i-1) == '.'
3954 || GetChar(i-1) == '?'
3955 || GetChar(i-1) == ':'
3956 || GetChar(i-1) == '!'))) {
3957 if (tex_code_break_column == 0) {
3958 // in batchmode we need LaTeX to still
3959 // see it as a space not as an extra '\n'
3965 texrow.start(this, i+1);
3967 } else if (font.latex() == LyXFont::OFF) {
3968 if (style.free_spacing) {
3978 #ifdef USE_OSTREAM_ONLY
3979 void LyXParagraph::SimpleTeXSpecialChars(ostream & os, TexRow & texrow,
3981 LyXFont & running_font,
3984 LyXLayout const & style,
3985 LyXParagraph::size_type & i,
3986 int & column, char const c)
3988 // Two major modes: LaTeX or plain
3989 // Handle here those cases common to both modes
3990 // and then split to handle the two modes separately.
3992 case LyXParagraph::META_INSET: {
3993 Inset * inset = GetInset(i);
3996 int len = os.tellp();
3997 if ((inset->LyxCode() == Inset::GRAPHICS_CODE
3998 || inset->LyxCode() == Inset::MATH_CODE
3999 || inset->LyxCode() == Inset::URL_CODE)
4000 && running_font.getFontDirection()
4001 == LYX_DIR_RIGHT_TO_LEFT) {
4006 int tmp = inset->Latex(os, style.isCommand(),
4007 style.free_spacing);
4015 column += os.tellp() - len;
4024 case LyXParagraph::META_NEWLINE:
4026 column += running_font.latexWriteEndChanges(os,
4031 basefont = getFont(-1);
4032 running_font = basefont;
4035 case LyXParagraph::META_HFILL:
4041 // And now for the special cases within each mode
4042 // Are we in LaTeX mode?
4043 if (font.latex() == LyXFont::ON) {
4044 // at present we only have one option
4045 // but I'll leave it as a switch statement
4046 // so its simpler to extend. (ARRae)
4049 case LyXParagraph::META_PROTECTED_SEPARATOR:
4054 // make sure that we will not print
4055 // error generating chars to the tex
4056 // file. This test would not be needed
4057 // if it were done in the buffer
4065 // Plain mode (i.e. not LaTeX)
4068 case LyXParagraph::META_PROTECTED_SEPARATOR:
4073 os << "\\textbackslash{}";
4077 case '°': case '±': case '²': case '³':
4078 case '×': case '÷': case '¹': case 'ª':
4079 case 'º': case '¬': case 'µ':
4080 if (current_view->buffer()->params.inputenc == "latin1") {
4081 os << "\\ensuremath{"
4090 case '|': case '<': case '>':
4091 // In T1 encoding, these characters exist
4092 if (lyxrc->fontenc == "T1") {
4094 //... but we should avoid ligatures
4095 if ((c == '>' || c == '<')
4097 && GetChar(i + 1) == c){
4098 os << "\\textcompwordmark{}";
4103 // Typewriter font also has them
4104 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
4108 // Otherwise, we use what LaTeX
4112 os << "\\textless{}";
4116 os << "\\textgreater{}";
4120 os << "\\textbar{}";
4126 case '-': // "--" in Typewriter mode -> "-{}-"
4128 && GetChar(i + 1) == '-'
4129 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
4138 os << "\\char`\\\"{}";
4143 if (current_view->buffer()->params.inputenc == "default") {
4152 case '%': case '#': case '{':
4159 os << "\\textasciitilde{}";
4164 os << "\\textasciicircum{}";
4168 case '*': case '[': case ']':
4169 // avoid being mistaken for optional arguments
4170 os << '{' << c << '}';
4175 // Blanks are printed before font switching.
4176 // Sure? I am not! (try nice-latex)
4177 // I am sure it's correct. LyX might be smarter
4178 // in the future, but for now, nothing wrong is
4183 /* idea for labels --- begin*/
4187 && font.family() != LyXFont::TYPEWRITER_FAMILY
4188 && GetChar(i + 1) == 'y'
4189 && GetChar(i + 2) == 'X') {
4197 && font.family() != LyXFont::TYPEWRITER_FAMILY
4198 && GetChar(i + 1) == 'e'
4199 && GetChar(i + 2) == 'X') {
4204 // Check for "LaTeX2e"
4207 && font.family() != LyXFont::TYPEWRITER_FAMILY
4208 && GetChar(i + 1) == 'a'
4209 && GetChar(i + 2) == 'T'
4210 && GetChar(i + 3) == 'e'
4211 && GetChar(i + 4) == 'X'
4212 && GetChar(i + 5) == '2'
4213 && GetChar(i + 6) == 'e') {
4218 // Check for "LaTeX"
4221 && font.family() != LyXFont::TYPEWRITER_FAMILY
4222 && GetChar(i + 1) == 'a'
4223 && GetChar(i + 2) == 'T'
4224 && GetChar(i + 3) == 'e'
4225 && GetChar(i + 4) == 'X') {
4229 /* idea for labels --- end*/
4230 } else if (c != '\0') {
4239 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
4241 LyXFont & running_font,
4244 LyXLayout const & style,
4245 LyXParagraph::size_type & i,
4246 int & column, char const c)
4248 // Two major modes: LaTeX or plain
4249 // Handle here those cases common to both modes
4250 // and then split to handle the two modes separately.
4252 case LyXParagraph::META_INSET: {
4253 Inset * inset = GetInset(i);
4256 int len = file.length();
4257 if ((inset->LyxCode() == Inset::GRAPHICS_CODE
4258 || inset->LyxCode() == Inset::MATH_CODE
4259 || inset->LyxCode() == Inset::URL_CODE)
4260 && running_font.getFontDirection()
4261 == LYX_DIR_RIGHT_TO_LEFT) {
4265 #ifdef USE_OSTREAM_ONLY
4268 int tmp = inset->Latex(ost, style.isCommand());
4269 file += ost.str().c_str();
4272 int tmp = inset->Latex(ost, style.isCommand());
4274 char * chtmp = ost.str();
4279 int tmp = inset->Latex(file, style.isCommand());
4287 column += file.length() - len;
4296 case LyXParagraph::META_NEWLINE:
4298 column += running_font.latexWriteEndChanges(file,
4299 basefont, basefont);
4302 basefont = getFont(-1);
4303 running_font = basefont;
4306 case LyXParagraph::META_HFILL:
4307 file += "\\hfill{}";
4312 // And now for the special cases within each mode
4313 // Are we in LaTeX mode?
4314 if (font.latex() == LyXFont::ON) {
4315 // at present we only have one option
4316 // but I'll leave it as a switch statement
4317 // so its simpler to extend. (ARRae)
4320 case LyXParagraph::META_PROTECTED_SEPARATOR:
4325 // make sure that we will not print
4326 // error generating chars to the tex
4327 // file. This test would not be needed
4328 // if it were done in the buffer
4336 // Plain mode (i.e. not LaTeX)
4339 case LyXParagraph::META_PROTECTED_SEPARATOR:
4344 file += "\\textbackslash{}";
4348 case '°': case '±': case '²': case '³':
4349 case '×': case '÷': case '¹': case 'ª':
4350 case 'º': case '¬': case 'µ':
4351 if (current_view->buffer()->params.inputenc == "latin1") {
4352 file += "\\ensuremath{";
4361 case '|': case '<': case '>':
4362 // In T1 encoding, these characters exist
4363 if (lyxrc->fontenc == "T1") {
4365 //... but we should avoid ligatures
4366 if ((c == '>' || c == '<')
4368 && GetChar(i+1) == c){
4369 file += "\\textcompwordmark{}";
4374 // Typewriter font also has them
4375 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
4379 // Otherwise, we use what LaTeX
4383 file += "\\textless{}";
4387 file += "\\textgreater{}";
4391 file += "\\textbar{}";
4397 case '-': // "--" in Typewriter mode -> "-{}-"
4399 && GetChar(i + 1) == '-'
4400 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
4409 file += "\\char`\\\"{}";
4414 if (current_view->buffer()->params.inputenc == "default") {
4415 file += "\\pounds{}";
4423 case '%': case '#': case '{':
4431 file += "\\textasciitilde{}";
4436 file += "\\textasciicircum{}";
4440 case '*': case '[': case ']':
4441 // avoid being mistaken for optional arguments
4449 // Blanks are printed before font switching.
4450 // Sure? I am not! (try nice-latex)
4451 // I am sure it's correct. LyX might be smarter
4452 // in the future, but for now, nothing wrong is
4457 /* idea for labels --- begin*/
4461 && font.family() != LyXFont::TYPEWRITER_FAMILY
4462 && GetChar(i + 1) == 'y'
4463 && GetChar(i + 2) == 'X') {
4471 && font.family() != LyXFont::TYPEWRITER_FAMILY
4472 && GetChar(i + 1) == 'e'
4473 && GetChar(i + 2) == 'X') {
4478 // Check for "LaTeX2e"
4481 && font.family() != LyXFont::TYPEWRITER_FAMILY
4482 && GetChar(i + 1) == 'a'
4483 && GetChar(i + 2) == 'T'
4484 && GetChar(i + 3) == 'e'
4485 && GetChar(i + 4) == 'X'
4486 && GetChar(i + 5) == '2'
4487 && GetChar(i + 6) == 'e') {
4488 file += "\\LaTeXe{}";
4492 // Check for "LaTeX"
4495 && font.family() != LyXFont::TYPEWRITER_FAMILY
4496 && GetChar(i + 1) == 'a'
4497 && GetChar(i + 2) == 'T'
4498 && GetChar(i + 3) == 'e'
4499 && GetChar(i + 4) == 'X') {
4500 file += "\\LaTeX{}";
4503 /* idea for labels --- end*/
4504 } else if (c != '\0') {
4516 bool LyXParagraph::RoffContTableRows(ostream & os,
4517 LyXParagraph::size_type i,
4523 LyXFont font1(LyXFont::ALL_INHERIT);
4528 string fname2 = TmpFileName(string(), "RAT2");
4530 int cell = table->CellHasContRow(actcell);
4533 // first find the right position
4535 for (; i < size() && actcell < cell; ++i) {
4537 if (c == LyXParagraph::META_NEWLINE)
4542 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
4545 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
4547 font2 = GetFontSettings(i);
4548 if (font1.latex() != font2.latex()) {
4549 if (font2.latex() != LyXFont::OFF)
4554 case LyXParagraph::META_INSET:
4555 if ((inset = GetInset(i))) {
4558 stringstream ss(ios::in | ios::out);
4559 inset->Latex(ss, -1);
4571 inset->Latex(ss, -1);
4584 fstream fs(fname2.c_str(),
4587 WriteAlert(_("LYX_ERROR:"),
4588 _("Cannot open temporary file:"),
4592 inset->Latex(fs, -1);
4606 case LyXParagraph::META_NEWLINE:
4608 case LyXParagraph::META_HFILL:
4611 case LyXParagraph::META_PROTECTED_SEPARATOR:
4621 lyxerr.debug() << "RoffAsciiTable: "
4622 "NULL char in structure."
4627 cell = table->CellHasContRow(actcell);
4634 #ifdef USE_OSTREAM_ONLY
4635 LyXParagraph * LyXParagraph::TeXDeeper(ostream & os, TexRow & texrow,
4636 ostream & foot, TexRow & foot_texrow,
4639 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
4640 LyXParagraph * par = this;
4642 while (par && par->depth == depth) {
4644 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
4645 if (textclasslist.Style(current_view->buffer()->params.textclass,
4646 par->layout).isEnvironment()
4647 || par->pextra_type != PEXTRA_NONE) {
4648 par = par->TeXEnvironment(os, texrow,
4652 par = par->TeXOnePar(os, texrow,
4657 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
4662 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
4663 string & foot, TexRow & foot_texrow,
4666 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
4667 LyXParagraph * par = this;
4669 while (par && par->depth == depth) {
4671 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
4672 if (textclasslist.Style(current_view->buffer()->params.textclass,
4673 par->layout).isEnvironment()
4674 || par->pextra_type != PEXTRA_NONE)
4676 par = par->TeXEnvironment(file, texrow,
4680 par = par->TeXOnePar(file, texrow,
4685 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
4692 #ifdef USE_OSTREAM_ONLY
4693 LyXParagraph * LyXParagraph::TeXEnvironment(ostream & os, TexRow & texrow,
4695 TexRow & foot_texrow,
4698 bool eindent_open = false;
4699 bool foot_this_level = false;
4700 // flags when footnotetext should be appended to file.
4701 static bool minipage_open = false;
4702 static int minipage_open_depth = 0;
4703 char par_sep = current_view->buffer()->params.paragraph_separation;
4705 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
4707 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
4709 LyXLayout const & style =
4710 textclasslist.Style(current_view->buffer()->params.textclass,
4713 if (pextra_type == PEXTRA_INDENT) {
4714 if (!pextra_width.empty()) {
4715 os << "\\begin{LyXParagraphIndent}{"
4716 << pextra_width << "}\n";
4718 //float ib = atof(pextra_widthp.c_str())/100;
4719 // string can't handle floats at present (971109)
4720 // so I'll do a conversion by hand knowing that
4721 // the limits are 0.0 to 1.0. ARRae.
4722 os << "\\begin{LyXParagraphIndent}{";
4723 switch (pextra_widthp.length()) {
4735 os << "\\columnwidth}\n";
4738 eindent_open = true;
4740 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
4741 if (pextra_hfill && Previous() &&
4742 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
4743 os << "\\hfill{}\n";
4746 if (par_sep == BufferParams::PARSEP_INDENT) {
4747 os << "{\\setlength\\parindent{0pt}\n";
4750 os << "\\begin{minipage}";
4751 switch(pextra_alignment) {
4752 case MINIPAGE_ALIGN_TOP:
4755 case MINIPAGE_ALIGN_MIDDLE:
4758 case MINIPAGE_ALIGN_BOTTOM:
4762 if (!pextra_width.empty()) {
4763 os << '{' << pextra_width << "}\n";
4765 //float ib = atof(par->pextra_width.c_str())/100;
4766 // string can't handle floats at present
4767 // so I'll do a conversion by hand knowing that
4768 // the limits are 0.0 to 1.0. ARRae.
4770 switch (pextra_widthp.length()) {
4782 os << "\\columnwidth}\n";
4785 if (par_sep == BufferParams::PARSEP_INDENT) {
4786 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
4789 minipage_open = true;
4790 minipage_open_depth = depth;
4793 #ifdef WITH_WARNINGS
4794 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
4795 //I disabled it because it breaks when lists span on several
4798 if (style.isEnvironment()){
4799 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
4800 #ifdef FANCY_FOOTNOTE_CODE
4801 if (foot_count < 0) {
4802 // flag that footnote[mark][text] should be
4803 // used for any footnotes from now on
4805 foot_this_level = true;
4808 os << "\\begin{" << style.latexname() << "}{"
4809 << labelwidthstring << "}\n";
4810 } else if (style.labeltype == LABEL_BIBLIO) {
4812 os << "\\begin{" << style.latexname() << "}{"
4813 << bibitemWidthest(current_view->painter())
4815 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
4816 #ifdef FANCY_FOOTNOTE_CODE
4817 if (foot_count < 0) {
4818 // flag that footnote[mark][text] should be
4819 // used for any footnotes from now on
4821 foot_this_level = true;
4824 os << "\\begin{" << style.latexname() << '}'
4825 << style.latexparam() << '\n';
4827 os << "\\begin{" << style.latexname() << '}'
4828 << style.latexparam() << '\n';
4831 LyXParagraph * par = this;
4833 par = par->TeXOnePar(os, texrow,
4834 foot, foot_texrow, foot_count);
4836 if (minipage_open && par && !style.isEnvironment() &&
4837 (par->pextra_type == PEXTRA_MINIPAGE) &&
4838 par->pextra_start_minipage) {
4839 os << "\\end{minipage}\n";
4841 if (par_sep == BufferParams::PARSEP_INDENT) {
4845 minipage_open = false;
4847 if (par && par->depth > depth) {
4848 if (textclasslist.Style(current_view->buffer()->params.textclass,
4849 par->layout).isParagraph()
4852 // How to handle this? (Lgb)
4853 //&& !suffixIs(os, "\n\n")
4855 // There should be at least one '\n' already
4856 // but we need there to be two for Standard
4857 // paragraphs that are depth-increment'ed to be
4858 // output correctly. However, tables can
4859 // also be paragraphs so don't adjust them.
4862 // Will it ever harm to have one '\n' too
4863 // many? i.e. that we sometimes will have
4864 // three in a row. (Lgb)
4868 par = par->TeXDeeper(os, texrow,
4869 foot, foot_texrow, foot_count);
4871 if (par && par->layout == layout && par->depth == depth &&
4872 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
4873 if (par->pextra_hfill && par->Previous() &&
4874 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
4875 os << "\\hfill{}\n";
4878 if (par_sep == BufferParams::PARSEP_INDENT) {
4879 os << "{\\setlength\\parindent{0pt}\n";
4882 os << "\\begin{minipage}";
4883 switch(par->pextra_alignment) {
4884 case MINIPAGE_ALIGN_TOP:
4887 case MINIPAGE_ALIGN_MIDDLE:
4890 case MINIPAGE_ALIGN_BOTTOM:
4894 if (!par->pextra_width.empty()) {
4895 os << '{' << par->pextra_width << "}\n";
4897 //float ib = atof(par->pextra_widthp.c_str())/100;
4898 // string can't handle floats at present
4899 // so I'll do a conversion by hand knowing that
4900 // the limits are 0.0 to 1.0. ARRae.
4902 switch (par->pextra_widthp.length()) {
4907 os << "0." << par->pextra_widthp;
4910 os << "0.0" << par->pextra_widthp;
4912 os << "\\columnwidth}\n";
4915 if (par_sep == BufferParams::PARSEP_INDENT) {
4916 os << "\\setlength\\parindent{\\LyXMinipageIndent}\n";
4919 minipage_open = true;
4920 minipage_open_depth = par->depth;
4923 && par->layout == layout
4924 && par->depth == depth
4925 && par->pextra_type == pextra_type);
4927 if (style.isEnvironment()) {
4928 os << "\\end{" << style.latexname() << '}';
4929 // maybe this should go after the minipage closes?
4930 if (foot_this_level) {
4931 if (foot_count >= 1) {
4932 if (foot_count > 1) {
4933 os << "\\addtocounter{footnote}{-"
4938 texrow += foot_texrow;
4940 foot_texrow.reset();
4945 if (minipage_open && (minipage_open_depth == depth) &&
4946 (!par || par->pextra_start_minipage ||
4947 par->pextra_type != PEXTRA_MINIPAGE)) {
4948 os << "\\end{minipage}\n";
4950 if (par_sep == BufferParams::PARSEP_INDENT) {
4954 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
4955 os << "\\medskip\n\n";
4959 minipage_open = false;
4962 os << "\\end{LyXParagraphIndent}\n";
4965 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
4966 && par->pextra_hfill)) {
4970 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
4971 return par; // ale970302
4974 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
4976 TexRow & foot_texrow,
4979 bool eindent_open = false;
4980 bool foot_this_level = false;
4981 // flags when footnotetext should be appended to file.
4982 static bool minipage_open = false;
4983 static int minipage_open_depth = 0;
4984 char par_sep = current_view->buffer()->params.paragraph_separation;
4986 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
4988 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
4990 LyXLayout const & style =
4991 textclasslist.Style(current_view->buffer()->params.textclass,
4994 if (pextra_type == PEXTRA_INDENT) {
4995 if (!pextra_width.empty()) {
4996 file += "\\begin{LyXParagraphIndent}{"
4997 + pextra_width + "}\n";
4999 //float ib = atof(pextra_widthp.c_str())/100;
5000 // string can't handle floats at present (971109)
5001 // so I'll do a conversion by hand knowing that
5002 // the limits are 0.0 to 1.0. ARRae.
5003 file += "\\begin{LyXParagraphIndent}{";
5004 switch (pextra_widthp.length()) {
5010 file += pextra_widthp;
5014 file += pextra_widthp;
5016 file += "\\columnwidth}\n";
5019 eindent_open = true;
5021 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
5022 if (pextra_hfill && Previous() &&
5023 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
5024 file += "\\hfill{}\n";
5027 if (par_sep == BufferParams::PARSEP_INDENT) {
5028 file += "{\\setlength\\parindent{0pt}\n";
5031 file += "\\begin{minipage}";
5032 switch(pextra_alignment) {
5033 case MINIPAGE_ALIGN_TOP:
5036 case MINIPAGE_ALIGN_MIDDLE:
5039 case MINIPAGE_ALIGN_BOTTOM:
5043 if (!pextra_width.empty()) {
5045 file += pextra_width + "}\n";
5047 //float ib = atof(par->pextra_width.c_str())/100;
5048 // string can't handle floats at present
5049 // so I'll do a conversion by hand knowing that
5050 // the limits are 0.0 to 1.0. ARRae.
5052 switch (pextra_widthp.length()) {
5058 file += pextra_widthp;
5062 file += pextra_widthp;
5064 file += "\\columnwidth}\n";
5067 if (par_sep == BufferParams::PARSEP_INDENT) {
5068 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
5071 minipage_open = true;
5072 minipage_open_depth = depth;
5075 #ifdef WITH_WARNINGS
5076 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
5077 //I disabled it because it breaks when lists span on several
5080 if (style.isEnvironment()){
5081 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
5082 #ifdef FANCY_FOOTNOTE_CODE
5083 if (foot_count < 0) {
5084 // flag that footnote[mark][text] should be
5085 // used for any footnotes from now on
5087 foot_this_level = true;
5090 file += "\\begin{" + style.latexname() + "}{"
5091 + labelwidthstring + "}\n";
5092 } else if (style.labeltype == LABEL_BIBLIO) {
5094 file += "\\begin{" + style.latexname() + "}{"
5095 + bibitemWidthest(current_view->painter())
5097 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
5098 #ifdef FANCY_FOOTNOTE_CODE
5099 if (foot_count < 0) {
5100 // flag that footnote[mark][text] should be
5101 // used for any footnotes from now on
5103 foot_this_level = true;
5106 file += "\\begin{" + style.latexname() + '}'
5107 + style.latexparam() + '\n';
5109 file += "\\begin{" + style.latexname() + '}'
5110 + style.latexparam() + '\n';
5113 LyXParagraph * par = this;
5115 par = par->TeXOnePar(file, texrow,
5116 foot, foot_texrow, foot_count);
5118 if (minipage_open && par && !style.isEnvironment() &&
5119 (par->pextra_type == PEXTRA_MINIPAGE) &&
5120 par->pextra_start_minipage) {
5121 file += "\\end{minipage}\n";
5123 if (par_sep == BufferParams::PARSEP_INDENT) {
5127 minipage_open = false;
5129 if (par && par->depth > depth) {
5130 if (textclasslist.Style(current_view->buffer()->params.textclass,
5131 par->layout).isParagraph()
5133 && !suffixIs(file, "\n\n")) {
5134 // There should be at least one '\n' already
5135 // but we need there to be two for Standard
5136 // paragraphs that are depth-increment'ed to be
5137 // output correctly. However, tables can
5138 // also be paragraphs so don't adjust them.
5143 par = par->TeXDeeper(file, texrow,
5144 foot, foot_texrow, foot_count);
5146 if (par && par->layout == layout && par->depth == depth &&
5147 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
5148 if (par->pextra_hfill && par->Previous() &&
5149 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
5150 file += "\\hfill{}\n";
5153 if (par_sep == BufferParams::PARSEP_INDENT) {
5154 file += "{\\setlength\\parindent{0pt}\n";
5157 file += "\\begin{minipage}";
5158 switch(par->pextra_alignment) {
5159 case MINIPAGE_ALIGN_TOP:
5162 case MINIPAGE_ALIGN_MIDDLE:
5165 case MINIPAGE_ALIGN_BOTTOM:
5169 if (!par->pextra_width.empty()) {
5171 file += par->pextra_width;
5174 //float ib = atof(par->pextra_widthp.c_str())/100;
5175 // string can't handle floats at present
5176 // so I'll do a conversion by hand knowing that
5177 // the limits are 0.0 to 1.0. ARRae.
5179 switch (par->pextra_widthp.length()) {
5185 file += par->pextra_widthp;
5189 file += par->pextra_widthp;
5191 file += "\\columnwidth}\n";
5194 if (par_sep == BufferParams::PARSEP_INDENT) {
5195 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
5198 minipage_open = true;
5199 minipage_open_depth = par->depth;
5202 && par->layout == layout
5203 && par->depth == depth
5204 && par->pextra_type == pextra_type);
5206 if (style.isEnvironment()) {
5207 file += "\\end{" + style.latexname() + '}';
5208 // maybe this should go after the minipage closes?
5209 if (foot_this_level) {
5210 if (foot_count >= 1) {
5211 if (foot_count > 1) {
5212 file += "\\addtocounter{footnote}{-";
5213 file += tostr(foot_count - 1);
5217 texrow += foot_texrow;
5219 foot_texrow.reset();
5224 if (minipage_open && (minipage_open_depth == depth) &&
5225 (!par || par->pextra_start_minipage ||
5226 par->pextra_type != PEXTRA_MINIPAGE)) {
5227 file += "\\end{minipage}\n";
5229 if (par_sep == BufferParams::PARSEP_INDENT) {
5233 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
5234 file += "\\medskip\n\n";
5238 minipage_open = false;
5241 file += "\\end{LyXParagraphIndent}\n";
5244 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
5245 && par->pextra_hfill)) {
5249 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
5250 return par; // ale970302
5255 #ifdef USE_OSTREAM_ONLY
5256 LyXParagraph * LyXParagraph::TeXFootnote(ostream & os, TexRow & texrow,
5257 ostream & foot, TexRow & foot_texrow,
5259 LyXDirection par_direction)
5261 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
5262 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
5263 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5264 "No footnote!" << endl;
5266 LyXParagraph * par = this;
5267 LyXLayout const & style =
5268 textclasslist.Style(current_view->buffer()->params.textclass,
5269 previous->GetLayout());
5271 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
5272 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5273 "Float other than footnote in command"
5274 " with moving argument is illegal" << endl;
5277 if (footnotekind != LyXParagraph::FOOTNOTE
5278 && footnotekind != LyXParagraph::MARGIN
5281 // How to solve this?
5282 //&& !suffixIs(file, '\n')
5284 // we need to ensure that real floats like tables and figures
5285 // have their \begin{} on a new line otherwise we can get
5286 // incorrect results when using the endfloat.sty package
5287 // especially if two floats follow one another. ARRae 981022
5288 // NOTE: if the file is length 0 it must have just been
5289 // written out so we assume it ended with a '\n'
5291 // As far as I can see there is never any harm in writing
5292 // a '\n' too much. Please tell me if I am wrong. (Lgb)
5297 BufferParams * params = ¤t_view->buffer()->params;
5298 bool footer_in_body = true;
5299 switch (footnotekind) {
5300 case LyXParagraph::FOOTNOTE:
5301 if (style.intitle) {
5302 os << "\\thanks{\n";
5303 footer_in_body = false;
5305 if (foot_count == -1) {
5306 // we're at depth 0 so we can use:
5307 os << "\\footnote{%\n";
5308 footer_in_body = false;
5310 os << "\\footnotemark{}%\n";
5312 // we only need this when there are
5313 // multiple footnotes
5314 os << "\\stepcounter{footnote}";
5316 os << "\\footnotetext{%\n";
5317 foot_texrow.start(this, 0);
5318 foot_texrow.newline();
5323 case LyXParagraph::MARGIN:
5324 os << "\\marginpar{\n";
5326 case LyXParagraph::FIG:
5327 if (pextra_type == PEXTRA_FLOATFLT
5328 && (!pextra_width.empty()
5329 || !pextra_widthp.empty())) {
5330 if (!pextra_width.empty())
5331 os << "\\begin{floatingfigure}{"
5332 << pextra_width << "}\n";
5334 os << "\\begin{floatingfigure}{"
5335 << atoi(pextra_widthp.c_str())/100.0
5336 << "\\textwidth}\n";
5338 os << "\\begin{figure}";
5339 if (!params->float_placement.empty()) {
5340 os << '[' << params->float_placement << "]\n";
5346 case LyXParagraph::TAB:
5347 os << "\\begin{table}";
5348 if (!params->float_placement.empty()) {
5349 os << '[' << params->float_placement << "]\n";
5354 case LyXParagraph::WIDE_FIG:
5355 os << "\\begin{figure*}";
5356 if (!params->float_placement.empty()) {
5357 os << '[' << params->float_placement << "]\n";
5362 case LyXParagraph::WIDE_TAB:
5363 os << "\\begin{table*}";
5364 if (!params->float_placement.empty()) {
5365 os << '[' << params->float_placement << "]\n";
5370 case LyXParagraph::ALGORITHM:
5371 os << "\\begin{algorithm}\n";
5377 LyXDirection direction = getParDirection();
5378 if (direction != par_direction) {
5379 if (direction == LYX_DIR_LEFT_TO_RIGHT)
5380 os << "\\unsethebrew\n";
5382 os << "\\sethebrew\n";
5386 if (footnotekind != LyXParagraph::FOOTNOTE
5387 || !footer_in_body) {
5388 // Process text for all floats except footnotes in body
5390 LyXLayout const & style =
5392 .Style(current_view->buffer()->params
5396 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5398 if (style.isEnvironment()
5399 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5400 // Allows the use of minipages within float
5401 // environments. Shouldn't be circular because
5402 // we don't support footnotes inside
5403 // floats (yet). ARRae
5404 par = par->TeXEnvironment(os, texrow,
5408 par = par->TeXOnePar(os, texrow,
5413 if (par && !par->IsDummy() && par->depth > depth) {
5414 par = par->TeXDeeper(os, texrow,
5418 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5420 // process footnotes > depth 0 or in environments separately
5421 // NOTE: Currently don't support footnotes within footnotes
5422 // even though that is possible using the \footnotemark
5424 ostringstream dummy;
5428 TexRow dummy_texrow;
5429 int dummy_count = 0;
5431 LyXLayout const & style =
5433 .Style(current_view->buffer()->params
5437 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5439 if (style.isEnvironment()
5440 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5441 // Allows the use of minipages within float
5442 // environments. Shouldn't be circular because
5443 // we don't support footnotes inside
5444 // floats (yet). ARRae
5445 par = par->TeXEnvironment(foot, foot_texrow,
5446 dummy, dummy_texrow,
5449 par = par->TeXOnePar(foot, foot_texrow,
5450 dummy, dummy_texrow,
5454 if (par && !par->IsDummy() && par->depth > depth) {
5455 par = par->TeXDeeper(foot, foot_texrow,
5456 dummy, dummy_texrow,
5460 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5462 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5463 "Footnote in a Footnote -- not supported"
5466 #ifndef HAVE_OSTREAM
5467 delete [] dummy.str();
5471 switch (footnotekind) {
5472 case LyXParagraph::FOOTNOTE:
5473 if (footer_in_body) {
5474 // This helps tell which of the multiple
5475 // footnotetexts an error was in.
5477 foot_texrow.newline();
5482 case LyXParagraph::MARGIN:
5485 case LyXParagraph::FIG:
5486 if (pextra_type == PEXTRA_FLOATFLT
5487 && (!pextra_width.empty()
5488 || !pextra_widthp.empty()))
5489 os << "\\end{floatingfigure}";
5491 os << "\\end{figure}";
5493 case LyXParagraph::TAB:
5494 os << "\\end{table}";
5496 case LyXParagraph::WIDE_FIG:
5497 os << "\\end{figure*}";
5499 case LyXParagraph::WIDE_TAB:
5500 os << "\\end{table*}";
5502 case LyXParagraph::ALGORITHM:
5503 os << "\\end{algorithm}";
5507 if (footnotekind != LyXParagraph::FOOTNOTE
5508 && footnotekind != LyXParagraph::MARGIN) {
5509 // we need to ensure that real floats like tables and figures
5510 // have their \end{} on a line of their own otherwise we can
5511 // get incorrect results when using the endfloat.sty package.
5516 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
5520 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
5521 string & foot, TexRow & foot_texrow,
5523 LyXDirection par_direction)
5525 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
5526 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
5527 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5528 "No footnote!" << endl;
5530 LyXParagraph * par = this;
5531 LyXLayout const & style =
5532 textclasslist.Style(current_view->buffer()->params.textclass,
5533 previous->GetLayout());
5535 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
5536 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5537 "Float other than footnote in command"
5538 " with moving argument is illegal" << endl;
5541 if (footnotekind != LyXParagraph::FOOTNOTE
5542 && footnotekind != LyXParagraph::MARGIN
5544 && !suffixIs(file, '\n')) {
5545 // we need to ensure that real floats like tables and figures
5546 // have their \begin{} on a new line otherwise we can get
5547 // incorrect results when using the endfloat.sty package
5548 // especially if two floats follow one another. ARRae 981022
5549 // NOTE: if the file is length 0 it must have just been
5550 // written out so we assume it ended with a '\n'
5555 BufferParams * params = ¤t_view->buffer()->params;
5556 bool footer_in_body = true;
5557 switch (footnotekind) {
5558 case LyXParagraph::FOOTNOTE:
5559 if (style.intitle) {
5560 file += "\\thanks{\n";
5561 footer_in_body = false;
5563 if (foot_count == -1) {
5564 // we're at depth 0 so we can use:
5565 file += "\\footnote{%\n";
5566 footer_in_body = false;
5568 file += "\\footnotemark{}%\n";
5570 // we only need this when there are
5571 // multiple footnotes
5572 foot += "\\stepcounter{footnote}";
5574 foot += "\\footnotetext{%\n";
5575 foot_texrow.start(this, 0);
5576 foot_texrow.newline();
5581 case LyXParagraph::MARGIN:
5582 file += "\\marginpar{\n";
5584 case LyXParagraph::FIG:
5585 if (pextra_type == PEXTRA_FLOATFLT
5586 && (!pextra_width.empty()
5587 || !pextra_widthp.empty())) {
5589 if (!pextra_width.empty())
5591 "\\begin{floatingfigure}{%s}\n",
5592 pextra_width.c_str());
5595 "\\begin{floatingfigure}{%f\\textwidth}\n",
5596 atoi(pextra_widthp.c_str())/100.0);
5599 file += "\\begin{figure}";
5600 if (!params->float_placement.empty()) {
5602 file += params->float_placement;
5609 case LyXParagraph::TAB:
5610 file += "\\begin{table}";
5611 if (!params->float_placement.empty()) {
5613 file += params->float_placement;
5619 case LyXParagraph::WIDE_FIG:
5620 file += "\\begin{figure*}";
5621 if (!params->float_placement.empty()) {
5623 file += params->float_placement;
5629 case LyXParagraph::WIDE_TAB:
5630 file += "\\begin{table*}";
5631 if (!params->float_placement.empty()) {
5633 file += params->float_placement;
5639 case LyXParagraph::ALGORITHM:
5640 file += "\\begin{algorithm}\n";
5646 LyXDirection direction = getParDirection();
5647 if (direction != par_direction) {
5648 if (direction == LYX_DIR_LEFT_TO_RIGHT)
5649 file += "\\unsethebrew\n";
5651 file += "\\sethebrew\n";
5655 if (footnotekind != LyXParagraph::FOOTNOTE
5656 || !footer_in_body) {
5657 // Process text for all floats except footnotes in body
5659 LyXLayout const & style =
5661 .Style(current_view->buffer()->params
5665 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5667 if (style.isEnvironment()
5668 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5669 // Allows the use of minipages within float
5670 // environments. Shouldn't be circular because
5671 // we don't support footnotes inside
5672 // floats (yet). ARRae
5673 par = par->TeXEnvironment(file, texrow,
5677 par = par->TeXOnePar(file, texrow,
5682 if (par && !par->IsDummy() && par->depth > depth) {
5683 par = par->TeXDeeper(file, texrow,
5687 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5689 // process footnotes > depth 0 or in environments separately
5690 // NOTE: Currently don't support footnotes within footnotes
5691 // even though that is possible using the \footnotemark
5693 TexRow dummy_texrow;
5694 int dummy_count = 0;
5696 LyXLayout const & style =
5698 .Style(current_view->buffer()->params
5702 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
5704 if (style.isEnvironment()
5705 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
5706 // Allows the use of minipages within float
5707 // environments. Shouldn't be circular because
5708 // we don't support footnotes inside
5709 // floats (yet). ARRae
5710 par = par->TeXEnvironment(foot, foot_texrow,
5711 dummy, dummy_texrow,
5714 par = par->TeXOnePar(foot, foot_texrow,
5715 dummy, dummy_texrow,
5719 if (par && !par->IsDummy() && par->depth > depth) {
5720 par = par->TeXDeeper(foot, foot_texrow,
5721 dummy, dummy_texrow,
5725 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
5727 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
5728 "Footnote in a Footnote -- not supported"
5733 switch (footnotekind) {
5734 case LyXParagraph::FOOTNOTE:
5735 if (footer_in_body) {
5736 // This helps tell which of the multiple
5737 // footnotetexts an error was in.
5739 foot_texrow.newline();
5744 case LyXParagraph::MARGIN:
5747 case LyXParagraph::FIG:
5748 if (pextra_type == PEXTRA_FLOATFLT
5749 && (!pextra_width.empty()
5750 || !pextra_widthp.empty()))
5751 file += "\\end{floatingfigure}";
5753 file += "\\end{figure}";
5755 case LyXParagraph::TAB:
5756 file += "\\end{table}";
5758 case LyXParagraph::WIDE_FIG:
5759 file += "\\end{figure*}";
5761 case LyXParagraph::WIDE_TAB:
5762 file += "\\end{table*}";
5764 case LyXParagraph::ALGORITHM:
5765 file += "\\end{algorithm}";
5769 if (footnotekind != LyXParagraph::FOOTNOTE
5770 && footnotekind != LyXParagraph::MARGIN) {
5771 // we need to ensure that real floats like tables and figures
5772 // have their \end{} on a line of their own otherwise we can
5773 // get incorrect results when using the endfloat.sty package.
5778 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
5784 void LyXParagraph::SetPExtraType(int type, char const * width,
5785 char const * widthp)
5788 pextra_width = width;
5789 pextra_widthp = widthp;
5791 if (textclasslist.Style(current_view->buffer()->params.textclass,
5792 layout).isEnvironment()) {
5797 while (par && (par->layout == layout)
5798 && (par->depth == depth)) {
5800 par = par->Previous();
5802 par = par->FirstPhysicalPar();
5803 while (par && par->depth > depth) {
5804 par = par->Previous();
5806 par = par->FirstPhysicalPar();
5810 while (par && (par->layout == layout)
5811 && (par->depth == depth)) {
5812 par->pextra_type = type;
5813 par->pextra_width = width;
5814 par->pextra_widthp = widthp;
5815 par = par->NextAfterFootnote();
5816 if (par && (par->depth > depth))
5817 par->SetPExtraType(type, width, widthp);
5818 while (par && ((par->depth > depth) || par->IsDummy()))
5819 par = par->NextAfterFootnote();
5825 void LyXParagraph::UnsetPExtraType()
5827 if (pextra_type == PEXTRA_NONE)
5830 pextra_type = PEXTRA_NONE;
5831 pextra_width.clear();
5832 pextra_widthp.clear();
5834 if (textclasslist.Style(current_view->buffer()->params.textclass,
5835 layout).isEnvironment()) {
5840 while (par && (par->layout == layout)
5841 && (par->depth == depth)) {
5843 par = par->Previous();
5845 par = par->FirstPhysicalPar();
5846 while (par && par->depth > depth) {
5847 par = par->Previous();
5849 par = par->FirstPhysicalPar();
5853 while (par && (par->layout == layout)
5854 && (par->depth == depth)) {
5855 par->pextra_type = PEXTRA_NONE;
5856 par->pextra_width.clear();
5857 par->pextra_widthp.clear();
5858 par = par->NextAfterFootnote();
5859 if (par && (par->depth > depth))
5860 par->UnsetPExtraType();
5861 while (par && ((par->depth > depth) || par->IsDummy()))
5862 par = par->NextAfterFootnote();
5868 bool LyXParagraph::IsHfill(size_type pos) const
5870 return IsHfillChar(GetChar(pos));
5874 bool LyXParagraph::IsInset(size_type pos) const
5876 return IsInsetChar(GetChar(pos));
5880 bool LyXParagraph::IsFloat(size_type pos) const
5882 return IsFloatChar(GetChar(pos));
5886 bool LyXParagraph::IsNewline(size_type pos) const
5890 tmp = IsNewlineChar(GetChar(pos));
5895 bool LyXParagraph::IsSeparator(size_type pos) const
5897 return IsSeparatorChar(GetChar(pos));
5901 bool LyXParagraph::IsLineSeparator(size_type pos) const
5903 return IsLineSeparatorChar(GetChar(pos));
5907 bool LyXParagraph::IsKomma(size_type pos) const
5909 return IsKommaChar(GetChar(pos));
5913 /// Used by the spellchecker
5914 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
5916 unsigned char c = GetChar(pos);
5917 if (IsLetterChar(c))
5919 // '\0' is not a letter, allthough every string contains "" (below)
5922 // We want to pass the ' and escape chars to ispell
5923 string extra = lyxrc->isp_esc_chars + '\'';
5927 return contains(extra, ch);
5931 bool LyXParagraph::IsWord(size_type pos ) const
5933 return IsWordChar(GetChar(pos)) ;
5937 LyXDirection LyXParagraph::getParDirection() const
5939 if (!lyxrc->rtl_support || table)
5940 return LYX_DIR_LEFT_TO_RIGHT;
5943 return (getFont(0).direction() == LyXFont::RTL_DIR)
5944 ? LYX_DIR_RIGHT_TO_LEFT : LYX_DIR_LEFT_TO_RIGHT;
5946 return current_view->buffer()->params.getDocumentDirection();
5951 LyXParagraph::getLetterDirection(LyXParagraph::size_type pos) const
5953 if (!lyxrc->rtl_support)
5954 return LYX_DIR_LEFT_TO_RIGHT;
5956 LyXDirection direction = getFont(pos).getFontDirection();
5957 if (IsLineSeparator(pos) && 0 < pos && pos < Last() - 1
5958 && !IsLineSeparator(pos + 1)
5959 && !(table && IsNewline(pos + 1))
5960 && (getFont(pos - 1).getFontDirection() != direction
5961 || getFont(pos + 1).getFontDirection() != direction))
5962 return getParDirection();