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 extern void addNewlineAndDepth(string & file, int const depth); // Jug 990923
39 int tex_code_break_column = 72; // needs non-zero initialization. set later.
40 // this is a bad idea, but how can LyXParagraph find its buffer to get
41 // parameters? (JMarc)
42 extern BufferView * current_view;
47 extern string bibitemWidthest(Painter &);
49 // this is a minibuffer
50 static char minibuffer_char;
51 static LyXFont minibuffer_font;
52 static Inset * minibuffer_inset;
55 // Initialization of the counter for the paragraph id's,
56 // declared in lyxparagraph.h
57 unsigned int LyXParagraph::paragraph_id = 0;
60 LyXParagraph::LyXParagraph()
62 text.reserve(500); // is this number too big?
64 for (int i = 0; i < 10; ++i) setCounter(i , 0);
70 footnoteflag = LyXParagraph::NO_FOOTNOTE;
71 footnotekind = LyXParagraph::FOOTNOTE; // should not be needed
73 align = LYX_ALIGN_BLOCK;
75 /* table stuff -- begin*/
77 /* table stuff -- end*/
79 bibkey = 0; // ale970302
84 // This konstruktor inserts the new paragraph in a list.
85 LyXParagraph::LyXParagraph(LyXParagraph * par)
88 par->text.resize(par->text.size());
90 for (int i = 0; i < 10; ++i) setCounter(i, 0);
94 // double linked list begin
97 next->previous = this;
99 previous->next = this;
101 footnoteflag = LyXParagraph::NO_FOOTNOTE;
102 footnotekind = LyXParagraph::FOOTNOTE;
104 /* table stuff -- begin*/
106 /* table stuff -- end*/
107 id_ = paragraph_id++;
109 bibkey = 0; // ale970302
115 void LyXParagraph::writeFile(ostream & os, BufferParams & params,
116 char footflag, char dth)
118 LyXFont font1, font2;
124 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
126 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
128 // The beginning or the end of a footnote environment?
129 if (footflag != footnoteflag) {
130 footflag = footnoteflag;
132 os << "\n\\begin_float "
133 << string_footnotekinds[footnotekind]
136 os << "\n\\end_float ";
140 // The beginning or end of a deeper (i.e. nested) area?
143 while (depth > dth) {
144 os << "\n\\begin_deeper ";
148 while (depth < dth) {
149 os << "\n\\end_deeper ";
155 // First write the layout
157 << textclasslist.NameOfLayout(params.textclass, layout)
160 // Maybe some vertical spaces.
161 if (added_space_top.kind() != VSpace::NONE)
162 os << "\\added_space_top "
163 << added_space_top.asLyXCommand() << " ";
164 if (added_space_bottom.kind() != VSpace::NONE)
165 os << "\\added_space_bottom "
166 << added_space_bottom.asLyXCommand() << " ";
168 // The labelwidth string used in lists.
169 if (!labelwidthstring.empty())
170 os << "\\labelwidthstring "
171 << labelwidthstring << '\n';
173 // Lines above or below?
177 os << "\\line_bottom ";
179 // Pagebreaks above or below?
181 os << "\\pagebreak_top ";
182 if (pagebreak_bottom)
183 os << "\\pagebreak_bottom ";
185 // Start of appendix?
186 if (start_of_appendix)
187 os << "\\start_of_appendix ";
194 if (align != LYX_ALIGN_LAYOUT) {
196 case LYX_ALIGN_LEFT: h = 1; break;
197 case LYX_ALIGN_RIGHT: h = 2; break;
198 case LYX_ALIGN_CENTER: h = 3; break;
199 default: h = 0; break;
201 os << "\\align " << string_align[h] << " ";
203 if (pextra_type != PEXTRA_NONE) {
204 os << "\\pextra_type " << pextra_type;
205 if (pextra_type == PEXTRA_MINIPAGE) {
206 os << " \\pextra_alignment "
209 os << " \\pextra_hfill "
211 if (pextra_start_minipage)
212 os << " \\pextra_start_minipage "
213 << pextra_start_minipage;
215 if (!pextra_width.empty()) {
216 os << " \\pextra_width "
217 << VSpace(pextra_width).asLyXCommand();
218 } else if (!pextra_widthp.empty()) {
219 os << " \\pextra_widthp "
225 // Dummy layout. This means that a footnote ended.
226 os << "\n\\end_float ";
227 footflag = LyXParagraph::NO_FOOTNOTE;
230 // It might be a table.
232 os << "\\LyXTable\n";
240 font1 = LyXFont(LyXFont::ALL_INHERIT);
243 for (size_type i = 0; i < size(); ++i) {
249 // Write font changes
250 font2 = GetFontSettings(i);
251 if (font2 != font1) {
252 font2.lyxWriteChanges(font1, os);
262 if (inset->DirectWrite()) {
263 // international char, let it write
264 // code directly so it's shorter in
268 os << "\n\\begin_inset ";
270 os << "\n\\end_inset \n\n";
275 os << "\n\\newline \n";
279 os << "\n\\hfill \n";
282 case META_PROTECTED_SEPARATOR:
283 os << "\n\\protected_separator \n";
287 os << "\n\\backslash \n";
291 if (i + 1 < size() && GetChar(i + 1) == ' ') {
298 if ((column > 70 && c == ' ')
303 // this check is to amend a bug. LyX sometimes
304 // inserts '\0' this could cause problems.
308 lyxerr << "ERROR (LyXParagraph::writeFile):"
309 " NULL char in structure." << endl;
315 // now write the next paragraph
317 next->writeFile(os, params, footflag, dth);
321 void LyXParagraph::validate(LaTeXFeatures & features) const
323 // this will be useful later
324 LyXLayout const & layout =
325 textclasslist.Style(current_view->buffer()->params.textclass,
329 if (line_top || line_bottom)
330 features.lyxline = true;
333 features.layout[GetLayout()] = true;
336 for (FontList::const_iterator cit = fontlist.begin();
337 cit != fontlist.end(); ++cit) {
338 if ((*cit).font.noun() == LyXFont::ON) {
339 lyxerr[Debug::LATEX] << "font.noun: "
340 << (*cit).font.noun()
342 features.noun = true;
343 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
344 << (*cit).font.stateText()
347 switch ((*cit).font.color()) {
349 case LColor::inherit:
353 features.color = true;
354 lyxerr[Debug::LATEX] << "Color enabled. Font: "
355 << (*cit).font.stateText()
361 for (InsetList::const_iterator cit = insetlist.begin();
362 cit != insetlist.end(); ++cit) {
364 (*cit).inset->Validate(features);
367 if (table && table->IsLongTable())
368 features.longtable = true;
369 if (pextra_type == PEXTRA_INDENT)
370 features.LyXParagraphIndent = true;
371 if (pextra_type == PEXTRA_FLOATFLT)
372 features.floatflt = true;
373 if (layout.needprotect
374 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
375 features.NeedLyXFootnoteCode = true;
376 if ((current_view->buffer()->params.paragraph_separation == BufferParams::PARSEP_INDENT) &&
377 (pextra_type == LyXParagraph::PEXTRA_MINIPAGE))
378 features.NeedLyXMinipageIndent = true;
379 if (table && table->NeedRotating())
380 features.rotating = true;
381 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
382 features.algorithm = true;
386 // First few functions needed for cut and paste and paragraph breaking.
387 void LyXParagraph::CopyIntoMinibuffer(LyXParagraph::size_type pos) const
389 minibuffer_char = GetChar(pos);
390 minibuffer_font = GetFontSettings(pos);
391 minibuffer_inset = 0;
392 if (minibuffer_char == LyXParagraph::META_INSET) {
394 minibuffer_inset = GetInset(pos)->Clone();
396 minibuffer_inset = 0;
397 minibuffer_char = ' ';
398 // This reflects what GetInset() does (ARRae)
404 void LyXParagraph::CutIntoMinibuffer(LyXParagraph::size_type pos)
406 minibuffer_char = GetChar(pos);
407 minibuffer_font = GetFontSettings(pos);
408 minibuffer_inset = 0;
409 if (minibuffer_char == LyXParagraph::META_INSET) {
411 minibuffer_inset = GetInset(pos);
412 // This is a little hack since I want exactly
413 // the inset, not just a clone. Otherwise
414 // the inset would be deleted when calling Erase(pos)
416 for (InsetList::iterator it = insetlist.begin();
417 it != insetlist.end(); ++it) {
418 if ((*it).pos == pos) {
425 minibuffer_inset = 0;
426 minibuffer_char = ' ';
427 // This reflects what GetInset() does (ARRae)
432 // Erase(pos); now the caller is responsible for that.
436 void LyXParagraph::InsertFromMinibuffer(LyXParagraph::size_type pos)
438 InsertChar(pos, minibuffer_char);
439 SetFont(pos, minibuffer_font);
440 if (minibuffer_char == LyXParagraph::META_INSET)
441 InsertInset(pos, minibuffer_inset);
448 void LyXParagraph::Clear()
453 pagebreak_top = false;
454 pagebreak_bottom = false;
456 added_space_top = VSpace(VSpace::NONE);
457 added_space_bottom = VSpace(VSpace::NONE);
459 align = LYX_ALIGN_LAYOUT;
463 pextra_type = PEXTRA_NONE;
464 pextra_width.clear();
465 pextra_widthp.clear();
466 pextra_alignment = MINIPAGE_ALIGN_TOP;
467 pextra_hfill = false;
468 pextra_start_minipage = false;
471 labelwidthstring.clear();
475 start_of_appendix = false;
479 // the destructor removes the new paragraph from the list
480 LyXParagraph::~LyXParagraph()
483 previous->next = next;
485 next->previous = previous;
487 for (InsetList::iterator it = insetlist.begin();
488 it != insetlist.end(); ++it) {
492 /* table stuff -- begin*/
494 /* table stuff -- end*/
501 void LyXParagraph::Erase(LyXParagraph::size_type pos)
503 // > because last is the next unused position, and you can
504 // use it if you want
506 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
507 NextAfterFootnote()->Erase(pos - text.size() - 1);
509 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
510 "position does not exist." << endl;
513 if (pos < size()) { // last is free for insertation, but should be empty
514 // if it is an inset, delete the inset entry
515 if (text[pos] == LyXParagraph::META_INSET) {
517 for (InsetList::iterator it = insetlist.begin();
518 it != insetlist.end(); ++it) {
519 if ((*it).pos == pos) {
526 text.erase(text.begin() + pos);
527 // Erase entries in the tables.
528 for (FontList::iterator it = fontlist.begin();
529 it != fontlist.end(); ++it) {
530 if (pos >= (*it).pos && pos <= (*it).pos_end) {
531 if ((*it).pos == (*it).pos_end) {
532 // If it is a multi-character font
533 // entry, we just make it smaller
534 // (see update below), otherwise we
541 // Update all other entries.
542 for (FontList::iterator it = fontlist.begin();
543 it != fontlist.end(); ++it) {
546 if ((*it).pos_end >= pos)
550 // Update the inset table.
551 for (InsetList::iterator it = insetlist.begin();
552 it != insetlist.end(); ++it) {
557 lyxerr << "ERROR (LyXParagraph::Erase): "
558 "can't erase non-existant char." << endl;
563 void LyXParagraph::InsertChar(LyXParagraph::size_type pos, char c)
565 // > because last is the next unused position, and you can
566 // use it if you want
569 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
570 NextAfterFootnote()->InsertChar(pos - text.size() - 1,
573 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
574 "position does not exist." << endl;
577 text.insert(text.begin() + pos, c);
578 // Update the font table.
579 for (FontList::iterator it = fontlist.begin();
580 it != fontlist.end(); ++it) {
581 if ((*it).pos >= pos)
583 if ((*it).pos_end >= pos)
587 // Update the inset table.
588 for (InsetList::iterator it = insetlist.begin();
589 it != insetlist.end(); ++it) {
590 if ((*it).pos >= pos)
596 void LyXParagraph::InsertInset(LyXParagraph::size_type pos,
599 // > because last is the next unused position, and you can
600 // use it if you want
603 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
605 ->InsertInset(pos - text.size() - 1, inset);
607 lyxerr << "ERROR (LyXParagraph::InsertInset): "
608 "position does not exist: " << pos << endl;
611 if (text[pos] != LyXParagraph::META_INSET) {
612 lyxerr << "ERROR (LyXParagraph::InsertInset): "
613 "there is no LyXParagraph::META_INSET" << endl;
618 // Add a new entry in the inset table.
619 InsetList::iterator it =
620 insetlist.insert(insetlist.begin(), InsetTable());
627 Inset * LyXParagraph::GetInset(LyXParagraph::size_type pos)
631 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
632 return NextAfterFootnote()
633 ->GetInset(pos - text.size() - 1);
635 lyxerr << "ERROR (LyXParagraph::GetInset): "
636 "position does not exist: "
642 for (InsetList::iterator it = insetlist.begin();
643 it != insetlist.end(); ++it) {
644 if ((*it).pos == pos) {
648 lyxerr << "ERROR (LyXParagraph::GetInset): "
649 "Inset does not exist: " << pos << endl;
650 text[pos] = ' '; // WHY!!! does this set the pos to ' '????
651 // Did this commenting out introduce a bug? So far I have not
652 // see any, please enlighten me. (Lgb)
653 // My guess is that since the inset does not exist, we might
654 // as well replace it with a space to prevent craches. (Asger)
659 Inset const * LyXParagraph::GetInset(LyXParagraph::size_type pos) const
663 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
664 return NextAfterFootnote()
665 ->GetInset(pos - text.size() - 1);
667 lyxerr << "ERROR (LyXParagraph::GetInset): "
668 "position does not exist: "
674 for (InsetList::const_iterator cit = insetlist.begin();
675 cit != insetlist.end(); ++cit) {
676 if ((*cit).pos == pos) {
680 lyxerr << "ERROR (LyXParagraph::GetInset): "
681 "Inset does not exist: " << pos << endl;
682 //text[pos] = ' '; // WHY!!! does this set the pos to ' '????
683 // Did this commenting out introduce a bug? So far I have not
684 // see any, please enlighten me. (Lgb)
685 // My guess is that since the inset does not exist, we might
686 // as well replace it with a space to prevent craches. (Asger)
691 // Gets uninstantiated font setting at position.
692 // Optimized after profiling. (Asger)
693 LyXFont LyXParagraph::GetFontSettings(LyXParagraph::size_type pos) const
696 for (FontList::const_iterator cit = fontlist.begin();
697 cit != fontlist.end(); ++cit) {
698 if (pos >= (*cit).pos && pos <= (*cit).pos_end)
702 // > because last is the next unused position, and you can
703 // use it if you want
704 else if (pos > size()) {
706 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
707 return NextAfterFootnote()
708 ->GetFontSettings(pos - text.size() - 1);
710 // Why is it an error to ask for the font of a
711 // position that does not exist? Would it be
712 // enough for this to be enabled on debug?
713 // We want strict error checking, but it's ok to only
714 // have it when debugging. (Asger)
715 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
716 "position does not exist. "
717 << pos << " (" << static_cast<int>(pos)
721 return GetFontSettings(pos - 1);
723 return LyXFont(LyXFont::ALL_INHERIT);
727 // Gets the fully instantiated font at a given position in a paragraph
728 // This is basically the same function as LyXText::GetFont() in text2.C.
729 // The difference is that this one is used for generating the LaTeX file,
730 // and thus cosmetic "improvements" are disallowed: This has to deliver
731 // the true picture of the buffer. (Asger)
732 // If position is -1, we get the layout font of the paragraph.
733 // If position is -2, we get the font of the manual label of the paragraph.
734 LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos) const
737 LyXLayout const & layout =
738 textclasslist.Style(current_view->buffer()->params.textclass,
740 LyXParagraph::size_type main_body = 0;
741 if (layout.labeltype == LABEL_MANUAL)
742 main_body = BeginningOfMainBody();
747 layoutfont = layout.labelfont;
749 layoutfont = layout.font;
750 tmpfont = GetFontSettings(pos);
751 tmpfont.realize(layoutfont);
753 // process layoutfont for pos == -1 and labelfont for pos < -1
755 tmpfont = layout.font;
757 tmpfont = layout.labelfont;
758 if (getParDirection() == LYX_DIR_RIGHT_TO_LEFT)
759 tmpfont.setDirection(LyXFont::RTL_DIR);
762 // check for environment font information
763 char par_depth = GetDepth();
764 LyXParagraph const * par = this;
765 while (par && par_depth && !tmpfont.resolved()) {
766 par = par->DepthHook(par_depth - 1);
768 tmpfont.realize(textclasslist.
769 Style(current_view->buffer()->params.textclass,
770 par->GetLayout()).font);
771 par_depth = par->GetDepth();
775 tmpfont.realize(textclasslist
776 .TextClass(current_view->buffer()->params.textclass)
782 /// Returns the height of the highest font in range
784 LyXParagraph::HighestFontInRange(LyXParagraph::size_type startpos,
785 LyXParagraph::size_type endpos) const
787 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
788 for (FontList::const_iterator cit = fontlist.begin();
789 cit != fontlist.end(); ++cit) {
790 if (startpos <= (*cit).pos_end && endpos >= (*cit).pos) {
791 LyXFont::FONT_SIZE size = (*cit).font.size();
792 if (size > maxsize && size <= LyXFont::SIZE_HUGER)
800 char LyXParagraph::GetChar(LyXParagraph::size_type pos)
807 // > because last is the next unused position, and you can
808 // use it if you want
809 else if (pos > size()) {
810 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
811 return NextAfterFootnote()
812 ->GetChar(pos - text.size() - 1);
814 lyxerr << "ERROR (LyXParagraph::GetChar): "
815 "position does not exist."
816 << pos << " (" << static_cast<int>(pos)
818 // Assert(false); // This triggers sometimes...
823 // We should have a footnote environment.
824 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
825 // Notice that LyX does request the
826 // last char from time to time. (Asger)
827 //lyxerr << "ERROR (LyXParagraph::GetChar): "
828 // "expected footnote." << endl;
831 switch (next->footnotekind) {
832 case LyXParagraph::FOOTNOTE:
833 return LyXParagraph::META_FOOTNOTE;
834 case LyXParagraph::MARGIN:
835 return LyXParagraph::META_MARGIN;
836 case LyXParagraph::FIG:
837 case LyXParagraph::WIDE_FIG:
838 return LyXParagraph::META_FIG;
839 case LyXParagraph::TAB:
840 case LyXParagraph::WIDE_TAB:
841 return LyXParagraph::META_TAB;
842 case LyXParagraph::ALGORITHM:
843 return LyXParagraph::META_ALGORITHM;
845 return '\0'; // to shut up gcc
850 char LyXParagraph::GetChar(LyXParagraph::size_type pos) const
857 // > because last is the next unused position, and you can
858 // use it if you want
859 else if (pos > size()) {
860 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
861 return NextAfterFootnote()
862 ->GetChar(pos - text.size() - 1);
864 lyxerr << "ERROR (LyXParagraph::GetChar const): "
865 "position does not exist."
866 << pos << " (" << static_cast<int>(pos)
872 // We should have a footnote environment.
873 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
874 // Notice that LyX does request the
875 // last char from time to time. (Asger)
876 //lyxerr << "ERROR (LyXParagraph::GetChar): "
877 // "expected footnote." << endl;
880 switch (next->footnotekind) {
881 case LyXParagraph::FOOTNOTE:
882 return LyXParagraph::META_FOOTNOTE;
883 case LyXParagraph::MARGIN:
884 return LyXParagraph::META_MARGIN;
885 case LyXParagraph::FIG:
886 case LyXParagraph::WIDE_FIG:
887 return LyXParagraph::META_FIG;
888 case LyXParagraph::TAB:
889 case LyXParagraph::WIDE_TAB:
890 return LyXParagraph::META_TAB;
891 case LyXParagraph::ALGORITHM:
892 return LyXParagraph::META_ALGORITHM;
894 return '\0'; // to shut up gcc
899 // return an string of the current word, and the end of the word in lastpos.
900 string LyXParagraph::GetWord(LyXParagraph::size_type & lastpos) const
904 // the current word is defined as starting at the first character
905 // from the immediate left of lastpospos which meets the definition
906 // of IsLetter(), continuing to the last character to the right
907 // of this meeting IsLetter.
913 // move back until we have a letter
915 //there's no real reason to have firstpos & lastpos as
916 //separate variables as this is written, but maybe someon
917 // will want to return firstpos in the future.
919 //since someone might have typed a punctuation first
920 int firstpos = lastpos;
922 while ((firstpos >= 0) && !IsLetter(firstpos))
925 // now find the beginning by looking for a nonletter
927 while ((firstpos>= 0) && IsLetter(firstpos))
930 // the above is now pointing to the preceeding non-letter
934 // so copy characters into theword until we get a nonletter
935 // note that this can easily exceed lastpos, wich means
936 // that if used in the middle of a word, the whole word
939 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
946 LyXParagraph::size_type LyXParagraph::Last() const
948 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
949 return text.size() + NextAfterFootnote()->Last() + 1;
950 // the 1 is the symbol
957 LyXParagraph * LyXParagraph::ParFromPos(LyXParagraph::size_type pos)
959 // > because last is the next unused position, and you can
960 // use it if you want
963 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
964 return NextAfterFootnote()
965 ->ParFromPos(pos - text.size() - 1);
967 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
968 "position does not exist." << endl;
975 int LyXParagraph::PositionInParFromPos(LyXParagraph::size_type pos) const
977 // > because last is the next unused position, and you can
978 // use it if you want
981 && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
982 return NextAfterFootnote()
983 ->PositionInParFromPos(pos - text.size() - 1);
986 "ERROR (LyXParagraph::PositionInParFromPos): "
987 "position does not exist." << endl;
995 void LyXParagraph::SetFont(LyXParagraph::size_type pos,
996 LyXFont const & font)
998 // > because last is the next unused position, and you can
999 // use it if you want
1002 next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1003 NextAfterFootnote()->SetFont(pos - text.size() - 1,
1006 lyxerr << "ERROR (LyXParagraph::SetFont): "
1007 "position does not exist." << endl;
1011 LyXFont patternfont(LyXFont::ALL_INHERIT);
1013 // First, reduce font against layout/label font
1014 // Update: The SetCharFont() routine in text2.C already
1015 // reduces font, so we don't need to do that here. (Asger)
1016 // No need to simplify this because it will disappear
1017 // in a new kernel. (Asger)
1018 // Next search font table
1019 FontList::iterator tmp = fontlist.begin();
1020 for (; tmp != fontlist.end(); ++tmp) {
1021 if (pos >= (*tmp).pos && pos <= (*tmp).pos_end) {
1025 if (tmp == fontlist.end()) { // !found
1026 // if we did not find a font entry, but if the font at hand
1027 // is the same as default, we just forget it
1028 if (font == patternfont) return;
1030 // ok, we did not find a font entry. But maybe there is exactly
1031 // the needed font ientry one position left
1032 FontList::iterator tmp2 = fontlist.begin();
1033 for (; tmp2 != fontlist.end(); ++tmp2) {
1034 if (pos - 1 >= (*tmp2).pos
1035 && pos - 1 <= (*tmp2).pos_end)
1038 if (tmp2 != fontlist.end()) {
1039 // ok there is one, maybe it is exactly
1041 if ((*tmp2).font == font) {
1042 // put the position under the font
1047 // Add a new entry in the
1048 // fontlist for the position
1052 ft.font = font; // or patternfont
1053 // It seems that using font instead of patternfont here
1054 // fixes all the problems. This also surfaces a "bug" in
1056 fontlist.insert(fontlist.begin(), ft);
1057 } else if ((*tmp).pos != (*tmp).pos_end) { // we found a font entry. maybe we have to split it and create a new one.
1059 // more than one character
1060 if (pos == (*tmp).pos) {
1061 // maybe we should enlarge the left fonttable
1062 FontList::iterator tmp2 = fontlist.begin();
1063 for (; tmp2 != fontlist.end(); ++tmp2) {
1064 if (pos - 1 >= (*tmp2).pos
1065 && pos - 1 <= (*tmp2).pos_end)
1068 // Is there is one, and is it exactly
1070 if (tmp2 != fontlist.end() &&
1071 (*tmp2).font == font) {
1072 // Put the position under the font
1078 // Add a new entry in the
1079 // fontlist for the position
1082 ft.pos_end = (*tmp).pos_end;
1083 ft.font = (*tmp).font;
1084 (*tmp).pos_end = pos;
1086 fontlist.insert(fontlist.begin(), ft);
1087 } else if (pos == (*tmp).pos_end) {
1088 // Add a new entry in the
1089 // fontlist for the position
1091 ft.pos = (*tmp).pos;
1092 ft.pos_end = (*tmp).pos_end - 1;
1093 ft.font = (*tmp).font;
1094 (*tmp).pos = (*tmp).pos_end;
1096 fontlist.insert(fontlist.begin(), ft);
1098 // Add a new entry in the
1099 // fontlist for the position
1101 ft.pos = (*tmp).pos;
1102 ft.pos_end = pos - 1;
1103 ft.font = (*tmp).font;
1107 ft2.pos_end = (*tmp).pos_end;
1108 ft2.font = (*tmp).font;
1111 (*tmp).pos_end = pos;
1114 fontlist.insert(fontlist.begin(), ft);
1115 fontlist.insert(fontlist.begin(), ft2);
1123 // This function is able to hide closed footnotes.
1124 LyXParagraph * LyXParagraph::Next()
1126 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1127 LyXParagraph * tmp = next;
1129 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1131 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1132 return tmp->Next(); /* there can be more than one
1133 footnote in a logical
1136 return next; // This should never happen!
1142 LyXParagraph * LyXParagraph::NextAfterFootnote()
1144 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1145 LyXParagraph * tmp = next;
1146 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1148 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1149 return tmp; /* there can be more than one footnote
1150 in a logical paragraph */
1152 return next; // This should never happen!
1158 LyXParagraph const * LyXParagraph::NextAfterFootnote() const
1160 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1161 LyXParagraph * tmp = next;
1162 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1164 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1165 return tmp; /* there can be more than one footnote
1166 in a logical paragraph */
1168 return next; // This should never happen!
1174 LyXParagraph * LyXParagraph::PreviousBeforeFootnote()
1177 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1179 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1180 tmp = tmp->previous;
1181 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1182 return tmp; /* there can be more than one footnote
1183 in a logical paragraph */
1185 return previous; // This should never happen!
1191 LyXParagraph * LyXParagraph::LastPhysicalPar()
1193 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1196 LyXParagraph * tmp = this;
1198 && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1199 tmp = tmp->NextAfterFootnote();
1206 LyXParagraph * LyXParagraph::FirstPhysicalPar()
1210 LyXParagraph * tmppar = this;
1214 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1215 tmppar = tmppar->previous;
1224 LyXParagraph const * LyXParagraph::FirstPhysicalPar() const
1228 LyXParagraph const * tmppar = this;
1232 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1233 tmppar = tmppar->previous;
1242 // This function is able to hide closed footnotes.
1243 LyXParagraph * LyXParagraph::Previous()
1245 LyXParagraph * tmp = previous;
1250 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1251 tmp = tmp->previous;
1253 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1254 tmp = tmp->previous;
1255 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1256 return tmp->next->Previous();
1265 // This function is able to hide closed footnotes.
1266 LyXParagraph const * LyXParagraph::Previous() const
1268 LyXParagraph * tmp = previous;
1273 && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1274 tmp = tmp->previous;
1276 && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1277 tmp = tmp->previous;
1278 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1279 return tmp->next->Previous();
1288 void LyXParagraph::BreakParagraph(LyXParagraph::size_type pos,
1291 size_type i, pos_end, pos_first;
1292 // create a new paragraph
1293 LyXParagraph * par = ParFromPos(pos);
1294 LyXParagraph * firstpar = FirstPhysicalPar();
1296 LyXParagraph * tmp = new LyXParagraph(par);
1298 tmp->footnoteflag = footnoteflag;
1299 tmp->footnotekind = footnotekind;
1301 // this is an idea for a more userfriendly layout handling, I will
1302 // see what the users say
1304 // layout stays the same with latex-environments
1306 tmp->SetOnlyLayout(firstpar->layout);
1307 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1310 if (Last() > pos || !Last() || flag == 2) {
1311 tmp->SetOnlyLayout(firstpar->layout);
1312 tmp->align = firstpar->align;
1313 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1315 tmp->line_bottom = firstpar->line_bottom;
1316 firstpar->line_bottom = false;
1317 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1318 firstpar->pagebreak_bottom = false;
1319 tmp->added_space_bottom = firstpar->added_space_bottom;
1320 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1322 tmp->depth = firstpar->depth;
1323 tmp->noindent = firstpar->noindent;
1325 // copy everything behind the break-position
1326 // to the new paragraph
1328 while (ParFromPos(pos_first) != par)
1331 pos_end = pos_first + par->text.size() - 1;
1332 // The constructor has already reserved 500 elements
1333 //if (pos_end > pos)
1334 // tmp->text.reserve(pos_end - pos);
1336 for (i = pos; i <= pos_end; ++i) {
1337 par->CutIntoMinibuffer(i - pos_first);
1338 tmp->InsertFromMinibuffer(i - pos);
1340 tmp->text.resize(tmp->text.size());
1341 for (i = pos_end; i >= pos; --i)
1342 par->Erase(i - pos_first);
1344 par->text.resize(par->text.size());
1347 // just an idea of me
1349 tmp->line_top = firstpar->line_top;
1350 tmp->pagebreak_top = firstpar->pagebreak_top;
1351 tmp->added_space_top = firstpar->added_space_top;
1352 tmp->bibkey = firstpar->bibkey;
1354 // layout stays the same with latex-environments
1356 firstpar->SetOnlyLayout(tmp->layout);
1357 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1358 firstpar->depth = tmp->depth;
1364 void LyXParagraph::MakeSameLayout(LyXParagraph const * par)
1366 par = par->FirstPhysicalPar();
1367 footnoteflag = par->footnoteflag;
1368 footnotekind = par->footnotekind;
1370 layout = par->layout;
1371 align = par-> align;
1372 SetLabelWidthString(par->labelwidthstring);
1374 line_bottom = par->line_bottom;
1375 pagebreak_bottom = par->pagebreak_bottom;
1376 added_space_bottom = par->added_space_bottom;
1378 line_top = par->line_top;
1379 pagebreak_top = par->pagebreak_top;
1380 added_space_top = par->added_space_top;
1382 pextra_type = par->pextra_type;
1383 pextra_width = par->pextra_width;
1384 pextra_widthp = par->pextra_widthp;
1385 pextra_alignment = par->pextra_alignment;
1386 pextra_hfill = par->pextra_hfill;
1387 pextra_start_minipage = par->pextra_start_minipage;
1389 noindent = par->noindent;
1394 LyXParagraph * LyXParagraph::FirstSelfrowPar()
1396 LyXParagraph * tmppar = this;
1399 && tmppar->previous->footnoteflag ==
1400 LyXParagraph::CLOSED_FOOTNOTE)
1401 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1402 tmppar = tmppar->previous;
1405 return this; // This should never happen!
1411 LyXParagraph * LyXParagraph::Clone() const
1413 // create a new paragraph
1414 LyXParagraph * result = new LyXParagraph;
1416 result->MakeSameLayout(this);
1418 // this is because of the dummy layout of the paragraphs that
1420 result->layout = layout;
1422 /* table stuff -- begin*/
1424 result->table = table->Clone();
1427 /* table stuff -- end*/
1430 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1433 // copy everything behind the break-position to the new paragraph
1435 for (size_type i = 0; i < size(); ++i) {
1436 CopyIntoMinibuffer(i);
1437 result->InsertFromMinibuffer(i);
1439 result->text.resize(result->text.size());
1444 bool LyXParagraph::HasSameLayout(LyXParagraph const * par) const
1446 par = par->FirstPhysicalPar();
1449 par->footnoteflag == footnoteflag &&
1450 par->footnotekind == footnotekind &&
1452 par->layout == layout &&
1454 par->align == align &&
1456 par->line_bottom == line_bottom &&
1457 par->pagebreak_bottom == pagebreak_bottom &&
1458 par->added_space_bottom == added_space_bottom &&
1460 par->line_top == line_top &&
1461 par->pagebreak_top == pagebreak_top &&
1462 par->added_space_top == added_space_top &&
1464 par->pextra_type == pextra_type &&
1465 par->pextra_width == pextra_width &&
1466 par->pextra_widthp == pextra_widthp &&
1467 par->pextra_alignment == pextra_alignment &&
1468 par->pextra_hfill == pextra_hfill &&
1469 par->pextra_start_minipage == pextra_start_minipage &&
1471 par->table == table && // what means: NO TABLE AT ALL
1473 par->noindent == noindent &&
1474 par->depth == depth);
1478 void LyXParagraph::BreakParagraphConservative(LyXParagraph::size_type pos)
1480 // create a new paragraph
1481 LyXParagraph * par = ParFromPos(pos);
1483 LyXParagraph * tmp = new LyXParagraph(par);
1485 tmp->MakeSameLayout(par);
1487 // When can pos < Last()?
1488 // I guess pos == Last() is possible.
1490 // copy everything behind the break-position to the new
1492 size_type pos_first = 0;
1493 while (ParFromPos(pos_first) != par)
1495 size_type pos_end = pos_first + par->text.size() - 1;
1496 // make sure there is enough memory for the now larger
1497 // paragraph. This is not neccessary, because
1498 // InsertFromMinibuffer will enlarge the memory (it uses
1499 // InsertChar of course). But doing it by hand
1500 // is MUCH faster! (only one time, not thousend times!!)
1501 // Not needed since the constructor aleady have
1502 // reserved 500 elements in text.
1503 //if (pos_end > pos)
1504 // tmp->text.reserve(pos_end - pos);
1506 for (size_type i = pos; i <= pos_end; ++i) {
1507 par->CutIntoMinibuffer(i - pos_first);
1508 tmp->InsertFromMinibuffer(i - pos);
1510 tmp->text.resize(tmp->text.size());
1511 for (size_type i = pos_end; i >= pos; --i)
1512 par->Erase(i - pos_first);
1514 par->text.resize(par->text.size());
1519 // Be carefull, this does not make any check at all.
1520 void LyXParagraph::PasteParagraph()
1522 // copy the next paragraph to this one
1523 LyXParagraph * the_next = Next();
1525 LyXParagraph * firstpar = FirstPhysicalPar();
1527 // first the DTP-stuff
1528 firstpar->line_bottom = the_next->line_bottom;
1529 firstpar->added_space_bottom = the_next->added_space_bottom;
1530 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1532 size_type pos_end = the_next->text.size() - 1;
1533 size_type pos_insert = Last();
1535 // ok, now copy the paragraph
1536 for (size_type i = 0; i <= pos_end; ++i) {
1537 the_next->CutIntoMinibuffer(i);
1538 InsertFromMinibuffer(pos_insert + i);
1541 // delete the next paragraph
1546 void LyXParagraph::OpenFootnote(LyXParagraph::size_type pos)
1548 LyXParagraph * par = ParFromPos(pos);
1550 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1551 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1557 void LyXParagraph::CloseFootnote(LyXParagraph::size_type pos)
1559 LyXParagraph * par = ParFromPos(pos);
1561 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1562 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1568 LyXTextClass::LayoutList::size_type LyXParagraph::GetLayout() const
1570 return FirstPhysicalPar()->layout;
1574 char LyXParagraph::GetDepth() const
1576 return FirstPhysicalPar()->depth;
1580 char LyXParagraph::GetAlign() const
1582 return FirstPhysicalPar()->align;
1586 string LyXParagraph::GetLabestring() const
1588 return FirstPhysicalPar()->labelstring;
1592 int LyXParagraph::GetFirstCounter(int i) const
1594 return FirstPhysicalPar()->counter_[i];
1598 // the next two functions are for the manual labels
1599 string LyXParagraph::GetLabelWidthString() const
1601 if (!FirstPhysicalPar()->labelwidthstring.empty())
1602 return FirstPhysicalPar()->labelwidthstring;
1604 return _("Senseless with this layout!");
1608 void LyXParagraph::SetLabelWidthString(string const & s)
1610 LyXParagraph * par = FirstPhysicalPar();
1612 par->labelwidthstring = s;
1616 void LyXParagraph::SetOnlyLayout(LyXTextClass::LayoutList::size_type new_layout)
1618 LyXParagraph * par = FirstPhysicalPar();
1619 LyXParagraph * ppar = 0;
1620 LyXParagraph * npar = 0;
1622 par->layout = new_layout;
1623 /* table stuff -- begin*/
1626 /* table stuff -- end*/
1627 if (par->pextra_type == PEXTRA_NONE) {
1628 if (par->Previous()) {
1629 ppar = par->Previous()->FirstPhysicalPar();
1632 && (ppar->depth > par->depth))
1633 ppar = ppar->Previous()->FirstPhysicalPar();
1636 npar = par->Next()->NextAfterFootnote();
1639 && (npar->depth > par->depth))
1640 npar = npar->Next()->NextAfterFootnote();
1642 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1644 p1 = ppar->pextra_width,
1645 p2 = ppar->pextra_widthp;
1646 ppar->SetPExtraType(ppar->pextra_type,
1647 p1.c_str(), p2.c_str());
1649 if ((par->pextra_type == PEXTRA_NONE) &&
1650 npar && (npar->pextra_type != PEXTRA_NONE)) {
1652 p1 = npar->pextra_width,
1653 p2 = npar->pextra_widthp;
1654 npar->SetPExtraType(npar->pextra_type,
1655 p1.c_str(), p2.c_str());
1661 void LyXParagraph::SetLayout(LyXTextClass::LayoutList::size_type new_layout)
1664 * par = FirstPhysicalPar(),
1668 par->layout = new_layout;
1669 par->labelwidthstring.clear();
1670 par->align = LYX_ALIGN_LAYOUT;
1671 par->added_space_top = VSpace(VSpace::NONE);
1672 par->added_space_bottom = VSpace(VSpace::NONE);
1673 /* table stuff -- begin*/
1676 /* table stuff -- end*/
1677 if (par->pextra_type == PEXTRA_NONE) {
1678 if (par->Previous()) {
1679 ppar = par->Previous()->FirstPhysicalPar();
1682 && (ppar->depth > par->depth))
1683 ppar = ppar->Previous()->FirstPhysicalPar();
1686 npar = par->Next()->NextAfterFootnote();
1689 && (npar->depth > par->depth))
1690 npar = npar->Next()->NextAfterFootnote();
1692 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1694 p1 = ppar->pextra_width,
1695 p2 = ppar->pextra_widthp;
1696 ppar->SetPExtraType(ppar->pextra_type,
1697 p1.c_str(), p2.c_str());
1699 if ((par->pextra_type == PEXTRA_NONE) &&
1700 npar && (npar->pextra_type != PEXTRA_NONE)) {
1702 p1 = npar->pextra_width,
1703 p2 = npar->pextra_widthp;
1704 npar->SetPExtraType(npar->pextra_type,
1705 p1.c_str(), p2.c_str());
1711 // if the layout of a paragraph contains a manual label, the beginning of the
1712 // main body is the beginning of the second word. This is what the par-
1713 // function returns. If the layout does not contain a label, the main
1714 // body always starts with position 0. This differentiation is necessary,
1715 // because there cannot be a newline or a blank <= the beginning of the
1716 // main body in TeX.
1718 int LyXParagraph::BeginningOfMainBody() const
1720 if (FirstPhysicalPar() != this)
1723 // Unroll the first two cycles of the loop
1724 // and remember the previous character to
1725 // remove unnecessary GetChar() calls
1728 && GetChar(i) != LyXParagraph::META_NEWLINE) {
1730 char previous_char, temp;
1732 && (previous_char = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1733 // Yes, this ^ is supposed to be "= " not "=="
1736 && previous_char != ' '
1737 && (temp = GetChar(i)) != LyXParagraph::META_NEWLINE) {
1739 previous_char = temp;
1744 if (i == 0 && i == size() &&
1745 !(footnoteflag == LyXParagraph::NO_FOOTNOTE
1746 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1747 ++i; /* the cursor should not jump
1748 * to the main body if there
1754 LyXParagraph * LyXParagraph::DepthHook(int deth)
1756 LyXParagraph * newpar = this;
1761 newpar = newpar->FirstPhysicalPar()->Previous();
1762 } while (newpar && newpar->GetDepth() > deth
1763 && newpar->footnoteflag == footnoteflag);
1766 if (Previous() || GetDepth())
1767 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1771 return newpar->FirstPhysicalPar();
1775 LyXParagraph const * LyXParagraph::DepthHook(int deth) const
1777 LyXParagraph const * newpar = this;
1782 newpar = newpar->FirstPhysicalPar()->Previous();
1783 } while (newpar && newpar->GetDepth() > deth
1784 && newpar->footnoteflag == footnoteflag);
1787 if (Previous() || GetDepth())
1788 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1792 return newpar->FirstPhysicalPar();
1796 int LyXParagraph::AutoDeleteInsets()
1798 vector<size_type> tmpvec;
1800 for (InsetList::iterator it = insetlist.begin();
1801 it != insetlist.end(); ++it) {
1802 if ((*it).inset && (*it).inset->AutoDelete()) {
1803 tmpvec.push_back((*it).pos);
1807 for (vector<size_type>::const_iterator cit = tmpvec.begin();
1808 cit != tmpvec.end(); ++cit) {
1815 Inset * LyXParagraph::ReturnNextInsetPointer(LyXParagraph::size_type & pos)
1817 InsetList::iterator it2 = insetlist.end();
1818 for (InsetList::iterator it = insetlist.begin();
1819 it != insetlist.end(); ++it) {
1820 if ((*it).pos >= pos) {
1821 if (it2 == insetlist.end() || (*it).pos < (*it2).pos)
1825 if (it2 != insetlist.end()) {
1827 return (*it2).inset;
1833 // returns -1 if inset not found
1834 int LyXParagraph::GetPositionOfInset(Inset * inset) const
1837 for (InsetList::const_iterator cit = insetlist.begin();
1838 cit != insetlist.end(); ++cit) {
1839 if ((*cit).inset == inset) {
1843 // Think about footnotes.
1844 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
1845 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1847 NextAfterFootnote()->GetPositionOfInset(inset);
1849 return text.size() + 1 + further;
1855 void LyXParagraph::readSimpleWholeFile(istream & is)
1861 InsertChar(text.size(), c);
1866 LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow,
1867 string & foot, TexRow & foot_texrow,
1870 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
1871 LyXParagraph * par = next;
1872 LyXLayout const & style =
1873 textclasslist.Style(current_view->buffer()->params.textclass,
1876 bool further_blank_line = false;
1878 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1880 if (start_of_appendix) {
1881 file += "\\appendix\n";
1885 if (tex_code_break_column && style.isCommand()){
1890 if (pagebreak_top) {
1891 file += "\\newpage";
1892 further_blank_line = true;
1894 if (added_space_top.kind() != VSpace::NONE) {
1895 file += added_space_top.asLatexCommand();
1896 further_blank_line = true;
1900 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
1901 file += "\\vspace{-1\\parskip}";
1902 further_blank_line = true;
1905 if (further_blank_line){
1910 LyXDirection direction = getParDirection();
1911 LyXDirection global_direction =
1912 current_view->buffer()->params.getDocumentDirection();
1913 if (direction != global_direction) {
1914 if (direction == LYX_DIR_LEFT_TO_RIGHT)
1915 file += "\\unsethebrew\n";
1917 file += "\\sethebrew\n";
1922 switch (style.latextype) {
1925 file += style.latexname();
1926 file += style.latexparam();
1928 case LATEX_ITEM_ENVIRONMENT:
1930 bibkey->Latex(file, false);
1934 case LATEX_LIST_ENVIRONMENT:
1941 bool need_par = SimpleTeXOnePar(file, texrow);
1943 // Spit out footnotes
1944 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
1945 && par->footnoteflag != footnoteflag) {
1946 par = par->TeXFootnote(file, texrow,
1947 foot, foot_texrow, foot_count,
1949 par->SimpleTeXOnePar(file, texrow);
1953 // Make sure that \\par is done with the font of the last
1954 // character if this has another size as the default.
1955 // This is necessary because LaTeX (and LyX on the screen)
1956 // calculates the space between the baselines according
1957 // to this font. (Matthias)
1958 LyXFont font = getFont(Last()-1);
1960 if (style.resfont.size() != font.size()) {
1962 file += font.latexSize();
1966 } else if (textclasslist.Style(current_view->buffer()->params.textclass,
1967 GetLayout()).isCommand()){
1968 if (style.resfont.size() != font.size()) {
1970 file += font.latexSize();
1974 } else if (style.resfont.size() != font.size()){
1975 file += "{\\" + font.latexSize() + " \\par}";
1978 if (direction != global_direction)
1979 if (direction == LYX_DIR_LEFT_TO_RIGHT)
1980 file += "\\sethebrew";
1982 file += "\\unsethebrew";
1984 switch (style.latextype) {
1985 case LATEX_ITEM_ENVIRONMENT:
1986 case LATEX_LIST_ENVIRONMENT:
1987 if (par && (depth < par->depth)) {
1992 case LATEX_ENVIRONMENT:
1993 // if its the last paragraph of the current environment
1994 // skip it otherwise fall through
1996 && (par->layout != layout
1997 || par->depth != depth
1998 || par->pextra_type != pextra_type))
2001 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2002 && footnotekind != LyXParagraph::FOOTNOTE
2003 && footnotekind != LyXParagraph::MARGIN
2007 // don't insert this if we would be adding it
2008 // before or after a table in a float. This
2009 // little trick is needed in order to allow
2010 // use of tables in \subfigures or \subtables.
2016 further_blank_line = false;
2018 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2019 further_blank_line = true;
2022 if (added_space_bottom.kind() != VSpace::NONE) {
2023 file += added_space_bottom.asLatexCommand();
2024 further_blank_line = true;
2027 if (pagebreak_bottom) {
2028 file += "\\newpage";
2029 further_blank_line = true;
2032 if (further_blank_line){
2037 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2038 par->footnoteflag == LyXParagraph::NO_FOOTNOTE)) {
2043 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2048 // This one spits out the text of the paragraph
2049 bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow)
2051 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2054 return SimpleTeXOneTablePar(file, texrow);
2057 size_type main_body;
2059 bool return_value = false;
2061 LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass, GetLayout());
2062 LyXFont basefont, last_font;
2064 // Maybe we have to create a optional argument.
2065 if (style.labeltype != LABEL_MANUAL)
2068 main_body = BeginningOfMainBody();
2070 if (main_body > 0) {
2072 basefont = getFont(-2); // Get label font
2074 basefont = getFont(-1); // Get layout font
2082 if (style.isCommand()) {
2085 } else if (align != LYX_ALIGN_LAYOUT) {
2088 return_value = true;
2092 // Which font is currently active?
2093 LyXFont running_font = basefont;
2094 // Do we have an open font change?
2095 bool open_font = false;
2097 texrow.start(this, 0);
2099 for (size_type i = 0; i < size(); ++i) {
2101 // First char in paragraph or after label?
2102 if (i == main_body && !IsDummy()) {
2103 if (main_body > 0) {
2105 column += running_font.latexWriteEndChanges(file, basefont, basefont);
2108 basefont = getFont(-1); // Now use the layout font
2109 running_font = basefont;
2113 if (style.isCommand()) {
2116 } else if (align != LYX_ALIGN_LAYOUT) {
2119 return_value = true;
2123 file += "\\noindent ";
2127 case LYX_ALIGN_NONE:
2128 case LYX_ALIGN_BLOCK:
2129 case LYX_ALIGN_LAYOUT:
2130 case LYX_ALIGN_SPECIAL: break;
2131 case LYX_ALIGN_LEFT:
2132 file += "\\raggedright ";
2135 case LYX_ALIGN_RIGHT:
2136 file += "\\raggedleft ";
2139 case LYX_ALIGN_CENTER:
2140 file += "\\centering ";
2148 // Fully instantiated font
2149 LyXFont font = getFont(i);
2150 last_font = running_font;
2152 // Spaces at end of font change are simulated to be
2153 // outside font change, i.e. we write "\textXX{text} "
2154 // rather than "\textXX{text }". (Asger)
2155 if (open_font && c == ' ' && i <= size() - 2
2156 && !getFont(i+1).equalExceptLatex(running_font)
2157 && !getFont(i+1).equalExceptLatex(font)) {
2158 font = getFont(i + 1);
2160 // We end font definition before blanks
2161 if (!font.equalExceptLatex(running_font) && open_font) {
2162 column += running_font.latexWriteEndChanges(file,
2164 (i == main_body-1) ? basefont : font);
2165 running_font = basefont;
2169 // Blanks are printed before start of fontswitch
2171 // Do not print the separation of the optional argument
2172 if (i != main_body - 1) {
2173 SimpleTeXBlanks(file, texrow, i,
2174 column, font, style);
2178 // Do we need to change font?
2179 if (!font.equalExceptLatex(running_font)
2180 && i != main_body-1) {
2181 column += font.latexWriteStartChanges(file, basefont, last_font);
2182 running_font = font;
2186 if (c == LyXParagraph::META_NEWLINE) {
2187 // newlines are handled differently here than
2188 // the default in SimpleTeXSpecialChars().
2189 if (!style.newline_allowed
2190 || font.latex() == LyXFont::ON) {
2194 column += running_font.latexWriteEndChanges(file, basefont, basefont);
2197 basefont = getFont(-1);
2198 running_font = basefont;
2199 if (font.family() ==
2200 LyXFont::TYPEWRITER_FAMILY) {
2206 texrow.start(this, i + 1);
2209 SimpleTeXSpecialChars(file, texrow,
2210 font, running_font, basefont,
2211 open_font, style, i, column, c);
2215 // If we have an open font definition, we have to close it
2217 running_font.latexWriteEndChanges(file, basefont, basefont);
2220 // Needed if there is an optional argument but no contents.
2221 if (main_body > 0 && main_body == size()) {
2223 return_value = false;
2226 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2227 return return_value;
2231 // This one spits out the text of a table paragraph
2232 bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow)
2234 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2236 bool return_value = false;
2238 LyXLayout const & style =
2239 textclasslist.Style(current_view->buffer()->params.textclass,
2243 if (!IsDummy()) { // it is dummy if it is in a float!!!
2244 if (style.isCommand()) {
2247 } else if (align != LYX_ALIGN_LAYOUT) {
2250 return_value = true;
2253 file += "\\noindent ";
2257 case LYX_ALIGN_NONE:
2258 case LYX_ALIGN_BLOCK:
2259 case LYX_ALIGN_LAYOUT:
2260 case LYX_ALIGN_SPECIAL: break;
2261 case LYX_ALIGN_LEFT:
2262 file += "\\raggedright ";
2265 case LYX_ALIGN_RIGHT:
2266 file += "\\raggedleft ";
2269 case LYX_ALIGN_CENTER:
2270 file += "\\centering ";
2276 LyXFont basefont = getFont(-1); // Get layout font
2277 // Which font is currently active?
2278 LyXFont running_font = basefont;
2280 // Do we have an open font change?
2281 bool open_font = false;
2282 int current_cell_number = -1;
2283 int tmp = table->TexEndOfCell(file, current_cell_number);
2284 for (; tmp > 0 ; --tmp)
2287 texrow.start(this, 0);
2289 for (size_type i = 0; i < size(); ++i) {
2290 char c = GetChar(i);
2291 if (table->IsContRow(current_cell_number + 1)) {
2292 if (c == LyXParagraph::META_NEWLINE)
2293 ++current_cell_number;
2298 // Fully instantiated font
2299 LyXFont font = getFont(i);
2300 last_font = running_font;
2302 // Spaces at end of font change are simulated to be
2303 // outside font change.
2304 // i.e. we write "\textXX{text} " rather than
2305 // "\textXX{text }". (Asger)
2306 if (open_font && c == ' ' && i <= size() - 2
2307 && getFont(i+1) != running_font && getFont(i+1) != font) {
2308 font = getFont(i+1);
2311 // We end font definition before blanks
2312 if (font != running_font && open_font) {
2313 column += running_font.latexWriteEndChanges(file,
2315 running_font = basefont;
2318 // Blanks are printed before start of fontswitch
2320 SimpleTeXBlanks(file, texrow, i, column, font, style);
2322 // Do we need to change font?
2323 if (font != running_font) {
2324 column += font.latexWriteStartChanges(file, basefont, last_font);
2325 running_font = font;
2328 // Do we need to turn on LaTeX mode?
2329 if (font.latex() != running_font.latex()) {
2330 if (font.latex() == LyXFont::ON
2331 && style.needprotect) {
2332 file += "\\protect ";
2336 if (c == LyXParagraph::META_NEWLINE) {
2337 // special case for inside a table
2338 // different from default case in
2339 // SimpleTeXSpecialChars()
2341 column += running_font
2342 .latexWriteEndChanges(file, basefont, basefont);
2345 basefont = getFont(-1);
2346 running_font = basefont;
2347 ++current_cell_number;
2348 if (table->CellHasContRow(current_cell_number) >= 0) {
2349 TeXContTableRows(file, i + 1,
2350 current_cell_number,
2353 // if this cell follow only ContRows till end don't
2354 // put the EndOfCell because it is put after the
2356 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2357 --current_cell_number;
2360 int tmp = table->TexEndOfCell(file,
2361 current_cell_number);
2364 } else if (tmp < 0) {
2370 texrow.start(this, i + 1);
2372 SimpleTeXSpecialChars(file, texrow,
2373 font, running_font, basefont,
2374 open_font, style, i, column, c);
2378 // If we have an open font definition, we have to close it
2380 running_font.latexWriteEndChanges(file, basefont, basefont);
2382 ++current_cell_number;
2383 tmp = table->TexEndOfCell(file, current_cell_number);
2384 for (; tmp > 0; --tmp)
2386 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2387 return return_value;
2391 // This one spits out the text off ContRows in tables
2392 bool LyXParagraph::TeXContTableRows(string & file,
2393 LyXParagraph::size_type i,
2394 int current_cell_number,
2395 int & column, TexRow & texrow)
2397 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2403 bool return_value = false;
2404 LyXLayout const & style =
2405 textclasslist.Style(current_view->buffer()->params.textclass,
2407 LyXFont basefont = getFont(-1); // Get layout font
2409 // Which font is currently active?
2410 LyXFont running_font = basefont;
2411 // Do we have an open font change?
2412 bool open_font = false;
2414 size_type lastpos = i;
2415 int cell = table->CellHasContRow(current_cell_number);
2416 ++current_cell_number;
2418 // first find the right position
2420 for (; (i < size()) && (current_cell_number<cell); ++i) {
2422 if (c == LyXParagraph::META_NEWLINE)
2423 ++current_cell_number;
2427 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2431 } else if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2436 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2440 // Fully instantiated font
2441 LyXFont font = getFont(i);
2442 last_font = running_font;
2444 // Spaces at end of font change are simulated to
2445 // be outside font change. i.e. we write
2446 // "\textXX{text} " rather than "\textXX{text }".
2448 if (open_font && c == ' ' && i <= size() - 2
2449 && getFont(i + 1) != running_font
2450 && getFont(i + 1) != font) {
2451 font = getFont(i + 1);
2454 // We end font definition before blanks
2455 if (font != running_font && open_font) {
2456 column += running_font.latexWriteEndChanges(file, basefont, font);
2457 running_font = basefont;
2460 // Blanks are printed before start of fontswitch
2462 SimpleTeXBlanks(file, texrow, i,
2463 column, font, style);
2465 // Do we need to change font?
2466 if (font != running_font) {
2468 font.latexWriteStartChanges(file,
2469 basefont, last_font);
2470 running_font = font;
2473 // Do we need to turn on LaTeX mode?
2474 if (font.latex() != running_font.latex()) {
2475 if (font.latex() == LyXFont::ON
2476 && style.needprotect)
2478 file += "\\protect ";
2482 SimpleTeXSpecialChars(file, texrow, font,
2483 running_font, basefont,
2484 open_font, style, i, column, c);
2486 // If we have an open font definition, we have to close it
2488 running_font.latexWriteEndChanges(file, basefont, basefont);
2491 basefont = getFont(-1);
2492 running_font = basefont;
2493 cell = table->CellHasContRow(current_cell_number);
2495 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2496 return return_value;
2500 bool LyXParagraph::linuxDocConvertChar(char c, string & sgml_string)
2502 bool retval = false;
2504 case LyXParagraph::META_HFILL:
2505 sgml_string.clear();
2507 case LyXParagraph::META_PROTECTED_SEPARATOR:
2510 case LyXParagraph::META_NEWLINE:
2514 sgml_string = "&";
2517 sgml_string = "<";
2520 sgml_string = ">";
2523 sgml_string = "$";
2526 sgml_string = "#";
2529 sgml_string = "%";
2532 sgml_string = "[";
2535 sgml_string = "]";
2538 sgml_string = "{";
2541 sgml_string = "}";
2544 sgml_string = "˜";
2547 sgml_string = """;
2550 sgml_string = "\";
2556 case '\0': // Ignore :-)
2557 sgml_string.clear();
2567 void LyXParagraph::SimpleDocBookOneTablePar(string & file, string & extra,
2568 int & desc_on, int depth)
2571 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2573 LyXFont font1, font2;
2576 size_type main_body;
2577 string emph = "emphasis";
2578 bool emph_flag = false;
2580 LyXLayout const & style =
2581 textclasslist.Style(current_view->buffer()->params.textclass,
2584 if (style.labeltype != LABEL_MANUAL)
2587 main_body = BeginningOfMainBody();
2589 // Gets paragraph main font.
2591 font1 = style.labelfont;
2595 int char_line_count = depth;
2596 addNewlineAndDepth(file, depth);
2597 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2598 file += "<INFORMALTABLE>";
2599 addNewlineAndDepth(file, ++depth);
2601 int current_cell_number = -1;
2602 int tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
2604 // Parsing main loop.
2605 for (size_type i = 0; i < size(); ++i) {
2607 if (table->IsContRow(current_cell_number+1)) {
2608 if (c == LyXParagraph::META_NEWLINE)
2609 ++current_cell_number;
2614 // Fully instantiated font
2617 // Handle <emphasis> tag.
2618 if (font1.emph() != font2.emph() && i) {
2619 if (font2.emph() == LyXFont::ON) {
2620 file += "<emphasis>";
2622 } else if (emph_flag) {
2623 file += "</emphasis>";
2627 if (c == LyXParagraph::META_NEWLINE) {
2628 // We have only to control for emphasis open here!
2630 file += "</emphasis>";
2633 font1 = font2 = getFont(-1);
2634 ++current_cell_number;
2635 if (table->CellHasContRow(current_cell_number) >= 0) {
2636 DocBookContTableRows(file, extra, desc_on, i+1,
2637 current_cell_number,
2640 // if this cell follow only ContRows till end don't
2641 // put the EndOfCell because it is put after the
2643 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2644 --current_cell_number;
2647 tmp = table->DocBookEndOfCell(file,
2648 current_cell_number,
2653 } else if (c == LyXParagraph::META_INSET) {
2654 inset = GetInset(i);
2656 inset->DocBook(tmp_out);
2658 // This code needs some explanation:
2659 // Two insets are treated specially
2660 // label if it is the first element in a
2661 // command paragraph
2663 // graphics inside tables or figure floats
2665 // title (the equivalente in latex for this
2667 // and title should come first
2670 if(desc_on != 3 || i != 0) {
2671 if(tmp_out[0] == '@') {
2673 extra += frontStrip(tmp_out,
2676 file += frontStrip(tmp_out,
2681 } else if (font2.latex() == LyXFont::ON) {
2682 // "TeX"-Mode on == > SGML-Mode on.
2688 if (linuxDocConvertChar(c, sgml_string)
2689 && !style.free_spacing) {
2690 // in freespacing mode, spaces are
2691 // non-breaking characters
2696 file += "</term><listitem><para>";
2702 file += sgml_string;
2708 // Needed if there is an optional argument but no contents.
2709 if (main_body > 0 && main_body == size()) {
2714 file += "</emphasis>";
2717 ++current_cell_number;
2718 tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
2719 // Resets description flag correctly.
2722 // <term> not closed...
2726 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2727 file += "</INFORMALTABLE>";
2729 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
2734 void LyXParagraph::DocBookContTableRows(string & file, string & extra,
2736 LyXParagraph::size_type i,
2737 int current_cell_number, int &column)
2742 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
2747 string emph= "emphasis";
2748 bool emph_flag= false;
2749 int char_line_count= 0;
2751 LyXLayout const & style =
2752 textclasslist.Style(current_view->buffer()->params.textclass,
2755 size_type main_body;
2756 if (style.labeltype != LABEL_MANUAL)
2759 main_body = BeginningOfMainBody();
2761 // Gets paragraph main font.
2764 font1 = style.labelfont;
2768 size_type lastpos = i;
2769 int cell = table->CellHasContRow(current_cell_number);
2770 ++current_cell_number;
2772 // first find the right position
2774 for (; i < size() && current_cell_number < cell; ++i) {
2776 if (c == LyXParagraph::META_NEWLINE)
2777 ++current_cell_number;
2781 // I don't know how to handle this so I comment it
2782 // for the moment (Jug)
2783 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2784 // file += " \\\\\n";
2787 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE)) {
2792 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
2796 // Fully instantiated font
2799 // Handle <emphasis> tag.
2800 if (font1.emph() != font2.emph() && i) {
2801 if (font2.emph() == LyXFont::ON) {
2802 file += "<emphasis>";
2804 } else if (emph_flag) {
2805 file += "</emphasis>";
2809 if (c == LyXParagraph::META_INSET) {
2810 inset = GetInset(i);
2812 inset->DocBook(tmp_out);
2814 // This code needs some explanation:
2815 // Two insets are treated specially
2816 // label if it is the first element in a
2817 // command paragraph
2819 // graphics inside tables or figure floats
2820 // can't go on title (the equivalente in
2821 // latex for this case is caption and title
2822 // should come first
2825 if(desc_on != 3 || i != 0) {
2826 if(tmp_out[0] == '@') {
2828 extra += frontStrip(tmp_out, '@');
2830 file += frontStrip(tmp_out, '@');
2834 } else if (font2.latex() == LyXFont::ON) {
2835 // "TeX"-Mode on == > SGML-Mode on.
2841 if (linuxDocConvertChar(c, sgml_string)
2842 && !style.free_spacing) {
2843 // in freespacing mode, spaces are
2844 // non-breaking characters
2849 file += "</term><listitem><para>";
2855 file += sgml_string;
2859 // we have only to control for emphasis open here!
2861 file += "</emphasis>";
2864 font1 = font2 = getFont(-1);
2865 cell = table->CellHasContRow(current_cell_number);
2867 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
2871 void LyXParagraph::SimpleTeXBlanks(string & file, TexRow & texrow,
2872 LyXParagraph::size_type const i,
2873 int & column, LyXFont const & font,
2874 LyXLayout const & style)
2876 if (column > tex_code_break_column
2878 && GetChar(i - 1) != ' '
2880 // In LaTeX mode, we don't want to
2881 // break lines since some commands
2883 && ! (font.latex() == LyXFont::ON)
2884 // same in FreeSpacing mode
2885 && !style.free_spacing
2886 // In typewriter mode, we want to avoid
2887 // ! . ? : at the end of a line
2888 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
2889 && (GetChar(i-1) == '.'
2890 || GetChar(i-1) == '?'
2891 || GetChar(i-1) == ':'
2892 || GetChar(i-1) == '!'))) {
2893 if (tex_code_break_column == 0) {
2894 // in batchmode we need LaTeX to still
2895 // see it as a space not as an extra '\n'
2901 texrow.start(this, i+1);
2903 } else if (font.latex() == LyXFont::OFF) {
2904 if (style.free_spacing) {
2913 void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow,
2915 LyXFont & running_font,
2918 LyXLayout const & style,
2919 LyXParagraph::size_type & i,
2920 int & column, char const c)
2922 // Two major modes: LaTeX or plain
2923 // Handle here those cases common to both modes
2924 // and then split to handle the two modes separately.
2926 case LyXParagraph::META_INSET: {
2927 Inset * inset = GetInset(i);
2930 int len = file.length();
2931 if ((inset->LyxCode() == Inset::GRAPHICS_CODE
2932 || inset->LyxCode() == Inset::MATH_CODE
2933 || inset->LyxCode() == Inset::URL_CODE)
2934 && running_font.getFontDirection()
2935 == LYX_DIR_RIGHT_TO_LEFT) {
2939 int tmp = inset->Latex(file, style.isCommand());
2946 column += file.length() - len;
2955 case LyXParagraph::META_NEWLINE:
2957 column += running_font.latexWriteEndChanges(file,
2958 basefont, basefont);
2961 basefont = getFont(-1);
2962 running_font = basefont;
2965 case LyXParagraph::META_HFILL:
2966 file += "\\hfill{}";
2971 // And now for the special cases within each mode
2972 // Are we in LaTeX mode?
2973 if (font.latex() == LyXFont::ON) {
2974 // at present we only have one option
2975 // but I'll leave it as a switch statement
2976 // so its simpler to extend. (ARRae)
2978 case LyXParagraph::META_PROTECTED_SEPARATOR:
2983 // make sure that we will not print
2984 // error generating chars to the tex
2985 // file. This test would not be needed
2986 // if it were done in the buffer
2994 // Plain mode (i.e. not LaTeX)
2996 case LyXParagraph::META_PROTECTED_SEPARATOR:
3001 file += "\\textbackslash{}";
3005 case '°': case '±': case '²': case '³':
3006 case '×': case '÷': case '¹': case 'ª':
3007 case 'º': case '¬': case 'µ':
3008 if (current_view->buffer()->params.inputenc == "latin1") {
3009 file += "\\ensuremath{";
3018 case '|': case '<': case '>':
3019 // In T1 encoding, these characters exist
3020 if (lyxrc->fontenc == "T1") {
3022 //... but we should avoid ligatures
3023 if ((c == '>' || c == '<')
3025 && GetChar(i+1) == c){
3026 file += "\\textcompwordmark{}";
3031 // Typewriter font also has them
3032 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3036 // Otherwise, we use what LaTeX
3040 file += "\\textless{}";
3044 file += "\\textgreater{}";
3048 file += "\\textbar{}";
3054 case '-': // "--" in Typewriter mode -> "-{}-"
3056 && GetChar(i + 1) == '-'
3057 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3066 file += "\\char`\\\"{}";
3071 if (current_view->buffer()->params.inputenc == "default") {
3072 file += "\\pounds{}";
3080 case '%': case '#': case '{':
3088 file += "\\textasciitilde{}";
3093 file += "\\textasciicircum{}";
3097 case '*': case '[': case ']':
3098 // avoid being mistaken for optional arguments
3106 // Blanks are printed before font switching.
3107 // Sure? I am not! (try nice-latex)
3108 // I am sure it's correct. LyX might be smarter
3109 // in the future, but for now, nothing wrong is
3114 /* idea for labels --- begin*/
3118 && font.family() != LyXFont::TYPEWRITER_FAMILY
3119 && GetChar(i + 1) == 'y'
3120 && GetChar(i + 2) == 'X') {
3128 && font.family() != LyXFont::TYPEWRITER_FAMILY
3129 && GetChar(i + 1) == 'e'
3130 && GetChar(i + 2) == 'X') {
3135 // Check for "LaTeX2e"
3138 && font.family() != LyXFont::TYPEWRITER_FAMILY
3139 && GetChar(i + 1) == 'a'
3140 && GetChar(i + 2) == 'T'
3141 && GetChar(i + 3) == 'e'
3142 && GetChar(i + 4) == 'X'
3143 && GetChar(i + 5) == '2'
3144 && GetChar(i + 6) == 'e') {
3145 file += "\\LaTeXe{}";
3149 // Check for "LaTeX"
3152 && font.family() != LyXFont::TYPEWRITER_FAMILY
3153 && GetChar(i + 1) == 'a'
3154 && GetChar(i + 2) == 'T'
3155 && GetChar(i + 3) == 'e'
3156 && GetChar(i + 4) == 'X') {
3157 file += "\\LaTeX{}";
3160 /* idea for labels --- end*/
3161 } else if (c != '\0') {
3171 bool LyXParagraph::RoffContTableRows(ostream & os,
3172 LyXParagraph::size_type i,
3178 LyXFont font1(LyXFont::ALL_INHERIT);
3183 string fname2 = TmpFileName(string(), "RAT2");
3185 int cell = table->CellHasContRow(actcell);
3188 // first find the right position
3190 for (; i < size() && actcell < cell; ++i) {
3192 if (c == LyXParagraph::META_NEWLINE)
3197 if ((c != ' ') && (c != LyXParagraph::META_NEWLINE))
3200 && (c = GetChar(i)) != LyXParagraph::META_NEWLINE;
3202 font2 = GetFontSettings(i);
3203 if (font1.latex() != font2.latex()) {
3204 if (font2.latex() != LyXFont::OFF)
3209 case LyXParagraph::META_INSET:
3210 if ((inset = GetInset(i))) {
3211 fstream fs(fname2.c_str(),
3214 WriteAlert(_("LYX_ERROR:"),
3215 _("Cannot open temporary file:"),
3219 inset->Latex(fs, -1);
3232 case LyXParagraph::META_NEWLINE:
3234 case LyXParagraph::META_HFILL:
3236 case LyXParagraph::META_PROTECTED_SEPARATOR:
3245 lyxerr.debug() << "RoffAsciiTable: "
3246 "NULL char in structure."
3251 cell = table->CellHasContRow(actcell);
3257 LyXParagraph * LyXParagraph::TeXDeeper(string & file, TexRow & texrow,
3258 string & foot, TexRow & foot_texrow,
3261 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3262 LyXParagraph * par = this;
3264 while (par && par->depth == depth) {
3266 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3267 if (textclasslist.Style(current_view->buffer()->params.textclass,
3268 par->layout).isEnvironment()
3269 || par->pextra_type != PEXTRA_NONE)
3271 par = par->TeXEnvironment(file, texrow,
3275 par = par->TeXOnePar(file, texrow,
3280 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3286 LyXParagraph * LyXParagraph::TeXEnvironment(string & file, TexRow & texrow,
3288 TexRow & foot_texrow,
3291 bool eindent_open = false;
3292 bool foot_this_level = false;
3293 // flags when footnotetext should be appended to file.
3294 static bool minipage_open = false;
3295 static int minipage_open_depth = 0;
3296 char par_sep = current_view->buffer()->params.paragraph_separation;
3298 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3300 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3302 LyXLayout const & style =
3303 textclasslist.Style(current_view->buffer()->params.textclass,
3306 if (pextra_type == PEXTRA_INDENT) {
3307 if (!pextra_width.empty()) {
3308 file += "\\begin{LyXParagraphIndent}{"
3309 + pextra_width + "}\n";
3311 //float ib = atof(pextra_widthp.c_str())/100;
3312 // string can't handle floats at present (971109)
3313 // so I'll do a conversion by hand knowing that
3314 // the limits are 0.0 to 1.0. ARRae.
3315 file += "\\begin{LyXParagraphIndent}{";
3316 switch (pextra_widthp.length()) {
3322 file += pextra_widthp;
3326 file += pextra_widthp;
3328 file += "\\columnwidth}\n";
3331 eindent_open = true;
3333 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3334 if (pextra_hfill && Previous() &&
3335 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3336 file += "\\hfill{}\n";
3339 if (par_sep == BufferParams::PARSEP_INDENT) {
3340 file += "{\\setlength\\parindent{0pt}\n";
3343 file += "\\begin{minipage}";
3344 switch(pextra_alignment) {
3345 case MINIPAGE_ALIGN_TOP:
3348 case MINIPAGE_ALIGN_MIDDLE:
3351 case MINIPAGE_ALIGN_BOTTOM:
3355 if (!pextra_width.empty()) {
3357 file += pextra_width + "}\n";
3359 //float ib = atof(par->pextra_width.c_str())/100;
3360 // string can't handle floats at present
3361 // so I'll do a conversion by hand knowing that
3362 // the limits are 0.0 to 1.0. ARRae.
3364 switch (pextra_widthp.length()) {
3370 file += pextra_widthp;
3374 file += pextra_widthp;
3376 file += "\\columnwidth}\n";
3379 if (par_sep == BufferParams::PARSEP_INDENT) {
3380 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3383 minipage_open = true;
3384 minipage_open_depth = depth;
3387 #ifdef WITH_WARNINGS
3388 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3389 //I disabled it because it breaks when lists span on several
3392 if (style.isEnvironment()){
3393 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
3394 #ifdef FANCY_FOOTNOTE_CODE
3395 if (foot_count < 0) {
3396 // flag that footnote[mark][text] should be
3397 // used for any footnotes from now on
3399 foot_this_level = true;
3402 file += "\\begin{" + style.latexname() + "}{"
3403 + labelwidthstring + "}\n";
3404 } else if (style.labeltype == LABEL_BIBLIO) {
3406 file += "\\begin{" + style.latexname() + "}{"
3407 + bibitemWidthest(current_view->painter())
3409 } else if (style.latextype == LATEX_ITEM_ENVIRONMENT) {
3410 #ifdef FANCY_FOOTNOTE_CODE
3411 if (foot_count < 0) {
3412 // flag that footnote[mark][text] should be
3413 // used for any footnotes from now on
3415 foot_this_level = true;
3418 file += "\\begin{" + style.latexname() + '}'
3419 + style.latexparam() + '\n';
3421 file += "\\begin{" + style.latexname() + '}'
3422 + style.latexparam() + '\n';
3425 LyXParagraph * par = this;
3427 par = par->TeXOnePar(file, texrow,
3428 foot, foot_texrow, foot_count);
3430 if (minipage_open && par && !style.isEnvironment() &&
3431 (par->pextra_type == PEXTRA_MINIPAGE) &&
3432 par->pextra_start_minipage) {
3433 file += "\\end{minipage}\n";
3435 if (par_sep == BufferParams::PARSEP_INDENT) {
3439 minipage_open = false;
3441 if (par && par->depth > depth) {
3442 if (textclasslist.Style(current_view->buffer()->params.textclass,
3443 par->layout).isParagraph()
3445 && !suffixIs(file, "\n\n")) {
3446 // There should be at least one '\n' already
3447 // but we need there to be two for Standard
3448 // paragraphs that are depth-increment'ed to be
3449 // output correctly. However, tables can
3450 // also be paragraphs so don't adjust them.
3455 par = par->TeXDeeper(file, texrow,
3456 foot, foot_texrow, foot_count);
3458 if (par && par->layout == layout && par->depth == depth &&
3459 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3460 if (par->pextra_hfill && par->Previous() &&
3461 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3462 file += "\\hfill{}\n";
3465 if (par_sep == BufferParams::PARSEP_INDENT) {
3466 file += "{\\setlength\\parindent{0pt}\n";
3469 file += "\\begin{minipage}";
3470 switch(par->pextra_alignment) {
3471 case MINIPAGE_ALIGN_TOP:
3474 case MINIPAGE_ALIGN_MIDDLE:
3477 case MINIPAGE_ALIGN_BOTTOM:
3481 if (!par->pextra_width.empty()) {
3483 file += par->pextra_width;
3486 //float ib = atof(par->pextra_widthp.c_str())/100;
3487 // string can't handle floats at present
3488 // so I'll do a conversion by hand knowing that
3489 // the limits are 0.0 to 1.0. ARRae.
3491 switch (par->pextra_widthp.length()) {
3497 file += par->pextra_widthp;
3501 file += par->pextra_widthp;
3503 file += "\\columnwidth}\n";
3506 if (par_sep == BufferParams::PARSEP_INDENT) {
3507 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3510 minipage_open = true;
3511 minipage_open_depth = par->depth;
3514 && par->layout == layout
3515 && par->depth == depth
3516 && par->pextra_type == pextra_type);
3518 if (style.isEnvironment()) {
3519 file += "\\end{" + style.latexname() + '}';
3520 // maybe this should go after the minipage closes?
3521 if (foot_this_level) {
3522 if (foot_count >= 1) {
3523 if (foot_count > 1) {
3524 file += "\\addtocounter{footnote}{-";
3525 file += tostr(foot_count - 1);
3529 texrow += foot_texrow;
3531 foot_texrow.reset();
3536 if (minipage_open && (minipage_open_depth == depth) &&
3537 (!par || par->pextra_start_minipage ||
3538 par->pextra_type != PEXTRA_MINIPAGE)) {
3539 file += "\\end{minipage}\n";
3541 if (par_sep == BufferParams::PARSEP_INDENT) {
3545 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3546 file += "\\medskip\n\n";
3550 minipage_open = false;
3553 file += "\\end{LyXParagraphIndent}\n";
3556 if (!(par && (par->pextra_type == PEXTRA_MINIPAGE)
3557 && par->pextra_hfill)) {
3561 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3562 return par; // ale970302
3566 LyXParagraph * LyXParagraph::TeXFootnote(string & file, TexRow & texrow,
3567 string & foot, TexRow & foot_texrow,
3569 LyXDirection par_direction)
3571 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3572 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3573 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3574 "No footnote!" << endl;
3576 LyXParagraph * par = this;
3577 LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass,
3578 previous->GetLayout());
3580 if (style.needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3581 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3582 "Float other than footnote in command"
3583 " with moving argument is illegal" << endl;
3586 if (footnotekind != LyXParagraph::FOOTNOTE
3587 && footnotekind != LyXParagraph::MARGIN
3589 && !suffixIs(file, '\n')) {
3590 // we need to ensure that real floats like tables and figures
3591 // have their \begin{} on a new line otherwise we can get
3592 // incorrect results when using the endfloat.sty package
3593 // especially if two floats follow one another. ARRae 981022
3594 // NOTE: if the file is length 0 it must have just been
3595 // written out so we assume it ended with a '\n'
3600 BufferParams * params = ¤t_view->buffer()->params;
3601 bool footer_in_body = true;
3602 switch (footnotekind) {
3603 case LyXParagraph::FOOTNOTE:
3604 if (style.intitle) {
3605 file += "\\thanks{\n";
3606 footer_in_body = false;
3608 if (foot_count == -1) {
3609 // we're at depth 0 so we can use:
3610 file += "\\footnote{%\n";
3611 footer_in_body = false;
3613 file += "\\footnotemark{}%\n";
3615 // we only need this when there are
3616 // multiple footnotes
3617 foot += "\\stepcounter{footnote}";
3619 foot += "\\footnotetext{%\n";
3620 foot_texrow.start(this, 0);
3621 foot_texrow.newline();
3626 case LyXParagraph::MARGIN:
3627 file += "\\marginpar{\n";
3629 case LyXParagraph::FIG:
3630 if (pextra_type == PEXTRA_FLOATFLT
3631 && (!pextra_width.empty()
3632 || !pextra_widthp.empty())) {
3634 if (!pextra_width.empty())
3635 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
3636 pextra_width.c_str());
3639 "\\begin{floatingfigure}{%f\\textwidth}\n",
3640 atoi(pextra_widthp.c_str())/100.0);
3643 file += "\\begin{figure}";
3644 if (!params->float_placement.empty()) {
3646 file += params->float_placement;
3653 case LyXParagraph::TAB:
3654 file += "\\begin{table}";
3655 if (!params->float_placement.empty()) {
3657 file += params->float_placement;
3663 case LyXParagraph::WIDE_FIG:
3664 file += "\\begin{figure*}";
3665 if (!params->float_placement.empty()) {
3667 file += params->float_placement;
3673 case LyXParagraph::WIDE_TAB:
3674 file += "\\begin{table*}";
3675 if (!params->float_placement.empty()) {
3677 file += params->float_placement;
3683 case LyXParagraph::ALGORITHM:
3684 file += "\\begin{algorithm}\n";
3690 LyXDirection direction = getParDirection();
3691 if (direction != par_direction) {
3692 if (direction == LYX_DIR_LEFT_TO_RIGHT)
3693 file += "\\unsethebrew\n";
3695 file += "\\sethebrew\n";
3699 if (footnotekind != LyXParagraph::FOOTNOTE
3700 || !footer_in_body) {
3701 // Process text for all floats except footnotes in body
3703 LyXLayout const & style =
3704 textclasslist.Style(current_view->buffer()->params.textclass,
3707 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3709 if (style.isEnvironment()
3710 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3711 // Allows the use of minipages within float
3712 // environments. Shouldn't be circular because
3713 // we don't support footnotes inside
3714 // floats (yet). ARRae
3715 par = par->TeXEnvironment(file, texrow,
3719 par = par->TeXOnePar(file, texrow,
3724 if (par && !par->IsDummy() && par->depth > depth) {
3725 par = par->TeXDeeper(file, texrow,
3729 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3731 // process footnotes > depth 0 or in environments separately
3732 // NOTE: Currently don't support footnotes within footnotes
3733 // even though that is possible using the \footnotemark
3735 TexRow dummy_texrow;
3736 int dummy_count = 0;
3738 LyXLayout const & style =
3739 textclasslist.Style(current_view->buffer()->params.textclass,
3742 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3744 if (style.isEnvironment()
3745 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3746 // Allows the use of minipages within float
3747 // environments. Shouldn't be circular because
3748 // we don't support footnotes inside
3749 // floats (yet). ARRae
3750 par = par->TeXEnvironment(foot, foot_texrow,
3751 dummy, dummy_texrow,
3754 par = par->TeXOnePar(foot, foot_texrow,
3755 dummy, dummy_texrow,
3759 if (par && !par->IsDummy() && par->depth > depth) {
3760 par = par->TeXDeeper(foot, foot_texrow,
3761 dummy, dummy_texrow,
3765 && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3767 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3768 "Footnote in a Footnote -- not supported"
3773 switch (footnotekind) {
3774 case LyXParagraph::FOOTNOTE:
3775 if (footer_in_body) {
3776 // This helps tell which of the multiple
3777 // footnotetexts an error was in.
3779 foot_texrow.newline();
3784 case LyXParagraph::MARGIN:
3787 case LyXParagraph::FIG:
3788 if (pextra_type == PEXTRA_FLOATFLT
3789 && (!pextra_width.empty()
3790 || !pextra_widthp.empty()))
3791 file += "\\end{floatingfigure}";
3793 file += "\\end{figure}";
3795 case LyXParagraph::TAB:
3796 file += "\\end{table}";
3798 case LyXParagraph::WIDE_FIG:
3799 file += "\\end{figure*}";
3801 case LyXParagraph::WIDE_TAB:
3802 file += "\\end{table*}";
3804 case LyXParagraph::ALGORITHM:
3805 file += "\\end{algorithm}";
3809 if (footnotekind != LyXParagraph::FOOTNOTE
3810 && footnotekind != LyXParagraph::MARGIN) {
3811 // we need to ensure that real floats like tables and figures
3812 // have their \end{} on a line of their own otherwise we can
3813 // get incorrect results when using the endfloat.sty package.
3818 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
3823 void LyXParagraph::SetPExtraType(int type, char const * width,
3824 char const * widthp)
3827 pextra_width = width;
3828 pextra_widthp = widthp;
3830 if (textclasslist.Style(current_view->buffer()->params.textclass,
3831 layout).isEnvironment()) {
3836 while (par && (par->layout == layout)
3837 && (par->depth == depth)) {
3839 par = par->Previous();
3841 par = par->FirstPhysicalPar();
3842 while (par && par->depth > depth) {
3843 par = par->Previous();
3845 par = par->FirstPhysicalPar();
3849 while (par && (par->layout == layout)
3850 && (par->depth == depth)) {
3851 par->pextra_type = type;
3852 par->pextra_width = width;
3853 par->pextra_widthp = widthp;
3854 par = par->NextAfterFootnote();
3855 if (par && (par->depth > depth))
3856 par->SetPExtraType(type, width, widthp);
3857 while (par && ((par->depth > depth) || par->IsDummy()))
3858 par = par->NextAfterFootnote();
3864 void LyXParagraph::UnsetPExtraType()
3866 if (pextra_type == PEXTRA_NONE)
3869 pextra_type = PEXTRA_NONE;
3870 pextra_width.clear();
3871 pextra_widthp.clear();
3873 if (textclasslist.Style(current_view->buffer()->params.textclass,
3874 layout).isEnvironment()) {
3879 while (par && (par->layout == layout)
3880 && (par->depth == depth)) {
3882 par = par->Previous();
3884 par = par->FirstPhysicalPar();
3885 while (par && par->depth > depth) {
3886 par = par->Previous();
3888 par = par->FirstPhysicalPar();
3892 while (par && (par->layout == layout)
3893 && (par->depth == depth)) {
3894 par->pextra_type = PEXTRA_NONE;
3895 par->pextra_width.clear();
3896 par->pextra_widthp.clear();
3897 par = par->NextAfterFootnote();
3898 if (par && (par->depth > depth))
3899 par->UnsetPExtraType();
3900 while (par && ((par->depth > depth) || par->IsDummy()))
3901 par = par->NextAfterFootnote();
3907 bool LyXParagraph::IsHfill(size_type pos) const
3909 return IsHfillChar(GetChar(pos));
3913 bool LyXParagraph::IsInset(size_type pos) const
3915 return IsInsetChar(GetChar(pos));
3919 bool LyXParagraph::IsFloat(size_type pos) const
3921 return IsFloatChar(GetChar(pos));
3925 bool LyXParagraph::IsNewline(size_type pos) const
3929 tmp = IsNewlineChar(GetChar(pos));
3934 bool LyXParagraph::IsSeparator(size_type pos) const
3936 return IsSeparatorChar(GetChar(pos));
3940 bool LyXParagraph::IsLineSeparator(size_type pos) const
3942 return IsLineSeparatorChar(GetChar(pos));
3946 bool LyXParagraph::IsKomma(size_type pos) const
3948 return IsKommaChar(GetChar(pos));
3952 /// Used by the spellchecker
3953 bool LyXParagraph::IsLetter(LyXParagraph::size_type pos) const
3955 unsigned char c = GetChar(pos);
3956 if (IsLetterChar(c))
3958 // '\0' is not a letter, allthough every string contains "" (below)
3961 // We want to pass the ' and escape chars to ispell
3962 string extra = lyxrc->isp_esc_chars + '\'';
3966 return contains(extra, ch);
3970 bool LyXParagraph::IsWord(size_type pos ) const
3972 return IsWordChar(GetChar(pos)) ;