1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-1999 The LyX Team.
9 * ======================================================*/
14 #pragma implementation "lyxparagraph.h"
17 #include "lyxparagraph.h"
20 #include "tex-strings.h"
21 #include "bufferparams.h"
22 #include "support/FileInfo.h"
24 #include "LaTeXFeatures.h"
25 #include "insets/insetinclude.h"
26 #include "support/filetools.h"
27 #include "lyx_gui_misc.h"
30 #define INITIAL_SIZE_PAR 10 /*Number of bytes in one paragraph*/
31 #define STEP_SIZE_PAR 10 /*Number of bytes added when reallocated*/
33 extern void addNewlineAndDepth(string & file, int const depth); // Jug 990923
34 extern unsigned char GetCurrentTextClass(); // this should be fixed/removed
35 int tex_code_break_column = 72; // needs non-zero initialization. set later.
36 // this is a bad idea, but how can LyXParagraph find its buffer to get
37 // parameters? (JMarc)
38 extern BufferView *current_view;
43 extern string bibitemWidthest();
45 /* this is a minibuffer */
46 static char minibuffer_char;
47 static LyXFont minibuffer_font;
48 static Inset *minibuffer_inset;
51 // Initialization of the counter for the paragraph id's,
52 // declared in lyxparagraph.h
53 unsigned int LyXParagraph::paragraph_id = 0;
56 LyXParagraph::LyXParagraph()
58 size = INITIAL_SIZE_PAR;
60 text = new char[size];
61 for (int i=0; i<10; i++) setCounter(i , 0);
69 footnoteflag = LyXParagraph::NO_FOOTNOTE;
71 align = LYX_ALIGN_BLOCK;
73 /* table stuff -- begin*/
75 /* table stuff -- end*/
77 bibkey = 0; // ale970302
82 /* this konstruktor inserts the new paragraph in a list */
83 LyXParagraph::LyXParagraph(LyXParagraph *par)
85 size = INITIAL_SIZE_PAR;
87 text = new char[size];
88 for (int i=0; i<10; i++) setCounter(i, 0);
94 next->previous = this;
96 previous->next = this;
99 footnoteflag = LyXParagraph::NO_FOOTNOTE;
100 footnotekind = LyXParagraph::FOOTNOTE;
102 /* table stuff -- begin*/
104 /* table stuff -- end*/
107 bibkey = 0; // ale970302
109 // lyxerr << "new bib " << endl;
110 // if (par->bibkey) {
111 // bibkey = new InsetBibKey(par->bibkey);
117 /// Used by the spellchecker
118 bool LyXParagraph::IsLetter(int pos){
119 unsigned char c = GetChar(pos);
122 // '\0' is not a letter, allthough every string contains "" (below)
125 // We want to pass the ' and escape chars to ispell
126 string extra = lyxrc->isp_esc_chars + '\'';
130 return contains(extra, ch);
134 void LyXParagraph::writeFile(FILE *file, BufferParams ¶ms,
135 char footflag, char dth)
137 LyXFont font1, font2;
143 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
145 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
147 /* The beginning or the end of a footnote environment? */
148 if (footflag != footnoteflag) {
149 footflag = footnoteflag;
151 fprintf(file, "\n\\begin_float %s ",
152 string_footnotekinds[footnotekind]);
155 fprintf(file, "\n\\end_float ");
159 /* The beginning or end of a deeper (i.e. nested) area? */
162 while (depth > dth) {
163 fprintf(file, "\n\\begin_deeper ");
168 while (depth < dth) {
169 fprintf(file, "\n\\end_deeper ");
175 /* First write the layout */
176 fprintf(file, "\n\\layout %s\n",
177 lyxstyle.NameOfLayout(params.textclass,layout).c_str());
179 /* maybe some vertical spaces */
180 if (added_space_top.kind() != VSpace::NONE)
181 fprintf(file, "\\added_space_top %s ",
182 added_space_top.asLyXCommand().c_str());
183 if (added_space_bottom.kind() != VSpace::NONE)
184 fprintf(file, "\\added_space_bottom %s ",
185 added_space_bottom.asLyXCommand().c_str());
187 /* The labelwidth string used in lists */
188 if (!labelwidthstring.empty())
189 fprintf(file, "\\labelwidthstring %s\n",
190 labelwidthstring.c_str());
192 /* Lines above or below? */
194 fprintf(file, "\\line_top ");
196 fprintf(file, "\\line_bottom ");
198 /* Pagebreaks above or below? */
200 fprintf(file, "\\pagebreak_top ");
201 if (pagebreak_bottom)
202 fprintf(file, "\\pagebreak_bottom ");
204 /* Start of appendix? */
205 if (start_of_appendix)
206 fprintf(file, "\\start_of_appendix ");
210 fprintf(file, "\\noindent ");
213 if (align != LYX_ALIGN_LAYOUT) {
215 case LYX_ALIGN_LEFT: h = 1; break;
216 case LYX_ALIGN_RIGHT: h = 2; break;
217 case LYX_ALIGN_CENTER: h = 3; break;
218 default: h = 0; break;
220 fprintf(file, "\\align %s ", string_align[h]);
222 if (pextra_type != PEXTRA_NONE) {
223 fprintf(file, "\\pextra_type %d", pextra_type);
224 if (pextra_type == PEXTRA_MINIPAGE) {
225 fprintf(file, " \\pextra_alignment %d",
228 fprintf(file, " \\pextra_hfill %d",
230 if (pextra_start_minipage)
231 fprintf(file, " \\pextra_start_minipage %d",
232 pextra_start_minipage);
234 if (!pextra_width.empty()) {
235 fprintf(file, " \\pextra_width %s",
236 VSpace(pextra_width).asLyXCommand().c_str());
237 } else if (!pextra_widthp.empty()) {
238 fprintf(file, " \\pextra_widthp %s",pextra_widthp.c_str());
244 /* Dummy layout. This means that a footnote ended */
245 fprintf(file, "\n\\end_float ");
246 footflag = LyXParagraph::NO_FOOTNOTE;
249 /* It might be a table */
251 fprintf(file, "\\LyXTable\n");
259 font1 = LyXFont(LyXFont::ALL_INHERIT);
262 for (int i = 0; i < last; i++) {
268 // Write font changes
269 font2 = GetFontSettings(i);
270 if (font2 != font1) {
271 font2.lyxWriteChanges(font1, file);
281 if (inset->DirectWrite()) {
282 // international char, let it write
283 // code directly so it's shorter in
287 fprintf(file, "\n\\begin_inset ");
289 fprintf(file, "\n\\end_inset \n");
294 case LYX_META_NEWLINE:
295 fprintf(file, "\n\\newline \n");
299 fprintf(file, "\n\\hfill \n");
302 case LYX_META_PROTECTED_SEPARATOR:
303 fprintf(file, "\n\\protected_separator \n");
307 fprintf(file, "\n\\backslash \n");
311 if (i + 1 < last && GetChar(i + 1) == ' ') {
312 fprintf(file, ".\n");
318 if ((column > 70 && c==' ')
323 // this check is to amend a bug. LyX sometimes
324 // inserts '\0' this could cause problems.
326 fprintf(file, "%c", c);
328 lyxerr << "ERROR (LyXParagraph::writeFile):"
329 " NULL char in structure." << endl;
335 // now write the next paragraph
337 next->writeFile(file, params, footflag, dth);
341 void LyXParagraph::validate(LaTeXFeatures &features)
343 // this will be useful later
344 LyXLayout *layout = lyxstyle.Style(GetCurrentTextClass(),
348 if (line_top || line_bottom)
349 features.lyxline = true;
352 features.layout[GetLayout()] = true;
355 FontTable *tmpfonttable = fonttable;
356 while (tmpfonttable) {
357 if (tmpfonttable->font.noun() == LyXFont::ON) {
358 lyxerr[Debug::LATEX] << "font.noun: "
359 << tmpfonttable->font.noun()
361 features.noun = true;
362 lyxerr[Debug::LATEX] << "Noun enabled. Font: "
363 << tmpfonttable->font.stateText()
366 switch (tmpfonttable->font.color()) {
368 case LyXFont::INHERIT_COLOR:
369 case LyXFont::IGNORE_COLOR:
372 features.color = true;
373 lyxerr[Debug::LATEX] << "Color enabled. Font: "
374 << tmpfonttable->font.stateText()
377 tmpfonttable = tmpfonttable->next;
381 InsetTable *tmpinsettable = insettable;
382 while (tmpinsettable) {
383 if (tmpinsettable->inset) {
384 tmpinsettable->inset->Validate(features);
386 tmpinsettable = tmpinsettable->next;
388 if (table && table->IsLongTable())
389 features.longtable = true;
390 if (pextra_type == PEXTRA_INDENT)
391 features.LyXParagraphIndent = true;
392 if (pextra_type == PEXTRA_FLOATFLT)
393 features.floatflt = true;
394 if (layout->needprotect
395 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
396 features.NeedLyXFootnoteCode = true;
397 if ((current_view->currentBuffer()->params.paragraph_separation == LYX_PARSEP_INDENT) &&
398 (pextra_type == PEXTRA_MINIPAGE))
399 features.NeedLyXMinipageIndent = true;
400 if (table && table->NeedRotating())
401 features.rotating = true;
402 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
403 features.algorithm = true;
407 /* first few functions needed for cut and paste and paragraph breaking */
408 void LyXParagraph::CopyIntoMinibuffer(int pos)
410 minibuffer_char = GetChar(pos);
411 minibuffer_font = GetFontSettings(pos);
412 minibuffer_inset = 0;
413 if (minibuffer_char == LYX_META_INSET) {
415 minibuffer_inset = GetInset(pos)->Clone();
417 minibuffer_inset = 0;
418 minibuffer_char = ' ';
419 // This reflects what GetInset() does (ARRae)
425 void LyXParagraph::CutIntoMinibuffer(int pos)
427 minibuffer_char = GetChar(pos);
428 minibuffer_font = GetFontSettings(pos);
429 minibuffer_inset = 0;
430 if (minibuffer_char == LYX_META_INSET) {
432 minibuffer_inset = GetInset(pos);
433 /* This is a little hack since I want exactly the inset,
434 not just a clone. Otherwise the inset would be deleted
435 when calling Erase(pos) */
438 InsetTable *tmpi = insettable;
439 while (tmpi && tmpi->pos != pos) {
442 if (tmpi) { /* This should always be true */
446 minibuffer_inset = 0;
447 minibuffer_char = ' ';
448 // This reflects what GetInset() does (ARRae)
453 /* Erase(pos); now the caller is responsible for that*/
457 void LyXParagraph::InsertFromMinibuffer(int pos)
459 InsertChar(pos, minibuffer_char);
460 SetFont(pos, minibuffer_font);
461 if (minibuffer_char == LYX_META_INSET)
462 InsertInset(pos, minibuffer_inset);
465 /* end of minibuffer */
469 void LyXParagraph::Clear()
474 pagebreak_top = false;
475 pagebreak_bottom = false;
477 added_space_top = VSpace(VSpace::NONE);
478 added_space_bottom = VSpace(VSpace::NONE);
480 align = LYX_ALIGN_LAYOUT;
484 pextra_type = PEXTRA_NONE;
485 pextra_width.clear();
486 pextra_widthp.clear();
487 pextra_alignment = MINIPAGE_ALIGN_TOP;
488 pextra_hfill = false;
489 pextra_start_minipage = false;
492 labelwidthstring.clear();
496 start_of_appendix = false;
500 /* the destructor removes the new paragraph from the list */
501 LyXParagraph::~LyXParagraph()
504 previous->next = next;
506 next->previous = previous;
511 InsetTable *tmpinset;
513 tmpinset = insettable;
514 insettable = insettable->next;
516 delete tmpinset->inset;
518 if (insettable && insettable->next == insettable) {
519 // somehow this recursion appears occasionally
520 // but I can't find where. This bandaid
521 // helps but isn't the best fix. (ARRae)
522 if (insettable->inset) {
523 delete insettable->inset;
533 fonttable = fonttable->next;
537 /* table stuff -- begin*/
540 /* table stuff -- end*/
548 void LyXParagraph::Erase(int pos)
552 /* > because last is the next unused position, and you can
553 * use it if you want */
555 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
556 NextAfterFootnote()->Erase(pos - last - 1);
558 lyxerr.debug() << "ERROR (LyXParagraph::Erase): "
559 "position does not exist." << endl;
562 if (pos < last) { // last is free for insertation, but should be empty
564 /* if it is an inset, delete the inset entry */
565 if (text[pos] == LYX_META_INSET) {
567 InsetTable *tmpi = insettable;
568 InsetTable *tmpi2 = tmpi;
569 while (tmpi && tmpi->pos != pos) {
573 if (tmpi) { // this should always be true
574 if (tmpi->inset) // delete the inset if it exists
576 if (tmpi == insettable)
577 insettable = tmpi->next;
579 tmpi2->next = tmpi->next;
584 // Shift rest of text
585 for (i = pos; i < last - 1; i++) {
590 /* erase entries in the tables */
592 FontTable *tmp = fonttable;
594 while (tmp && !found) {
595 if (pos >= tmp->pos && pos <= tmp->pos_end)
603 if (found && tmp->pos == tmp->pos_end) {
604 /* if it is a multi-character font entry, we just make
605 * it smaller (see update below), otherwise we should
608 prev->next = tmp->next;
610 fonttable = tmp->next;
615 /* update all other entries */
621 if (tmp->pos_end >= pos)
626 /* update the inset table */
627 InsetTable *tmpi = insettable;
635 lyxerr << "ERROR (LyXParagraph::Erase): "
636 "can't erase non-existant char." << endl;
641 /* pos is needed to specify the paragraph correctly. Remember the
642 * closed footnotes */
643 void LyXParagraph::Enlarge(int pos, int number)
647 /* > because last is the next unused position, and you can
648 * use it if you want */
650 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
651 NextAfterFootnote()->Enlarge(pos - last - 1, number);
653 lyxerr << "ERROR (LyXParagraph::Enlarge): "
654 "position does not exist." << endl;
658 if (size - last < number) {
659 size += number - size + last + STEP_SIZE_PAR;
660 char *tmp = new char[size];
661 for (i = 0; i < last; i++)
669 /* make the allocated memory fit to the needed size */
670 /* used to make a paragraph smaller */
671 void LyXParagraph::FitSize()
675 if (size - last > STEP_SIZE_PAR) {
676 size = last + STEP_SIZE_PAR;
677 char *tmp = new char[size];
678 for (i = 0; i < last; i++)
686 void LyXParagraph::InsertChar(int pos, char c)
690 /* > because last is the next unused position, and you can
691 * use it if you want */
693 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
694 NextAfterFootnote()->InsertChar(pos - last - 1, c);
696 lyxerr.debug() << "ERROR (LyXParagraph::InsertChar): "
697 "position does not exist." << endl;
701 // Are we full? If so, enlarge.
703 size += STEP_SIZE_PAR;
704 char *tmp = new char[size];
705 for (i = 0; i < last; i++)
711 // Shift rest of character
712 for (i = last; i>pos; i--) {
719 /* update the font table */
720 FontTable *tmp = fonttable;
724 if (tmp->pos_end >= pos)
729 /* update the inset table */
730 InsetTable *tmpi = insettable;
732 if (tmpi->pos >= pos)
739 void LyXParagraph::InsertInset(int pos, Inset *inset)
741 /* > because last is the next unused position, and you can
742 * use it if you want */
744 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
745 NextAfterFootnote()->InsertInset(pos - last - 1, inset);
747 lyxerr << "ERROR (LyXParagraph::InsertInset): "
748 "position does not exist: " << pos << endl;
752 if (text[pos]!=LYX_META_INSET) {
753 lyxerr << "ERROR (LyXParagraph::InsertInset): "
754 "there is no LYX_META_INSET" << endl;
759 /* add a new entry in the inset table */
760 InsetTable *tmpi = new InsetTable;
763 tmpi->next = insettable;
769 Inset* LyXParagraph::GetInset(int pos)
772 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
773 return NextAfterFootnote()->GetInset(pos - last - 1);
775 lyxerr << "ERROR (LyXParagraph::GetInset): position does not exist: "
782 InsetTable *tmpi = insettable;
784 while (tmpi && tmpi->pos != pos)
790 lyxerr << "ERROR (LyXParagraph::GetInset): "
791 "Inset does not exist: " << pos << endl;
792 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
793 // Did this commenting out introduce a bug? So far I have not
794 // seen any, please enlighten me. (Lgb)
795 // My guess is that since the inset does not exist, we might
796 // as well replace it with a space to prevent crashes. (Asger)
802 // Gets uninstantiated font setting at position.
803 // Optimized after profiling. (Asger)
804 LyXFont LyXParagraph::GetFontSettings(int pos)
807 FontTable *tmp = fonttable;
809 if (pos >= tmp->pos && pos <= tmp->pos_end)
815 /* > because last is the next unused position, and you can
816 * use it if you want */
817 else if (pos > last) {
818 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
819 return NextAfterFootnote()->GetFontSettings(pos - last - 1);
821 // Why is it an error to ask for the font of a
822 // position that does not exist? Would it be
823 // enough for this to be anable on debug?
824 // We want strict error checking, but it's ok to only
825 // have it when debugging. (Asger)
826 lyxerr << "ERROR (LyXParagraph::GetFontSettings): "
827 "position does not exist. " << pos << endl;
830 return GetFontSettings(pos - 1);
832 return LyXFont(LyXFont::ALL_INHERIT);
836 // Gets the fully instantiated font at a given position in a paragraph
837 // This is basically the same function as LyXText::GetFont() in text2.C.
838 // The difference is that this one is used for generating the LaTeX file,
839 // and thus cosmetic "improvements" are disallowed: This has to deliver
840 // the true picture of the buffer. (Asger)
841 // If position is -1, we get the layout font of the paragraph.
842 // If position is -2, we get the font of the manual label of the paragraph.
843 LyXFont LyXParagraph::getFont(int pos)
846 LyXLayout *layout = lyxstyle.Style(GetCurrentTextClass(),
850 if (layout->labeltype == LABEL_MANUAL)
851 main_body = BeginningOfMainBody();
856 layoutfont = layout->labelfont;
858 layoutfont = layout->font;
859 tmpfont = GetFontSettings(pos);
860 tmpfont.realize(layoutfont);
862 // process layoutfont for pos == -1 and labelfont for pos < -1
864 tmpfont = layout->font;
866 tmpfont = layout->labelfont;
869 // check for environment font information
870 char par_depth = GetDepth();
871 LyXParagraph * par = this;
872 while (par && par_depth && !tmpfont.resolved()) {
873 par = par->DepthHook(par_depth - 1);
875 tmpfont.realize(lyxstyle.
876 Style(GetCurrentTextClass(),
877 par->GetLayout())->font);
878 par_depth = par->GetDepth();
882 tmpfont.realize(lyxstyle.TextClass(GetCurrentTextClass())->defaultfont);
887 /// Returns the height of the highest font in range
888 LyXFont::FONT_SIZE LyXParagraph::HighestFontInRange(int startpos, int endpos) const
890 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
892 FontTable *tmp = fonttable;
894 if (startpos <= tmp->pos_end && endpos >= tmp->pos) {
895 LyXFont::FONT_SIZE size = tmp->font.size();
896 if (size > maxsize && size<=LyXFont::SIZE_HUGER)
905 char LyXParagraph::GetChar(int pos)
908 /* a workaround to 'fix' some bugs in text-class */
910 // This function is important. It should not work around bugs.
911 // Let's find the bugs instead and fix them. (Asger)
912 lyxerr << "FATAL ERROR (LyXParagraph::GetChar):"
913 " bad position " << pos << endl;
922 /* > because last is the next unused position, and you can
923 * use it if you want */
924 else if (pos > last) {
925 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
926 return NextAfterFootnote()->GetChar(pos - last - 1);
928 lyxerr << "ERROR (LyXParagraph::GetChar): "
929 "position does not exist." << endl;
931 } else { // pos==last
932 /* we should have a footnote environment */
933 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
934 // Notice that LyX does request the last char from time to time. (Asger)
935 // lyxerr << "ERROR (LyXParagraph::GetChar): "
936 // "expected footnote." << endl;
939 switch (next->footnotekind) {
940 case LyXParagraph::FOOTNOTE:
941 return LYX_META_FOOTNOTE;
942 case LyXParagraph::MARGIN:
943 return LYX_META_MARGIN;
944 case LyXParagraph::FIG:
945 case LyXParagraph::WIDE_FIG:
947 case LyXParagraph::TAB:
948 case LyXParagraph::WIDE_TAB:
950 case LyXParagraph::ALGORITHM:
951 return LYX_META_ALGORITHM;
953 // if (next->footnotekind == LyXParagraph::FOOTNOTE)
954 // return LYX_META_FOOTNOTE;
955 // if (next->footnotekind == LyXParagraph::MARGIN)
956 // return LYX_META_MARGIN;
957 // if (next->footnotekind == LyXParagraph::FIG)
958 // return LYX_META_FIG;
959 // if (next->footnotekind == LyXParagraph::TAB)
960 // return LYX_META_TAB;
961 // if (next->footnotekind == LyXParagraph::ALGORITHM)
962 // return LYX_META_ALGORITHM;
963 // lyxerr << "ERROR (LyXParagraph::GetChar): "
964 // "unknown footnote kind." << endl;
965 // return 'F'; /* this should not happen! */
966 // This _can_ not happen, due to the type of next->footnotekind
967 // being LyXParagraph::footnot_kind
968 return '\0'; // to shut up gcc
973 string LyXParagraph::GetWord(int & lastpos)
976 //Added 98/9/21 by REH
977 // return an string of the current word, and the end of the word
980 // the current word is defined as starting at the first character from
981 // the immediate left of lastpospos which meets the definition of IsLetter(),
982 // continuing to the last character to the right of this meeting
986 // i just left this in from GetChar()
989 /* a workaround to 'fix' some bugs in text-class */
991 // This function is important. It should not work around bugs.
992 // Let's find the bugs instead and fix them. (Asger)
993 lyxerr << "FATAL ERROR (LyXParagraph::GetWord):"
994 " bad position " << lastpos << endl;
1004 //i think the devcode aborts before this, but why not be
1006 if (lastpos < 0) lastpos=0;
1009 // move back until we have a letter
1011 //there's no real reason to have firstpos & lastpos as
1012 //separate variables as this is written, but maybe someon
1013 // will want to return firstpos in the future.
1015 //since someone might have typed a punctuation first
1016 int firstpos = lastpos;
1018 while ((firstpos >=0) && !IsLetter(firstpos))
1021 // now find the beginning by looking for a nonletter
1023 while ((firstpos>=0) && IsLetter(firstpos))
1026 // the above is now pointing to the preceeding non-letter
1030 // so copy characters into theword until we get a nonletter
1031 // note that this can easily exceed lastpos, wich means
1032 // that if used in the middle of a word, the whole word
1035 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1042 int LyXParagraph::Last()
1044 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1045 return last + NextAfterFootnote()->Last() + 1; /* the 1 is the symbol
1046 * for the footnote */
1052 LyXParagraph *LyXParagraph::ParFromPos(int pos)
1054 /* > because last is the next unused position, and you can
1055 * use it if you want */
1057 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1058 return NextAfterFootnote()->ParFromPos(pos - last - 1);
1060 lyxerr << "ERROR (LyXParagraph::ParFromPos): "
1061 "position does not exist." << endl;
1069 int LyXParagraph::PositionInParFromPos(int pos)
1071 /* > because last is the next unused position, and you can
1072 * use it if you want */
1074 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1075 return NextAfterFootnote()->PositionInParFromPos(pos - last - 1);
1078 "ERROR (LyXParagraph::PositionInParFromPos): "
1079 "position does not exist." << endl;
1087 void LyXParagraph::SetFont(int pos, LyXFont const & font)
1089 /* > because last is the next unused position, and you can
1090 * use it if you want */
1092 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1093 NextAfterFootnote()->SetFont(pos - last - 1, font);
1095 lyxerr << "ERROR (LyXParagraph::SetFont): "
1096 "position does not exist." << endl;
1101 LyXFont patternfont(LyXFont::ALL_INHERIT);
1103 // First, reduce font against layout/label font
1104 // Update: The SetCharFont() routine in text2.C already reduces font, so
1105 // we don't need to do that here. (Asger)
1106 // No need to simplify this because it will disappear in a new kernel. (Asger)
1108 // Next search font table
1112 FontTable *tmp = fonttable;
1113 while (tmp && !found) {
1114 if (pos >= tmp->pos && pos <= tmp->pos_end)
1121 /* if we did not find a font entry, but if the font at hand
1122 * is the same as default, we just forget it */
1123 if (font == patternfont)
1126 /* ok, we did not find a font entry. But maybe there is exactly
1127 * the needed font entry one position left */
1130 while (tmp2 && !found) {
1131 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1137 /* ok there is one. maybe it is exactly the needed font */
1138 if (tmp2->font == font) {
1139 /* put the position under the font */
1144 /* Add a new entry in the
1145 * fonttable for the position */
1146 tmp = new FontTable;
1149 tmp->font = patternfont;
1150 tmp->next = fonttable;
1154 /* we found a font entry. maybe we have to split it and create
1157 if (tmp->pos != tmp->pos_end) { /* more than one character */
1159 if (pos == tmp->pos) {
1160 /* maybe we could enlarge the left fonttable */
1164 while (tmp2 && !found) {
1165 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1171 /* Is there is one, and is it exactly the needed font? */
1172 if (found && tmp2->font == font) {
1173 /* put the position under the font */
1179 /* Add a new entry in the
1180 * fonttable for the position */
1181 tmp2 = new FontTable;
1182 tmp2->pos = pos + 1;
1183 tmp2->pos_end = tmp->pos_end;
1184 tmp2->font = tmp->font;
1186 tmp2->next = fonttable;
1189 else if (pos == tmp->pos_end) {
1190 /* Add a new entry in the
1191 * fonttable for the position */
1192 tmp2 = new FontTable;
1193 tmp2->pos = tmp->pos;
1194 tmp2->pos_end = tmp->pos_end - 1;
1195 tmp2->font = tmp->font;
1196 tmp->pos = tmp->pos_end;
1197 tmp2->next = fonttable;
1201 /* Add a new entry in the
1202 * fonttable for the position */
1203 tmp2 = new FontTable;
1204 tmp2->pos = tmp->pos;
1205 tmp2->pos_end = pos - 1;
1206 tmp2->font = tmp->font;
1207 tmp2->next = fonttable;
1210 tmp2 = new FontTable;
1211 tmp2->pos = pos + 1;
1212 tmp2->pos_end = tmp->pos_end;
1213 tmp2->font = tmp->font;
1214 tmp2->next = fonttable;
1227 /* this function is able to hide closed footnotes */
1228 LyXParagraph *LyXParagraph::Next()
1231 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1233 while (tmp && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1235 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1236 return tmp->Next(); /* there can be more than one footnote
1237 * in a logical paragraph */
1239 return next; /* this should never happen! */
1246 LyXParagraph *LyXParagraph::NextAfterFootnote()
1249 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1251 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1253 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1254 return tmp; /* there can be more than one footnote
1255 * in a logical paragraph */
1257 return next; /* this should never happen! */
1264 LyXParagraph *LyXParagraph::PreviousBeforeFootnote()
1267 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1269 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1270 tmp = tmp->previous;
1271 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1272 return tmp; /* there can be more than one footnote
1273 * in a logical paragraph */
1275 return previous; /* this should never happen! */
1282 LyXParagraph *LyXParagraph::LastPhysicalPar()
1285 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1289 while (tmp->next && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1290 tmp = tmp->NextAfterFootnote();
1297 LyXParagraph *LyXParagraph::FirstPhysicalPar()
1301 LyXParagraph *tmppar = this;
1303 while (tmppar && (tmppar->IsDummy()
1304 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1305 tmppar = tmppar->previous;
1308 return this; /* this should never happen! */
1314 /* this function is able to hide closed footnotes */
1315 LyXParagraph *LyXParagraph::Previous()
1317 LyXParagraph *tmp = previous;
1321 if (tmp->previous && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1322 tmp = tmp->previous;
1323 while (tmp && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1324 tmp = tmp->previous;
1325 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1326 return tmp->next->Previous();
1336 void LyXParagraph::BreakParagraph(int pos, int flag)
1338 int i, pos_end, pos_first;
1340 /* create a new paragraph */
1341 LyXParagraph *par = ParFromPos(pos);
1342 LyXParagraph *firstpar = FirstPhysicalPar();
1344 LyXParagraph *tmp = new LyXParagraph(par);
1346 tmp->footnoteflag = footnoteflag;
1347 tmp->footnotekind = footnotekind;
1349 /* this is an idea for a more userfriendly layout handling, I will
1350 * see what the users say */
1352 /* layout stays the same with latex-environments */
1354 tmp->SetOnlyLayout(firstpar->layout);
1355 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1358 if (Last() > pos || !Last() || flag == 2) {
1359 tmp->SetOnlyLayout(firstpar->layout);
1360 tmp->align = firstpar->align;
1361 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1363 tmp->line_bottom = firstpar->line_bottom;
1364 firstpar->line_bottom = false;
1365 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1366 firstpar->pagebreak_bottom = false;
1367 tmp->added_space_bottom = firstpar->added_space_bottom;
1368 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1370 tmp->depth = firstpar->depth;
1371 tmp->noindent = firstpar->noindent;
1373 /* copy everything behind the break-position to the new paragraph */
1375 while (ParFromPos(pos_first) != par)
1378 pos_end = pos_first + par->last - 1;
1380 /* make sure there is enough memory for the now larger
1381 paragraph. This is not neccessary, because
1382 InsertFromMinibuffer will enlarge the memory (it uses
1383 InsertChar of course). But doing it by hand
1384 is MUCH faster! (only one time, not thousend times!!) */
1386 tmp->Enlarge(0, pos_end - pos);
1388 for (i = pos; i <= pos_end; i++) {
1389 par->CutIntoMinibuffer(i - pos_first);
1390 tmp->InsertFromMinibuffer(i - pos);
1393 for (i = pos_end; i >= pos; i--)
1394 par->Erase(i - pos_first);
1395 /* free memory of the now shorter paragraph*/
1399 /* just an idea of me */
1401 tmp->line_top = firstpar->line_top;
1402 tmp->pagebreak_top = firstpar->pagebreak_top;
1403 tmp->added_space_top = firstpar->added_space_top;
1404 tmp->bibkey = firstpar->bibkey;
1406 /* layout stays the same with latex-environments */
1408 firstpar->SetOnlyLayout(tmp->layout);
1409 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1410 firstpar->depth = tmp->depth;
1416 void LyXParagraph::MakeSameLayout(LyXParagraph *par)
1418 par = par->FirstPhysicalPar();
1419 footnoteflag = par->footnoteflag;
1420 footnotekind = par->footnotekind;
1422 layout = par->layout;
1423 align = par-> align;
1424 SetLabelWidthString(par->labelwidthstring);
1426 line_bottom = par->line_bottom;
1427 pagebreak_bottom = par->pagebreak_bottom;
1428 added_space_bottom = par->added_space_bottom;
1430 line_top = par->line_top;
1431 pagebreak_top = par->pagebreak_top;
1432 added_space_top = par->added_space_top;
1434 pextra_type = par->pextra_type;
1435 pextra_width = par->pextra_width;
1436 pextra_widthp = par->pextra_widthp;
1437 pextra_alignment = par->pextra_alignment;
1438 pextra_hfill = par->pextra_hfill;
1439 pextra_start_minipage = par->pextra_start_minipage;
1441 noindent = par->noindent;
1446 LyXParagraph *LyXParagraph::FirstSelfrowPar()
1448 LyXParagraph *tmppar;
1452 (tmppar->IsDummy() && tmppar->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1453 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1454 tmppar = tmppar->previous;
1457 return this; /* this should never happen! */
1463 LyXParagraph *LyXParagraph::Clone()
1467 /* create a new paragraph */
1468 LyXParagraph *result = new LyXParagraph();
1470 result->MakeSameLayout(this);
1472 /* this is because of the dummy layout of the paragraphs that
1474 result->layout = layout;
1476 /* table stuff -- begin*/
1478 result->table = table->Clone();
1481 /* table stuff -- end*/
1484 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1487 /* copy everything behind the break-position to the new paragraph */
1489 /* make shure there is enough memory for the now larger paragraph.
1490 * This is not neccessary, because InsertFromMinibuffer will enlarge
1491 * the memory (it uses InsertChar of course). But doing it by hand
1492 * is MUCH faster! (only one time, not thousend times!!) */
1494 result->Enlarge(0, last+2);
1496 for (i = 0; i < last; i++) {
1497 CopyIntoMinibuffer(i);
1498 result->InsertFromMinibuffer(i);
1504 bool LyXParagraph::HasSameLayout(LyXParagraph* par)
1506 par = par->FirstPhysicalPar();
1509 par->footnoteflag == footnoteflag &&
1510 par->footnotekind == footnotekind &&
1512 par->layout == layout &&
1514 par->align == align &&
1516 par->line_bottom == line_bottom &&
1517 par->pagebreak_bottom == pagebreak_bottom &&
1518 par->added_space_bottom == added_space_bottom &&
1520 par->line_top == line_top &&
1521 par->pagebreak_top == pagebreak_top &&
1522 par->added_space_top == added_space_top &&
1524 par->pextra_type == pextra_type &&
1525 par->pextra_width == pextra_width &&
1526 par->pextra_widthp == pextra_widthp &&
1527 par->pextra_alignment == pextra_alignment &&
1528 par->pextra_hfill == pextra_hfill &&
1529 par->pextra_start_minipage == pextra_start_minipage &&
1531 par->table == table && // what means: NO TABLE AT ALL
1533 par->noindent == noindent &&
1534 par->depth == depth);
1538 void LyXParagraph::BreakParagraphConservative(int pos)
1540 int i, pos_end, pos_first;
1542 /* create a new paragraph */
1543 LyXParagraph *par = ParFromPos(pos);
1545 LyXParagraph *tmp = new LyXParagraph(par);
1547 tmp->MakeSameLayout(par);
1550 /* copy everything behind the break-position to the new
1553 while (ParFromPos(pos_first) != par)
1556 pos_end = pos_first + par->last - 1;
1558 /* make shure there is enough memory for the now larger
1559 paragraph. This is not neccessary, because
1560 InsertFromMinibuffer will enlarge the memory (it uses
1561 InsertChar of course). But doing it by hand
1562 is MUCH faster! (only one time, not thousend times!!) */
1564 tmp->Enlarge(0, pos_end - pos);
1566 for (i = pos; i <= pos_end; i++) {
1568 par->CutIntoMinibuffer(i - pos_first);
1569 tmp->InsertFromMinibuffer(i - pos);
1571 for (i = pos_end; i >= pos; i--)
1572 par->Erase(i - pos_first);
1574 /* free memory of the now shorter paragraph*/
1580 /* be carefull, this does not make any check at all */
1581 void LyXParagraph::PasteParagraph()
1583 int i, pos_end, pos_insert;
1584 LyXParagraph *the_next;
1586 /* copy the next paragraph to this one */
1589 LyXParagraph *firstpar = FirstPhysicalPar();
1591 /* first the DTP-stuff */
1592 firstpar->line_bottom = the_next->line_bottom;
1593 firstpar->added_space_bottom = the_next->added_space_bottom;
1594 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1596 pos_end = the_next->last - 1;
1597 pos_insert = Last();
1599 /* enlarge the paragraph. This is faster than enlarge it
1600 * every 10th insertion. */
1602 Enlarge(pos_insert, pos_end);
1604 /* ok, now copy the paragraph */
1605 for (i = 0; i <= pos_end; i++) {
1606 the_next->CutIntoMinibuffer(i);
1607 InsertFromMinibuffer(pos_insert + i);
1610 /* delete the next paragraph */
1615 void LyXParagraph::OpenFootnote(int pos)
1617 LyXParagraph *par = ParFromPos(pos);
1619 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1620 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1626 void LyXParagraph::CloseFootnote(int pos)
1628 LyXParagraph *par = ParFromPos(pos);
1630 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1631 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1637 int LyXParagraph::GetLayout()
1639 return FirstPhysicalPar()->layout;
1643 char LyXParagraph::GetDepth()
1645 return FirstPhysicalPar()->depth;
1649 char LyXParagraph::GetAlign()
1651 return FirstPhysicalPar()->align;
1655 string LyXParagraph::GetLabestring()
1657 return FirstPhysicalPar()->labelstring;
1661 int LyXParagraph::GetFirstCounter(int i)
1663 return FirstPhysicalPar()->counter[i];
1667 /* the next two functions are for the manual labels */
1668 string LyXParagraph::GetLabelWidthString()
1670 if (!FirstPhysicalPar()->labelwidthstring.empty())
1671 return FirstPhysicalPar()->labelwidthstring;
1673 return _("Senseless with this layout!");
1677 void LyXParagraph::SetLabelWidthString(string const & s)
1679 LyXParagraph *par = FirstPhysicalPar();
1681 par->labelwidthstring = s;
1685 void LyXParagraph::SetOnlyLayout(char new_layout)
1688 *par = FirstPhysicalPar(),
1692 par->layout = new_layout;
1693 /* table stuff -- begin*/
1696 /* table stuff -- end*/
1697 if (par->pextra_type == PEXTRA_NONE) {
1698 if (par->Previous()) {
1699 ppar = par->Previous()->FirstPhysicalPar();
1702 && (ppar->depth > par->depth))
1703 ppar = ppar->Previous()->FirstPhysicalPar();
1706 npar = par->Next()->NextAfterFootnote();
1709 && (npar->depth > par->depth))
1710 npar = npar->Next()->NextAfterFootnote();
1712 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1714 p1 = ppar->pextra_width,
1715 p2 = ppar->pextra_widthp;
1716 ppar->SetPExtraType(ppar->pextra_type,
1717 p1.c_str(),p2.c_str());
1719 if ((par->pextra_type == PEXTRA_NONE) &&
1720 npar && (npar->pextra_type != PEXTRA_NONE)) {
1722 p1 = npar->pextra_width,
1723 p2 = npar->pextra_widthp;
1724 npar->SetPExtraType(npar->pextra_type,
1725 p1.c_str(),p2.c_str());
1731 void LyXParagraph::SetLayout(char new_layout)
1734 *par = FirstPhysicalPar(),
1738 par->layout = new_layout;
1739 par->labelwidthstring.clear();
1740 par->align = LYX_ALIGN_LAYOUT;
1742 par->added_space_top = VSpace(VSpace::NONE);
1743 par->added_space_bottom = VSpace(VSpace::NONE);
1744 /* table stuff -- begin*/
1747 /* table stuff -- end*/
1748 if (par->pextra_type == PEXTRA_NONE) {
1749 if (par->Previous()) {
1750 ppar = par->Previous()->FirstPhysicalPar();
1753 && (ppar->depth > par->depth))
1754 ppar = ppar->Previous()->FirstPhysicalPar();
1757 npar = par->Next()->NextAfterFootnote();
1760 && (npar->depth > par->depth))
1761 npar = npar->Next()->NextAfterFootnote();
1763 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1765 p1 = ppar->pextra_width,
1766 p2 = ppar->pextra_widthp;
1767 ppar->SetPExtraType(ppar->pextra_type,
1768 p1.c_str(),p2.c_str());
1770 if ((par->pextra_type == PEXTRA_NONE) &&
1771 npar && (npar->pextra_type != PEXTRA_NONE)) {
1773 p1 = npar->pextra_width,
1774 p2 = npar->pextra_widthp;
1775 npar->SetPExtraType(npar->pextra_type,
1776 p1.c_str(),p2.c_str());
1782 /* if the layout of a paragraph contains a manual label, the beginning of the
1783 * main body is the beginning of the second word. This is what the par-
1784 * function returns. If the layout does not contain a label, the main
1785 * body always starts with position 0. This differentiation is necessary,
1786 * because there cannot be a newline or a blank <= the beginning of the
1787 * main body in TeX. */
1789 int LyXParagraph::BeginningOfMainBody()
1791 if (FirstPhysicalPar() != this)
1796 // while (i < last && !(i > 1 && GetChar(i-1)==' ')
1797 // && GetChar(i)!=LYX_META_NEWLINE)
1799 // Unroll the first two cycles of this loop
1800 // and remember the previous character to remove unnecessary GetChar() calls
1803 && GetChar(i) != LYX_META_NEWLINE) {
1805 char previous_char, temp;
1807 && (previous_char = GetChar(i)) != LYX_META_NEWLINE) {
1808 // Yes, this ^ is supposed to be "=" not "=="
1811 && previous_char != ' '
1812 && (temp = GetChar(i)) != LYX_META_NEWLINE) {
1814 previous_char = temp;
1819 if (i==0 && i == last &&
1820 !(footnoteflag==LyXParagraph::NO_FOOTNOTE
1821 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1823 i++; /* the cursor should not jump
1824 * to the main body if there
1830 LyXParagraph* LyXParagraph::DepthHook(int deth)
1832 LyXParagraph *newpar = this;
1837 newpar = newpar->FirstPhysicalPar()->Previous();
1838 } while (newpar && newpar->GetDepth() > deth
1839 && newpar->footnoteflag == footnoteflag);
1842 if (Previous() || GetDepth())
1843 lyxerr << "ERROR (LyXParagraph::DepthHook): "
1847 return newpar->FirstPhysicalPar();
1851 int LyXParagraph::AutoDeleteInsets()
1853 InsetTable *tmpi = insettable;
1854 InsetTable *tmpi2 = tmpi;
1860 if (tmpi2->inset->AutoDelete()) {
1865 lyxerr << "ERROR (LyXParagraph::AutoDeleteInsets): "
1866 "cannot auto-delete insets" << endl;
1872 Inset* LyXParagraph::ReturnNextInsetPointer(int &pos)
1874 InsetTable *tmpi = insettable;
1875 InsetTable *tmpi2 = 0;
1877 if (tmpi->pos >= pos) {
1878 if (!tmpi2 || tmpi->pos < tmpi2->pos)
1885 return tmpi2->inset;
1892 /* returns -1 if inset not found */
1893 int LyXParagraph::GetPositionOfInset(Inset* inset)
1895 /* find the entry */
1896 InsetTable *tmpi = insettable;
1897 while (tmpi && tmpi->inset != inset) {
1900 if (tmpi && tmpi->inset)
1903 /* think about footnotes */
1904 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
1905 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1907 NextAfterFootnote()->GetPositionOfInset(inset);
1909 return last + 1 + further;
1916 void LyXParagraph::readSimpleWholeFile(FILE *myfile)
1920 FileInfo fileInfo(fileno(myfile));
1921 long file_size = fileInfo.getSize();
1922 /* it is horrible, I know, but faster.
1923 * I should not use InsertString for that :-( */
1925 /* I will write a better insertion in the future */
1926 Enlarge(0, file_size + 10);
1930 if (!feof(myfile)) {
1934 } while (!feof(myfile));
1940 LyXParagraph* LyXParagraph::TeXOnePar(string &file, TexRow &texrow,
1941 string &foot, TexRow &foot_texrow,
1944 lyxerr[Debug::LATEX] << "TeXOnePar... " << this << endl;
1945 LyXParagraph *par = next;
1946 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), layout);
1948 bool further_blank_line = false;
1950 lyxerr << "ERROR (LyXParagraph::TeXOnePar) is dummy." << endl;
1952 if (start_of_appendix) {
1953 file += "\\appendix\n";
1957 if (tex_code_break_column && style->isCommand()){
1962 if (pagebreak_top) {
1963 file += "\\newpage";
1964 further_blank_line = true;
1966 if (added_space_top.kind() != VSpace::NONE) {
1967 file += added_space_top.asLatexCommand();
1968 further_blank_line = true;
1972 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
1973 file += "\\vspace{-1\\parskip}";
1974 further_blank_line = true;
1977 if (further_blank_line){
1982 switch (style->latextype) {
1985 file += style->latexname;
1986 file += style->latexparam;
1988 case LATEX_ITEM_ENVIRONMENT:
1990 bibkey->Latex(file, false);
1994 case LATEX_LIST_ENVIRONMENT:
2001 bool need_par = SimpleTeXOnePar(file, texrow);
2003 // Spit out footnotes
2004 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2005 && par->footnoteflag != footnoteflag) {
2006 par = par->TeXFootnote(file, texrow,
2007 foot, foot_texrow, foot_count);
2008 par->SimpleTeXOnePar(file, texrow);
2012 // Make sure that \\par is done with the font of the last
2013 // character if this has another size as the default.
2014 // This is necessary because LaTeX (and LyX on the screen)
2015 // calculates the space between the baselines according
2016 // to this font. (Matthias)
2017 LyXFont font = getFont(Last()-1);
2019 if (style->resfont.size() != font.size()) {
2021 file += font.latexSize();
2025 } else if (lyxstyle.Style(GetCurrentTextClass(),
2026 GetLayout())->isCommand()){
2027 if (style->resfont.size() != font.size()) {
2029 file += font.latexSize();
2033 } else if (style->resfont.size() != font.size()){
2034 file += "{\\" + font.latexSize() + " \\par}";
2037 switch (style->latextype) {
2038 case LATEX_ITEM_ENVIRONMENT:
2039 case LATEX_LIST_ENVIRONMENT:
2040 if (par && (depth < par->depth)) {
2045 case LATEX_ENVIRONMENT:
2046 // if its the last paragraph of the current environment
2047 // skip it otherwise fall through
2049 && (par->layout != layout
2050 || par->depth != depth
2051 || par->pextra_type != pextra_type))
2054 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2055 && footnotekind != LyXParagraph::FOOTNOTE
2056 && footnotekind != LyXParagraph::MARGIN
2060 // don't insert this if we would be adding it
2061 // before or after a table in a float. This
2062 // little trick is needed in order to allow
2063 // use of tables in \subfigures or \subtables.
2069 further_blank_line = false;
2071 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2072 further_blank_line = true;
2075 if (added_space_bottom.kind() != VSpace::NONE) {
2076 file += added_space_bottom.asLatexCommand();
2077 further_blank_line = true;
2080 if (pagebreak_bottom) {
2081 file += "\\newpage";
2082 further_blank_line = true;
2085 if (further_blank_line){
2090 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2091 par->footnoteflag == LyXParagraph::NO_FOOTNOTE) // &&
2092 // (pextra_type != PEXTRA_MINIPAGE ||
2093 /* (par && !par->pextra_type == PEXTRA_MINIPAGE)) */ ) {
2098 lyxerr[Debug::LATEX] << "TeXOnePar...done " << par << endl;
2103 // This one spits out the text of the paragraph
2104 bool LyXParagraph::SimpleTeXOnePar(string &file, TexRow &texrow)
2106 lyxerr[Debug::LATEX] << "SimpleTeXOnePar... " << this << endl;
2109 return SimpleTeXOneTablePar(file, texrow);
2115 bool return_value = false;
2116 //bool underbar = false;
2118 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2121 /* maybe we have to create a optional argument */
2122 if (style->labeltype != LABEL_MANUAL)
2125 main_body = BeginningOfMainBody();
2127 if (main_body > 0) {
2129 basefont = getFont(-2); // Get label font
2131 basefont = getFont(-1); // Get layout font
2139 if (style->isCommand()) {
2142 } else if (align != LYX_ALIGN_LAYOUT) {
2145 return_value = true;
2149 // Which font is currently active?
2150 LyXFont running_font = basefont;
2151 // Do we have an open font change?
2152 bool open_font = false;
2154 texrow.start(this, 0);
2156 for (int i = 0; i < last; i++) {
2158 // First char in paragraph or after label?
2159 if (i == main_body && !IsDummy()) {
2160 if (main_body > 0) {
2162 column += running_font.latexWriteEndChanges(file, basefont);
2165 basefont = getFont(-1); // Now use the layout font
2166 running_font = basefont;
2170 if (style->isCommand()) {
2173 } else if (align != LYX_ALIGN_LAYOUT) {
2176 return_value = true;
2180 file += "\\noindent ";
2184 case LYX_ALIGN_LEFT:
2185 file += "\\raggedright ";
2188 case LYX_ALIGN_RIGHT:
2189 file += "\\raggedleft ";
2192 case LYX_ALIGN_CENTER:
2193 file += "\\centering ";
2201 // Fully instantiated font
2202 LyXFont font = getFont(i);
2204 // Spaces at end of font change are simulated to be
2205 // outside font change, i.e. we write "\textXX{text} "
2206 // rather than "\textXX{text }". (Asger)
2207 if (open_font && c == ' ' && i <= last-2
2208 && !getFont(i+1).equalExceptLatex(running_font)
2209 && !getFont(i+1).equalExceptLatex(font)) {
2210 font = getFont(i+1);
2213 // We end font definition before blanks
2214 if (!font.equalExceptLatex(running_font) && open_font) {
2215 column += running_font.latexWriteEndChanges(file, basefont);
2216 running_font = basefont;
2220 // Blanks are printed before start of fontswitch
2222 // Do not print the separation of the optional argument
2223 if (i != main_body - 1) {
2224 SimpleTeXBlanks(file, texrow, i, column, font, style);
2228 // Do we need to change font?
2229 if (!font.equalExceptLatex(running_font)
2230 && i != main_body-1) {
2231 column += font.latexWriteStartChanges(file, basefont);
2232 running_font = font;
2236 if (c == LYX_META_NEWLINE) {
2237 // newlines are handled differently here than
2238 // the default in SimpleTeXSpecialChars().
2239 if (!style->newline_allowed
2240 || font.latex() == LyXFont::ON) {
2244 column += running_font.latexWriteEndChanges(file, basefont);
2247 basefont = getFont(-1);
2248 running_font = basefont;
2249 if (font.family() ==
2250 LyXFont::TYPEWRITER_FAMILY) {
2256 texrow.start(this, i+1);
2259 SimpleTeXSpecialChars(file, texrow,
2260 font, running_font, basefont,
2261 open_font, style, i, column, c);
2265 // If we have an open font definition, we have to close it
2267 running_font.latexWriteEndChanges(file, basefont);
2270 /* needed if there is an optional argument but no contents */
2271 if (main_body > 0 && main_body == last) {
2273 return_value = false;
2276 lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
2277 return return_value;
2281 // This one spits out the text of a table paragraph
2282 bool LyXParagraph::SimpleTeXOneTablePar(string &file, TexRow &texrow)
2284 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar... " << this << endl;
2288 bool return_value = false;
2289 int current_cell_number = -1;
2291 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2294 basefont = getFont(-1); // Get layout font
2295 // Which font is currently active?
2296 LyXFont running_font = basefont;
2297 // Do we have an open font change?
2298 bool open_font = false;
2301 if (!IsDummy()) { // it is dummy if it is in a float!!!
2302 if (style->isCommand()) {
2305 } else if (align != LYX_ALIGN_LAYOUT) {
2308 return_value = true;
2311 file += "\\noindent ";
2315 case LYX_ALIGN_LEFT:
2316 file += "\\raggedright ";
2319 case LYX_ALIGN_RIGHT:
2320 file += "\\raggedleft ";
2323 case LYX_ALIGN_CENTER:
2324 file += "\\centering ";
2329 current_cell_number = -1;
2330 tmp = table->TexEndOfCell(file,current_cell_number);
2334 texrow.start(this, 0);
2336 for (int i = 0; i < last; i++) {
2338 if (table->IsContRow(current_cell_number+1)) {
2339 if (c == LYX_META_NEWLINE)
2340 current_cell_number++;
2345 // Fully instantiated font
2346 LyXFont font = getFont(i);
2348 // Spaces at end of font change are simulated to be outside font change.
2349 // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
2350 if (open_font && c == ' ' && i <= last-2
2351 && getFont(i+1) != running_font && getFont(i+1) != font) {
2352 font = getFont(i+1);
2355 // We end font definition before blanks
2356 if (font != running_font && open_font) {
2357 column += running_font.latexWriteEndChanges(file, basefont);
2358 running_font = basefont;
2361 // Blanks are printed before start of fontswitch
2363 SimpleTeXBlanks(file, texrow, i, column, font, style);
2365 // Do we need to change font?
2366 if (font != running_font) {
2367 column += font.latexWriteStartChanges(file, basefont);
2368 running_font = font;
2371 // Do we need to turn on LaTeX mode?
2372 if (font.latex() != running_font.latex()) {
2373 if (font.latex() == LyXFont::ON
2374 && style->needprotect) {
2375 file += "\\protect ";
2379 if (c == LYX_META_NEWLINE) {
2380 // special case for inside a table
2381 // different from default case in SimpleTeXSpecialChars()
2383 column += running_font.latexWriteEndChanges(file, basefont);
2386 basefont = getFont(-1);
2387 running_font = basefont;
2388 current_cell_number++;
2389 if (table->CellHasContRow(current_cell_number) >= 0) {
2390 TeXContTableRows(file, i+1, current_cell_number, column, texrow);
2392 // if this cell follow only ContRows till end don't
2393 // put the EndOfCell because it is put after the
2395 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2396 current_cell_number--;
2399 int tmp = table->TexEndOfCell(file, current_cell_number);
2402 } else if (tmp < 0) {
2408 texrow.start(this, i+1);
2410 SimpleTeXSpecialChars(file, texrow,
2411 font, running_font, basefont,
2412 open_font, style, i, column, c);
2416 // If we have an open font definition, we have to close it
2418 running_font.latexWriteEndChanges(file, basefont);
2420 current_cell_number++;
2421 tmp = table->TexEndOfCell(file, current_cell_number);
2424 lyxerr[Debug::LATEX] << "SimpleTeXOneTablePar...done " << this << endl;
2425 return return_value;
2429 // This one spits out the text off ContRows in tables
2430 bool LyXParagraph::TeXContTableRows(string &file, int i,
2431 int current_cell_number,
2432 int &column, TexRow &texrow)
2434 lyxerr[Debug::LATEX] << "TeXContTableRows... " << this << endl;
2442 bool return_value = false;
2443 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2446 basefont = getFont(-1); // Get layout font
2447 // Which font is currently active?
2448 LyXFont running_font = basefont;
2449 // Do we have an open font change?
2450 bool open_font = false;
2453 cell = table->CellHasContRow(current_cell_number);
2454 current_cell_number++;
2456 // first find the right position
2458 for (; (i<last) && (current_cell_number<cell); i++) {
2460 if (c == LYX_META_NEWLINE)
2461 current_cell_number++;
2465 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2469 } else if ((c != ' ') && (c != LYX_META_NEWLINE)) {
2472 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE); i++) {
2475 // Fully instantiated font
2476 LyXFont font = getFont(i);
2478 // Spaces at end of font change are simulated to be outside font change.
2479 // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
2480 if (open_font && c == ' ' && i <= last-2
2481 && getFont(i+1) != running_font && getFont(i+1) != font) {
2482 font = getFont(i+1);
2485 // We end font definition before blanks
2486 if (font != running_font && open_font) {
2487 column += running_font.latexWriteEndChanges(file, basefont);
2488 running_font = basefont;
2491 // Blanks are printed before start of fontswitch
2493 SimpleTeXBlanks(file, texrow, i, column, font, style);
2495 // Do we need to change font?
2496 if (font != running_font) {
2497 column += font.latexWriteStartChanges(file, basefont);
2498 running_font = font;
2501 // Do we need to turn on LaTeX mode?
2502 if (font.latex() != running_font.latex()) {
2503 if (font.latex() == LyXFont::ON
2504 && style->needprotect)
2506 file += "\\protect ";
2510 SimpleTeXSpecialChars(file, texrow, font, running_font, basefont,
2511 open_font, style, i, column, c);
2513 // If we have an open font definition, we have to close it
2515 running_font.latexWriteEndChanges(file, basefont);
2518 basefont = getFont(-1);
2519 running_font = basefont;
2520 cell = table->CellHasContRow(current_cell_number);
2522 lyxerr[Debug::LATEX] << "TeXContTableRows...done " << this << endl;
2523 return return_value;
2527 bool LyXParagraph::linuxDocConvertChar(char c, string &sgml_string)
2529 bool retval = false;
2531 case LYX_META_HFILL:
2532 sgml_string.clear();
2534 case LYX_META_PROTECTED_SEPARATOR:
2537 case LYX_META_NEWLINE:
2541 sgml_string = "&";
2544 sgml_string = "<";
2547 sgml_string = ">";
2550 sgml_string = "$";
2553 sgml_string = "#";
2556 sgml_string = "%";
2559 sgml_string = "[";
2562 sgml_string = "]";
2565 sgml_string = "{";
2568 sgml_string = "}";
2571 sgml_string = "˜";
2574 sgml_string = """;
2577 sgml_string = "\";
2583 case '\0': /* Ignore :-) */
2584 sgml_string.clear();
2593 void LyXParagraph::SimpleDocBookOneTablePar(string &file, string &extra,
2594 int & desc_on, int depth)
2598 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar... " << this << endl;
2600 //bool return_value = false; // unused
2601 int current_cell_number = -1;
2602 LyXFont font1,font2;
2605 int main_body; //, j; // unused
2606 string emph="emphasis";
2607 bool emph_flag=false;
2608 int char_line_count=0;
2610 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2612 if (style->labeltype != LABEL_MANUAL)
2615 main_body = BeginningOfMainBody();
2617 /* gets paragraph main font */
2619 font1 = style->labelfont;
2621 font1 = style->font;
2623 char_line_count = depth;
2624 addNewlineAndDepth(file, depth);
2625 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2626 file += "<INFORMALTABLE>";
2627 addNewlineAndDepth(file, ++depth);
2629 current_cell_number = -1;
2630 tmp = table->DocBookEndOfCell(file,current_cell_number, depth);
2632 /* parsing main loop */
2633 for (int i = 0; i < last; i++) {
2635 if (table->IsContRow(current_cell_number+1)) {
2636 if (c == LYX_META_NEWLINE)
2637 current_cell_number++;
2642 // Fully instantiated font
2645 /* handle <emphasis> tag */
2646 if (font1.emph() != font2.emph() && i) {
2647 if (font2.emph() == LyXFont::ON) {
2648 file += "<emphasis>";
2650 } else if (emph_flag) {
2651 file += "</emphasis>";
2655 if (c == LYX_META_NEWLINE) {
2656 // we have only to control for emphasis open here!
2658 file += "</emphasis>";
2661 font1 = font2 = getFont(-1);
2662 current_cell_number++;
2663 if (table->CellHasContRow(current_cell_number) >= 0) {
2664 DocBookContTableRows(file, extra, desc_on, i+1,
2665 current_cell_number,
2668 // if this cell follow only ContRows till end don't
2669 // put the EndOfCell because it is put after the
2671 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2672 current_cell_number--;
2675 tmp=table->DocBookEndOfCell(file, current_cell_number,
2680 } else if (c == LYX_META_INSET) {
2681 inset = GetInset(i);
2683 inset->DocBook(tmp_out);
2685 // This code needs some explanation:
2686 // Two insets are treated specially
2687 // label if it is the first element in a command paragraph
2689 // graphics inside tables or figure floats can't go on
2690 // title (the equivalente in latex for this case is caption
2691 // and title should come first
2694 if(desc_on!=3 || i!=0) {
2695 if(tmp_out[0]=='@') {
2697 extra += frontStrip(tmp_out, '@');
2699 file += frontStrip(tmp_out, '@');
2703 } else if (font2.latex() == LyXFont::ON) {
2704 // "TeX"-Mode on ==> SGML-Mode on.
2710 if (linuxDocConvertChar(c, sgml_string)
2711 && !style->free_spacing) {
2712 // in freespacing mode, spaces are
2713 // non-breaking characters
2718 file += "</term><listitem><para>";
2724 file += sgml_string;
2730 /* needed if there is an optional argument but no contents */
2731 if (main_body > 0 && main_body == last) {
2732 font1 = style->font;
2736 file += "</emphasis>";
2739 current_cell_number++;
2740 tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
2741 /* resets description flag correctly */
2744 /* <term> not closed... */
2748 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2749 file += "</INFORMALTABLE>";
2751 lyxerr[Debug::LATEX] << "SimpleDocbookOneTablePar...done "
2755 void LyXParagraph::DocBookContTableRows(string &file, string &extra,
2756 int & desc_on, int i,
2757 int current_cell_number, int &column)
2762 lyxerr[Debug::LATEX] << "DocBookContTableRows... " << this << endl;
2764 int cell, lastpos; //tmp; //unused
2765 LyXFont font1,font2;
2768 int main_body; // , j; // unused
2769 string emph="emphasis";
2770 bool emph_flag=false;
2771 int char_line_count=0;
2773 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2775 if (style->labeltype != LABEL_MANUAL)
2778 main_body = BeginningOfMainBody();
2780 /* gets paragraph main font */
2782 font1 = style->labelfont;
2784 font1 = style->font;
2787 cell = table->CellHasContRow(current_cell_number);
2788 current_cell_number++;
2790 // first find the right position
2792 for (; (i<last) && (current_cell_number<cell); i++) {
2794 if (c == LYX_META_NEWLINE)
2795 current_cell_number++;
2799 // I don't know how to handle this so I comment it
2800 // for the moment (Jug)
2801 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2802 // file += " \\\\\n";
2805 if ((c != ' ') && (c != LYX_META_NEWLINE)) {
2808 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE); i++) {
2811 // Fully instantiated font
2814 /* handle <emphasis> tag */
2815 if (font1.emph() != font2.emph() && i) {
2816 if (font2.emph() == LyXFont::ON) {
2817 file += "<emphasis>";
2819 } else if (emph_flag) {
2820 file += "</emphasis>";
2824 if (c == LYX_META_INSET) {
2825 inset = GetInset(i);
2827 inset->DocBook(tmp_out);
2829 // This code needs some explanation:
2830 // Two insets are treated specially
2831 // label if it is the first element in a command paragraph
2833 // graphics inside tables or figure floats can't go on
2834 // title (the equivalente in latex for this case is caption
2835 // and title should come first
2838 if(desc_on!=3 || i!=0) {
2839 if(tmp_out[0]=='@') {
2841 extra += frontStrip(tmp_out, '@');
2843 file += frontStrip(tmp_out, '@');
2847 } else if (font2.latex() == LyXFont::ON) {
2848 // "TeX"-Mode on ==> SGML-Mode on.
2854 if (linuxDocConvertChar(c, sgml_string)
2855 && !style->free_spacing) {
2856 // in freespacing mode, spaces are
2857 // non-breaking characters
2862 file += "</term><listitem><para>";
2868 file += sgml_string;
2872 // we have only to control for emphasis open here!
2874 file += "</emphasis>";
2877 font1 = font2 = getFont(-1);
2878 cell = table->CellHasContRow(current_cell_number);
2880 lyxerr[Debug::LATEX] << "DocBookContTableRows...done " << this << endl;
2885 void LyXParagraph::SimpleTeXBlanks(string &file, TexRow &texrow,
2886 int const i, int &column, LyXFont const &font,
2887 LyXLayout const * const style)
2889 if (column > tex_code_break_column
2891 && GetChar(i-1) != ' '
2893 // In LaTeX mode, we don't want to
2894 // break lines since some commands
2896 && ! (font.latex() == LyXFont::ON)
2897 // same in FreeSpacing mode
2898 && !style->free_spacing
2899 // In typewriter mode, we want to avoid
2900 // ! . ? : at the end of a line
2901 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
2902 && (GetChar(i-1) == '.'
2903 || GetChar(i-1) == '?'
2904 || GetChar(i-1) == ':'
2905 || GetChar(i-1) == '!'))) {
2906 if (tex_code_break_column == 0) {
2907 // in batchmode we need LaTeX to still
2908 // see it as a space not as an extra '\n'
2914 texrow.start(this, i+1);
2916 } else if (font.latex() == LyXFont::OFF) {
2917 if (style->free_spacing) {
2927 void LyXParagraph::SimpleTeXSpecialChars(string &file, TexRow &texrow,
2928 LyXFont &font, LyXFont &running_font, LyXFont &basefont,
2929 bool &open_font, LyXLayout const * const style,
2930 int &i, int &column, char const c)
2934 // Two major modes: LaTeX or plain
2935 // Handle here those cases common to both modes
2936 // and then split to handle the two modes separately.
2938 case LYX_META_INSET:
2939 inset = GetInset(i);
2941 int len = file.length();
2942 int tmp = inset->Latex(file, style->isCommand());
2947 column += file.length() - len;
2955 case LYX_META_NEWLINE:
2957 column += running_font.latexWriteEndChanges(file, basefont);
2960 basefont = getFont(-1);
2961 running_font = basefont;
2964 case LYX_META_HFILL:
2965 file += "\\hfill{}";
2970 // And now for the special cases within each mode
2971 // Are we in LaTeX mode?
2972 if (font.latex() == LyXFont::ON) {
2973 // at present we only have one option
2974 // but I'll leave it as a switch statement
2975 // so its simpler to extend. (ARRae)
2977 case LYX_META_PROTECTED_SEPARATOR:
2982 // make sure that we will not print
2983 // error generating chars to the tex
2984 // file. This test would not be needed
2985 // if it were done in the buffer
2993 // Plain mode (i.e. not LaTeX)
2995 case LYX_META_PROTECTED_SEPARATOR:
3000 file += "\\textbackslash{}";
3004 case '°': case '±': case '²': case '³':
3005 case '×': case '÷': case '¹': case 'ª':
3006 case 'º': case '¬': case 'µ':
3007 if (current_view->currentBuffer()->params.inputenc == "latin1") {
3008 file += "\\ensuremath{";
3017 case '|': case '<': case '>':
3018 // In T1 encoding, these characters exist
3019 if (lyxrc->fontenc == "T1") {
3021 //... but we should avoid ligatures
3022 if ((c == '>' || c == '<')
3024 && GetChar(i+1) == c){
3025 file += "\\textcompwordmark{}";
3030 // Typewriter font also has them
3031 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3035 // Otherwise, we use what LaTeX
3039 file += "\\textless{}";
3043 file += "\\textgreater{}";
3047 file += "\\textbar{}";
3053 case '-': // "--" in Typewriter mode -> "-{}-"
3055 && GetChar(i+1) == '-'
3056 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3065 file += "\\char`\\\"{}";
3070 if (current_view->currentBuffer()->params.inputenc == "default") {
3071 file += "\\pounds{}";
3079 case '%': case '#': case '{':
3093 case '*': case '[': case ']':
3094 // avoid being mistaken for optional arguments
3102 /* blanks are printed before font switching */
3103 // Sure? I am not! (try nice-latex)
3104 // I am sure it's correct. LyX might be smarter
3105 // in the future, but for now, nothing wrong is
3110 /* idea for labels --- begin*/
3114 && font.family() != LyXFont::TYPEWRITER_FAMILY
3115 && GetChar(i+1) == 'y'
3116 && GetChar(i+2) == 'X') {
3124 && font.family() != LyXFont::TYPEWRITER_FAMILY
3125 && GetChar(i+1) == 'e'
3126 && GetChar(i+2) == 'X') {
3131 /* check for LaTeX2e */
3134 && font.family() != LyXFont::TYPEWRITER_FAMILY
3135 && GetChar(i+1) == 'a'
3136 && GetChar(i+2) == 'T'
3137 && GetChar(i+3) == 'e'
3138 && GetChar(i+4) == 'X'
3139 && GetChar(i+5) == '2'
3140 && GetChar(i+6) == 'e') {
3141 file += "\\LaTeXe{}";
3145 /* check for LaTeX */
3148 && font.family() != LyXFont::TYPEWRITER_FAMILY
3149 && GetChar(i+1) == 'a'
3150 && GetChar(i+2) == 'T'
3151 && GetChar(i+3) == 'e'
3152 && GetChar(i+4) == 'X') {
3153 file += "\\LaTeX{}";
3156 /* idea for labels --- end*/
3157 } else if (c != '\0') {
3167 bool LyXParagraph::RoffContTableRows(FILE *fp, int i, int actcell)
3173 font1 = LyXFont(LyXFont::ALL_INHERIT),
3186 fname2 = TmpFileName(string(),"RAT2");
3188 cell = table->CellHasContRow(actcell);
3191 // first find the right position
3193 for (; (i<last) && (actcell<cell); i++) {
3195 if (c == LYX_META_NEWLINE)
3200 if ((c != ' ') && (c != LYX_META_NEWLINE))
3202 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE); i++) {
3203 font2 = GetFontSettings(i);
3204 if (font1.latex() != font2.latex()) {
3205 if (font2.latex() != LyXFont::OFF)
3210 case LYX_META_INSET:
3211 if ((inset = GetInset(i))) {
3212 if (!(fp2=fopen(fname2.c_str(),"w+"))) {
3213 WriteAlert(_("LYX_ERROR:"), _("Cannot open temporary file:"), fname2);
3216 inset->Latex(fp2,-1);
3229 case LYX_META_NEWLINE:
3231 case LYX_META_HFILL:
3233 case LYX_META_PROTECTED_SEPARATOR:
3236 fprintf(fp, "\\\\");
3240 fprintf(fp, "%c", c);
3242 lyxerr.debug() << "RoffAsciiTable: NULL char in structure." << endl;
3246 cell = table->CellHasContRow(actcell);
3251 LyXParagraph * LyXParagraph::TeXDeeper(string &file, TexRow &texrow,
3252 string &foot, TexRow &foot_texrow,
3255 lyxerr[Debug::LATEX] << "TeXDeeper... " << this << endl;
3256 LyXParagraph *par = this;
3258 while (par && par->depth == depth) {
3260 lyxerr << "ERROR (LyXParagraph::TeXDeeper)" << endl;
3261 if (lyxstyle.Style(GetCurrentTextClass(),
3262 par->layout)->isEnvironment()
3263 || par->pextra_type != PEXTRA_NONE)
3265 par = par->TeXEnvironment(file, texrow,
3269 par = par->TeXOnePar(file, texrow,
3274 lyxerr[Debug::LATEX] << "TeXDeeper...done " << par << endl;
3280 LyXParagraph* LyXParagraph::TeXEnvironment(string &file, TexRow &texrow,
3281 string &foot, TexRow &foot_texrow,
3285 eindent_open = false;
3287 foot_this_level = false;
3288 // flags when footnotetext should be appended to file.
3290 minipage_open = false;
3292 minipage_open_depth = 0;
3294 par_sep = current_view->currentBuffer()->params.paragraph_separation;
3296 lyxerr[Debug::LATEX] << "TeXEnvironment... " << this << endl;
3298 lyxerr << "ERROR (LyXParagraph::TeXEnvironment)" << endl;
3300 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), layout);
3302 if (pextra_type == PEXTRA_INDENT) {
3303 if (!pextra_width.empty()) {
3304 file += "\\begin{LyXParagraphIndent}{"
3305 + pextra_width + "}\n";
3307 //float ib = atof(pextra_widthp.c_str())/100;
3308 // string can't handle floats at present (971109)
3309 // so I'll do a conversion by hand knowing that
3310 // the limits are 0.0 to 1.0. ARRae.
3311 file += "\\begin{LyXParagraphIndent}{";
3312 switch (pextra_widthp.length()) {
3318 file += pextra_widthp;
3322 file += pextra_widthp;
3324 file += "\\columnwidth}\n";
3327 eindent_open = true;
3329 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3330 if (pextra_hfill && Previous() &&
3331 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3332 file += "\\hfill{}\n";
3335 if (par_sep == LYX_PARSEP_INDENT) {
3336 file += "{\\setlength\\parindent{0pt}\n";
3339 file += "\\begin{minipage}";
3340 switch(pextra_alignment) {
3341 case MINIPAGE_ALIGN_TOP:
3344 case MINIPAGE_ALIGN_MIDDLE:
3347 case MINIPAGE_ALIGN_BOTTOM:
3351 if (!pextra_width.empty()) {
3353 file += pextra_width + "}\n";
3355 //float ib = atof(par->pextra_width.c_str())/100;
3356 // string can't handle floats at present
3357 // so I'll do a conversion by hand knowing that
3358 // the limits are 0.0 to 1.0. ARRae.
3360 switch (pextra_widthp.length()) {
3366 file += pextra_widthp;
3370 file += pextra_widthp;
3372 file += "\\columnwidth}\n";
3375 if (par_sep == LYX_PARSEP_INDENT) {
3376 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3379 minipage_open = true;
3380 minipage_open_depth = depth;
3383 #ifdef WITH_WARNINGS
3384 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3385 //I disabled it because it breaks when lists span on several
3388 if (style->isEnvironment()){
3389 if (style->latextype == LATEX_LIST_ENVIRONMENT) {
3390 #ifdef FANCY_FOOTNOTE_CODE
3391 if (foot_count < 0) {
3392 // flag that footnote[mark][text] should be
3393 // used for any footnotes from now on
3395 foot_this_level = true;
3398 file += "\\begin{" + style->latexname + "}{"
3399 + labelwidthstring + "}\n";
3400 } else if (style->labeltype == LABEL_BIBLIO) {
3402 file += "\\begin{" + style->latexname + "}{"
3403 + bibitemWidthest() + "}\n";
3404 } else if (style->latextype == LATEX_ITEM_ENVIRONMENT) {
3405 #ifdef FANCY_FOOTNOTE_CODE
3406 if (foot_count < 0) {
3407 // flag that footnote[mark][text] should be
3408 // used for any footnotes from now on
3410 foot_this_level = true;
3413 file += "\\begin{" + style->latexname + '}'
3414 + style->latexparam + '\n';
3416 file += "\\begin{" + style->latexname + '}'
3417 + style->latexparam + '\n';
3420 LyXParagraph *par = this;
3422 par = par->TeXOnePar(file, texrow,
3423 foot, foot_texrow, foot_count);
3425 if (eindent_open && par && par->pextra_type != PEXTRA_INDENT) {
3426 file += "\\end{LyXParagraphIndent}\n";
3428 eindent_open = false;
3429 if (!style->isEnvironment())
3433 if (minipage_open && par && !style->isEnvironment() &&
3434 (par->pextra_type == PEXTRA_MINIPAGE) &&
3435 par->pextra_start_minipage) {
3436 file += "\\end{minipage}\n";
3438 if (par_sep == LYX_PARSEP_INDENT) {
3442 minipage_open = false;
3444 if (par && par->depth > depth) {
3445 if (lyxstyle.Style(GetCurrentTextClass(),
3446 par->layout)->isParagraph()
3448 && !suffixIs(file, "\n\n")) {
3449 // There should be at least one '\n' already
3450 // but we need there to be two for Standard
3451 // paragraphs that are depth-increment'ed to be
3452 // output correctly. However, tables can also be
3453 // paragraphs so don't adjust them. ARRae
3457 par = par->TeXDeeper(file, texrow,
3458 foot, foot_texrow, foot_count);
3460 if (par && par->layout == layout && par->depth == depth &&
3461 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3462 if (par->pextra_hfill && par->Previous() &&
3463 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3464 file += "\\hfill{}\n";
3469 if (par_sep == LYX_PARSEP_INDENT) {
3470 file += "{\\setlength\\parindent{0pt}\n";
3473 file += "\\begin{minipage}";
3474 switch(par->pextra_alignment) {
3475 case MINIPAGE_ALIGN_TOP:
3478 case MINIPAGE_ALIGN_MIDDLE:
3481 case MINIPAGE_ALIGN_BOTTOM:
3485 if (!par->pextra_width.empty()) {
3487 file += par->pextra_width;
3490 //float ib = atof(par->pextra_widthp.c_str())/100;
3491 // string can't handle floats at present
3492 // so I'll do a conversion by hand knowing that
3493 // the limits are 0.0 to 1.0. ARRae.
3495 switch (par->pextra_widthp.length()) {
3501 file += par->pextra_widthp;
3505 file += par->pextra_widthp;
3507 file += "\\columnwidth}\n";
3510 if (par_sep == LYX_PARSEP_INDENT) {
3511 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3514 minipage_open = true;
3515 minipage_open_depth = par->depth;
3518 && par->layout == layout
3519 && par->depth == depth
3520 && par->pextra_type == pextra_type);
3522 if (style->isEnvironment()) {
3523 file += "\\end{" + style->latexname + '}';
3524 // maybe this should go after the minipage closes?
3525 if (foot_this_level) {
3526 if (foot_count >= 1) {
3527 if (foot_count > 1) {
3528 file += "\\addtocounter{footnote}{-";
3529 file += tostr(foot_count - 1);
3533 texrow += foot_texrow;
3535 foot_texrow.reset();
3540 if (minipage_open && (minipage_open_depth == depth) &&
3541 (!par || par->pextra_start_minipage ||
3542 par->pextra_type != PEXTRA_MINIPAGE)) {
3543 file += "\\end{minipage}\n";
3545 if (par_sep == LYX_PARSEP_INDENT) {
3549 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3550 file += "\\medskip\n\n";
3554 minipage_open = false;
3557 file += "\\end{LyXParagraphIndent}\n";
3560 // if (tex_code_break_column){
3561 if (!(par && (par->pextra_type==PEXTRA_MINIPAGE)
3562 && par->pextra_hfill)) {
3566 lyxerr[Debug::LATEX] << "TeXEnvironment...done " << par << endl;
3567 return par; // ale970302
3571 LyXParagraph * LyXParagraph::TeXFootnote(string &file, TexRow &texrow,
3572 string &foot, TexRow &foot_texrow,
3575 lyxerr[Debug::LATEX] << "TeXFootnote... " << this << endl;
3576 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3577 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3578 "No footnote!" << endl;
3580 LyXParagraph *par = this;
3581 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(),
3582 previous->GetLayout());
3584 if (style->needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3585 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3586 "Float other than footnote in command"
3587 " with moving argument is illegal" << endl;
3590 if (footnotekind != LyXParagraph::FOOTNOTE
3591 && footnotekind != LyXParagraph::MARGIN
3593 && !suffixIs(file, '\n')) {
3594 // we need to ensure that real floats like tables and figures
3595 // have their \begin{} on a new line otherwise we can get
3596 // incorrect results when using the endfloat.sty package
3597 // especially if two floats follow one another. ARRae 981022
3598 // NOTE: if the file is length 0 it must have just been
3599 // written out so we assume it ended with a '\n'
3604 BufferParams *params = ¤t_view->currentBuffer()->params;
3605 bool footer_in_body = true;
3606 switch (footnotekind) {
3607 case LyXParagraph::FOOTNOTE:
3608 if (style->intitle) {
3609 file += "\\thanks{\n";
3610 footer_in_body = false;
3612 if (foot_count == -1) {
3613 // we're at depth 0 so we can use:
3614 file += "\\footnote{%\n";
3615 footer_in_body = false;
3617 file += "\\footnotemark{}%\n";
3619 // we only need this when there are
3620 // multiple footnotes
3621 foot += "\\stepcounter{footnote}";
3623 foot += "\\footnotetext{%\n";
3624 foot_texrow.start(this,0);
3625 foot_texrow.newline();
3630 case LyXParagraph::MARGIN:
3631 file += "\\marginpar{\n";
3633 case LyXParagraph::FIG:
3634 if (pextra_type == PEXTRA_FLOATFLT
3635 && (!pextra_width.empty()
3636 || !pextra_widthp.empty())) {
3638 if (!pextra_width.empty())
3639 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
3640 pextra_width.c_str());
3642 sprintf(bufr, "\\begin{floatingfigure}{%f\\textwidth}\n",
3643 atoi(pextra_widthp.c_str())/100.0);
3646 file += "\\begin{figure}";
3647 if (!params->float_placement.empty()) {
3649 file += params->float_placement;
3656 case LyXParagraph::TAB:
3657 file += "\\begin{table}";
3658 if (!params->float_placement.empty()) {
3660 file += params->float_placement;
3666 case LyXParagraph::WIDE_FIG:
3667 file += "\\begin{figure*}";
3668 if (!params->float_placement.empty()) {
3670 file += params->float_placement;
3676 case LyXParagraph::WIDE_TAB:
3677 file += "\\begin{table*}";
3678 if (!params->float_placement.empty()) {
3680 file += params->float_placement;
3686 case LyXParagraph::ALGORITHM:
3687 file += "\\begin{algorithm}\n";
3692 if (footnotekind != LyXParagraph::FOOTNOTE
3693 || !footer_in_body) {
3694 // Process text for all floats except footnotes in body
3696 LyXLayout *style = lyxstyle.Style(GetCurrentTextClass(),
3699 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3701 if (style->isEnvironment()
3702 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3703 // Allows the use of minipages within float environments.
3704 // Shouldn't be circular because we don't support
3705 // footnotes inside floats (yet). ARRae
3706 par = par->TeXEnvironment(file, texrow,
3710 par = par->TeXOnePar(file, texrow,
3715 if (par && !par->IsDummy() && par->depth > depth) {
3716 par = par->TeXDeeper(file, texrow,
3720 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3722 // process footnotes > depth 0 or in environments separately
3723 // NOTE: Currently don't support footnotes within footnotes
3724 // even though that is possible using the \footnotemark
3726 TexRow dummy_texrow;
3727 int dummy_count = 0;
3729 LyXLayout *style = lyxstyle.Style(GetCurrentTextClass(),
3732 lyxerr << "ERROR (LyXParagraph::TeXFootnote)"
3734 if (style->isEnvironment()
3735 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3736 // Allows the use of minipages within float environments.
3737 // Shouldn't be circular because we don't support
3738 // footnotes inside floats (yet). ARRae
3739 par = par->TeXEnvironment(foot, foot_texrow,
3740 dummy, dummy_texrow,
3743 par = par->TeXOnePar(foot, foot_texrow,
3744 dummy, dummy_texrow,
3748 if (par && !par->IsDummy() && par->depth > depth) {
3749 par = par->TeXDeeper(foot, foot_texrow,
3750 dummy, dummy_texrow,
3753 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3755 lyxerr << "ERROR (LyXParagraph::TeXFootnote): "
3756 "Footnote in a Footnote -- not supported"
3761 switch (footnotekind) {
3762 case LyXParagraph::FOOTNOTE:
3763 if (footer_in_body) {
3764 // This helps tell which of the multiple
3765 // footnotetexts an error was in.
3767 foot_texrow.newline();
3772 case LyXParagraph::MARGIN:
3775 case LyXParagraph::FIG:
3776 if (pextra_type == PEXTRA_FLOATFLT
3777 && (!pextra_width.empty()
3778 || !pextra_widthp.empty()))
3779 file += "\\end{floatingfigure}";
3781 file += "\\end{figure}";
3783 case LyXParagraph::TAB:
3784 file += "\\end{table}";
3786 case LyXParagraph::WIDE_FIG:
3787 file += "\\end{figure*}";
3789 case LyXParagraph::WIDE_TAB:
3790 file += "\\end{table*}";
3792 case LyXParagraph::ALGORITHM:
3793 file += "\\end{algorithm}";
3797 if (footnotekind != LyXParagraph::FOOTNOTE
3798 && footnotekind != LyXParagraph::MARGIN) {
3799 // we need to ensure that real floats like tables and figures
3800 // have their \end{} on a line of their own otherwise we can
3801 // get incorrect results when using the endfloat.sty package.
3806 lyxerr[Debug::LATEX] << "TeXFootnote...done " << par->next << endl;
3811 void LyXParagraph::SetPExtraType(int type, const char *width,const char *widthp)
3814 pextra_width = width;
3815 pextra_widthp = widthp;
3817 if (lyxstyle.Style(GetCurrentTextClass(),
3818 layout)->isEnvironment()) {
3823 while (par && (par->layout == layout) && (par->depth == depth)) {
3825 par = par->Previous();
3827 par = par->FirstPhysicalPar();
3828 while (par && par->depth > depth) {
3829 par = par->Previous();
3831 par = par->FirstPhysicalPar();
3835 while (par && (par->layout == layout) && (par->depth == depth)) {
3836 par->pextra_type = type;
3837 par->pextra_width = width;
3838 par->pextra_widthp = widthp;
3839 par = par->NextAfterFootnote();
3840 if (par && (par->depth > depth))
3841 par->SetPExtraType(type,width,widthp);
3842 while (par && ((par->depth > depth) || par->IsDummy()))
3843 par = par->NextAfterFootnote();
3848 void LyXParagraph::UnsetPExtraType()
3850 if (pextra_type == PEXTRA_NONE)
3853 pextra_type = PEXTRA_NONE;
3854 pextra_width.clear();
3855 pextra_widthp.clear();
3857 if (lyxstyle.Style(GetCurrentTextClass(),
3858 layout)->isEnvironment()) {
3863 while (par && (par->layout == layout) && (par->depth == depth)) {
3865 par = par->Previous();
3867 par = par->FirstPhysicalPar();
3868 while (par && par->depth > depth) {
3869 par = par->Previous();
3871 par = par->FirstPhysicalPar();
3875 while (par && (par->layout == layout) && (par->depth == depth)) {
3876 par->pextra_type = PEXTRA_NONE;
3877 par->pextra_width.clear();
3878 par->pextra_widthp.clear();
3879 par = par->NextAfterFootnote();
3880 if (par && (par->depth > depth))
3881 par->UnsetPExtraType();
3882 while (par && ((par->depth > depth) || par->IsDummy()))
3883 par = par->NextAfterFootnote();