1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright (C) 1995 Matthias Ettrich
7 * Copyright (C) 1995-1998 The LyX Team.
9 *======================================================*/
14 #pragma implementation "lyxparagraph.h"
17 #include "lyxparagraph.h"
20 #include "tex-strings.h"
21 #include "bufferparams.h"
24 #include "LaTeXFeatures.h"
25 #include "insets/insetinclude.h"
26 #include "filetools.h"
27 #include "lyx_gui_misc.h"
30 // $Id: paragraph.C,v 1.1 1999/09/27 18:44:38 larsbj Exp $
32 #if !defined(lint) && !defined(WITH_WARNINGS)
33 static char vcid[] = "$Id: paragraph.C,v 1.1 1999/09/27 18:44:38 larsbj Exp $";
36 #define INITIAL_SIZE_PAR 10 /*Number of bytes in one paragraph*/
37 #define STEP_SIZE_PAR 10 /*Number of bytes added when reallocated*/
39 extern void addNewlineAndDepth(LString & file, int const depth); // Jug 990923
40 extern unsigned char GetCurrentTextClass(); // this should be fixed/removed
41 int tex_code_break_column = 72; // needs non-zero initialization. set later.
42 // this is a bad idea, but how can LyXParagraph find its buffer to get
43 // parameters? (JMarc)
44 extern BufferView *current_view;
49 extern LString bibitemWidthest();
51 /* this is a minibuffer */
52 static char minibuffer_char;
53 static LyXFont minibuffer_font;
54 static Inset *minibuffer_inset;
57 // Initialization of the counter for the paragraph id's,
58 // declared in lyxparagraph.h
59 unsigned int LyXParagraph::paragraph_id = 0;
62 LyXParagraph::LyXParagraph()
64 size = INITIAL_SIZE_PAR;
66 text = new char[size];
67 for (int i=0; i<10; i++) setCounter(i , 0);
75 footnoteflag = LyXParagraph::NO_FOOTNOTE;
77 align = LYX_ALIGN_BLOCK;
79 /* table stuff -- begin*/
81 /* table stuff -- end*/
83 bibkey = NULL; // ale970302
88 /* this konstruktor inserts the new paragraph in a list */
89 LyXParagraph::LyXParagraph(LyXParagraph *par)
91 size = INITIAL_SIZE_PAR;
93 text = new char[size];
94 for (int i=0; i<10; i++) setCounter(i, 0);
100 next->previous = this;
102 previous->next = this;
105 footnoteflag = LyXParagraph::NO_FOOTNOTE;
106 footnotekind = LyXParagraph::FOOTNOTE;
108 /* table stuff -- begin*/
110 /* table stuff -- end*/
113 bibkey = NULL; // ale970302
115 // fprintf(stderr, "new bib "); fflush(stderr);
116 // if (par->bibkey) {
117 // bibkey = new InsetBibKey(par->bibkey);
123 /// Used by the spellchecker
124 bool LyXParagraph::IsLetter(int pos){
125 unsigned char c = GetChar(pos);
128 // '\0' is not a letter, allthough every string contains "" (below)
131 // We want to pass the ' and escape chars to ispell
132 LString extra = lyxrc->isp_esc_chars + '\'';
136 return extra.contains(ch);
140 void LyXParagraph::writeFile(FILE *file, BufferParams ¶ms,
141 char footflag, char dth)
143 LyXFont font1, font2;
149 if (footnoteflag != LyXParagraph::NO_FOOTNOTE
151 || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
153 /* The beginning or the end of a footnote environment? */
154 if (footflag != footnoteflag) {
155 footflag = footnoteflag;
157 fprintf(file, "\n\\begin_float %s ",
158 string_footnotekinds[footnotekind]);
161 fprintf(file, "\n\\end_float ");
165 /* The beginning or end of a deeper (i.e. nested) area? */
168 while (depth > dth) {
169 fprintf(file, "\n\\begin_deeper ");
174 while (depth < dth) {
175 fprintf(file, "\n\\end_deeper ");
181 /* First write the layout */
182 fprintf(file, "\n\\layout %s\n",
183 lyxstyle.NameOfLayout(params.textclass,layout).c_str());
185 /* maybe some vertical spaces */
186 if (added_space_top.kind() != VSpace::NONE)
187 fprintf(file, "\\added_space_top %s ",
188 added_space_top.asLyXCommand().c_str());
189 if (added_space_bottom.kind() != VSpace::NONE)
190 fprintf(file, "\\added_space_bottom %s ",
191 added_space_bottom.asLyXCommand().c_str());
193 /* The labelwidth string used in lists */
194 if (!labelwidthstring.empty())
195 fprintf(file, "\\labelwidthstring %s\n",
196 labelwidthstring.c_str());
198 /* Lines above or below? */
200 fprintf(file, "\\line_top ");
202 fprintf(file, "\\line_bottom ");
204 /* Pagebreaks above or below? */
206 fprintf(file, "\\pagebreak_top ");
207 if (pagebreak_bottom)
208 fprintf(file, "\\pagebreak_bottom ");
210 /* Start of appendix? */
211 if (start_of_appendix)
212 fprintf(file, "\\start_of_appendix ");
216 fprintf(file, "\\noindent ");
219 if (align != LYX_ALIGN_LAYOUT) {
221 case LYX_ALIGN_LEFT: h = 1; break;
222 case LYX_ALIGN_RIGHT: h = 2; break;
223 case LYX_ALIGN_CENTER: h = 3; break;
224 default: h = 0; break;
226 fprintf(file, "\\align %s ", string_align[h]);
228 if (pextra_type != PEXTRA_NONE) {
229 fprintf(file, "\\pextra_type %d", pextra_type);
230 if (pextra_type == PEXTRA_MINIPAGE) {
231 fprintf(file, " \\pextra_alignment %d",
234 fprintf(file, " \\pextra_hfill %d",
236 if (pextra_start_minipage)
237 fprintf(file, " \\pextra_start_minipage %d",
238 pextra_start_minipage);
240 if (!pextra_width.empty()) {
241 fprintf(file, " \\pextra_width %s",
242 VSpace(pextra_width).asLyXCommand().c_str());
243 } else if (!pextra_widthp.empty()) {
244 fprintf(file, " \\pextra_widthp %s",pextra_widthp.c_str());
250 /* Dummy layout. This means that a footnote ended */
251 fprintf(file, "\n\\end_float ");
252 footflag = LyXParagraph::NO_FOOTNOTE;
255 /* It might be a table */
257 fprintf(file, "\\LyXTable\n");
265 font1 = LyXFont(LyXFont::ALL_INHERIT);
268 for (int i = 0; i < last; i++) {
274 // Write font changes
275 font2 = GetFontSettings(i);
276 if (font2 != font1) {
277 font2.lyxWriteChanges(font1, file);
287 if (inset->DirectWrite()) {
288 // international char, let it write
289 // code directly so it's shorter in
293 fprintf(file, "\n\\begin_inset ");
295 fprintf(file, "\n\\end_inset \n");
300 case LYX_META_NEWLINE:
301 fprintf(file, "\n\\newline \n");
305 fprintf(file, "\n\\hfill \n");
308 case LYX_META_PROTECTED_SEPARATOR:
309 fprintf(file, "\n\\protected_separator \n");
313 fprintf(file, "\n\\backslash \n");
317 if (i + 1 < last && GetChar(i + 1) == ' ') {
318 fprintf(file, ".\n");
324 if ((column > 70 && c==' ')
329 // this check is to amend a bug. LyX sometimes
330 // inserts '\0' this could cause problems.
332 fprintf(file, "%c", c);
334 lyxerr.print("ERROR (LyXParagraph::writeFile):"
335 " NULL char in structure.");
341 // now write the next paragraph
343 next->writeFile(file, params, footflag, dth);
347 void LyXParagraph::validate(LaTeXFeatures &features)
349 // this will be useful later
350 LyXLayout *layout = lyxstyle.Style(GetCurrentTextClass(),
354 if (line_top || line_bottom)
355 features.lyxline = true;
358 features.layout[GetLayout()] = true;
361 FontTable *tmpfonttable = fonttable;
362 while (tmpfonttable) {
363 if (tmpfonttable->font.noun() == LyXFont::ON) {
364 lyxerr.debug(LString("font.noun: ")
365 + int(tmpfonttable->font.noun()),
367 features.noun = true;
368 lyxerr.debug("Noun enabled. Font: "
369 +tmpfonttable->font.stateText(),
372 switch (tmpfonttable->font.color()) {
374 case LyXFont::INHERIT_COLOR:
375 case LyXFont::IGNORE_COLOR:
378 features.color = true;
379 lyxerr.debug("Color enabled. Font: "
380 +tmpfonttable->font.stateText(),
383 tmpfonttable = tmpfonttable->next;
387 InsetTable *tmpinsettable = insettable;
388 while (tmpinsettable) {
389 if (tmpinsettable->inset) {
390 tmpinsettable->inset->Validate(features);
392 tmpinsettable = tmpinsettable->next;
394 if (table && table->IsLongTable())
395 features.longtable = true;
396 if (pextra_type == PEXTRA_INDENT)
397 features.LyXParagraphIndent = true;
398 if (pextra_type == PEXTRA_FLOATFLT)
399 features.floatflt = true;
400 if (layout->needprotect
401 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
402 features.NeedLyXFootnoteCode = true;
403 if ((current_view->currentBuffer()->params.paragraph_separation == LYX_PARSEP_INDENT) &&
404 (pextra_type == PEXTRA_MINIPAGE))
405 features.NeedLyXMinipageIndent = true;
406 if (table && table->NeedRotating())
407 features.rotating = true;
408 if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
409 features.algorithm = true;
413 /* first few functions needed for cut and paste and paragraph breaking */
414 void LyXParagraph::CopyIntoMinibuffer(int pos)
416 minibuffer_char = GetChar(pos);
417 minibuffer_font = GetFontSettings(pos);
418 minibuffer_inset = 0;
419 if (minibuffer_char == LYX_META_INSET) {
421 minibuffer_inset = GetInset(pos)->Clone();
423 minibuffer_inset = NULL;
424 minibuffer_char = ' ';
425 // This reflects what GetInset() does (ARRae)
431 void LyXParagraph::CutIntoMinibuffer(int pos)
433 minibuffer_char = GetChar(pos);
434 minibuffer_font = GetFontSettings(pos);
435 minibuffer_inset = 0;
436 if (minibuffer_char == LYX_META_INSET) {
438 minibuffer_inset = GetInset(pos);
439 /* This is a little hack since I want exactly the inset,
440 not just a clone. Otherwise the inset would be deleted
441 when calling Erase(pos) */
444 InsetTable *tmpi = insettable;
445 while (tmpi && tmpi->pos != pos) {
448 if (tmpi) { /* This should always be true */
452 minibuffer_inset = NULL;
453 minibuffer_char = ' ';
454 // This reflects what GetInset() does (ARRae)
459 /* Erase(pos); now the caller is responsible for that*/
463 void LyXParagraph::InsertFromMinibuffer(int pos)
465 InsertChar(pos, minibuffer_char);
466 SetFont(pos, minibuffer_font);
467 if (minibuffer_char == LYX_META_INSET)
468 InsertInset(pos, minibuffer_inset);
471 /* end of minibuffer */
475 void LyXParagraph::Clear()
480 pagebreak_top = false;
481 pagebreak_bottom = false;
483 added_space_top = VSpace(VSpace::NONE);
484 added_space_bottom = VSpace(VSpace::NONE);
486 align = LYX_ALIGN_LAYOUT;
490 pextra_type = PEXTRA_NONE;
491 pextra_width.clean();
492 pextra_widthp.clean();
493 pextra_alignment = MINIPAGE_ALIGN_TOP;
494 pextra_hfill = false;
495 pextra_start_minipage = false;
498 labelwidthstring.clean();
502 start_of_appendix = false;
506 /* the destructor removes the new paragraph from the list */
507 LyXParagraph::~LyXParagraph()
510 previous->next = next;
512 next->previous = previous;
517 InsetTable *tmpinset;
519 tmpinset = insettable;
520 insettable = insettable->next;
522 delete tmpinset->inset;
524 if (insettable && insettable->next == insettable) {
525 // somehow this recursion appears occasionally
526 // but I can't find where. This bandaid
527 // helps but isn't the best fix. (ARRae)
528 if (insettable->inset) {
529 delete insettable->inset;
539 fonttable = fonttable->next;
543 /* table stuff -- begin*/
546 /* table stuff -- end*/
554 void LyXParagraph::Erase(int pos)
558 /* > because last is the next unused position, and you can
559 * use it if you want */
561 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
562 NextAfterFootnote()->Erase(pos - last - 1);
564 lyxerr.debug("ERROR (LyXParagraph::Erase): position does not exist.");
567 if (pos < last) { // last is free for insertation, but should be empty
569 /* if it is an inset, delete the inset entry */
570 if (text[pos] == LYX_META_INSET) {
572 InsetTable *tmpi = insettable;
573 InsetTable *tmpi2 = tmpi;
574 while (tmpi && tmpi->pos != pos) {
578 if (tmpi) { // this should always be true
579 if (tmpi->inset) // delete the inset if it exists
581 if (tmpi == insettable)
582 insettable = tmpi->next;
584 tmpi2->next = tmpi->next;
589 // Shift rest of text
590 for (i = pos; i < last - 1; i++) {
595 /* erase entries in the tables */
597 FontTable *tmp = fonttable;
598 FontTable *prev = NULL;
599 while (tmp && !found) {
600 if (pos >= tmp->pos && pos <= tmp->pos_end)
608 if (found && tmp->pos == tmp->pos_end) {
609 /* if it is a multi-character font entry, we just make
610 * it smaller (see update below), otherwise we should
613 prev->next = tmp->next;
615 fonttable = tmp->next;
620 /* update all other entries */
626 if (tmp->pos_end >= pos)
631 /* update the inset table */
632 InsetTable *tmpi = insettable;
640 lyxerr.print("ERROR (LyXParagraph::Erase): can't erase non-existant char.");
645 /* pos is needed to specify the paragraph correctly. Remember the
646 * closed footnotes */
647 void LyXParagraph::Enlarge(int pos, int number)
651 /* > because last is the next unused position, and you can
652 * use it if you want */
654 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
655 NextAfterFootnote()->Enlarge(pos - last - 1, number);
657 lyxerr.print("ERROR (LyXParagraph::Enlarge): position does not exist.");
661 if (size - last < number) {
662 size += number - size + last + STEP_SIZE_PAR;
663 char *tmp = new char[size];
664 for (i = 0; i < last; i++)
672 /* make the allocated memory fit to the needed size */
673 /* used to make a paragraph smaller */
674 void LyXParagraph::FitSize()
678 if (size - last > STEP_SIZE_PAR) {
679 size = last + STEP_SIZE_PAR;
680 char *tmp = new char[size];
681 for (i = 0; i < last; i++)
689 void LyXParagraph::InsertChar(int pos, char c)
693 /* > because last is the next unused position, and you can
694 * use it if you want */
696 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
697 NextAfterFootnote()->InsertChar(pos - last - 1, c);
699 lyxerr.debug("ERROR (LyXParagraph::InsertChar): "
700 "position does not exist.");
704 // Are we full? If so, enlarge.
706 size += STEP_SIZE_PAR;
707 char *tmp = new char[size];
708 for (i = 0; i < last; i++)
714 // Shift rest of character
715 for (i = last; i>pos; i--) {
722 /* update the font table */
723 FontTable *tmp = fonttable;
727 if (tmp->pos_end >= pos)
732 /* update the inset table */
733 InsetTable *tmpi = insettable;
735 if (tmpi->pos >= pos)
742 void LyXParagraph::InsertInset(int pos, Inset *inset)
744 /* > because last is the next unused position, and you can
745 * use it if you want */
747 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
748 NextAfterFootnote()->InsertInset(pos - last - 1, inset);
750 lyxerr.print("ERROR (LyXParagraph::InsertInset): "
751 "position does not exist: " + pos);
755 if (text[pos]!=LYX_META_INSET) {
756 lyxerr.print("ERROR (LyXParagraph::InsertInset): "
757 "there is no LYX_META_INSET");
762 /* add a new entry in the inset table */
763 InsetTable *tmpi = new InsetTable;
766 tmpi->next = insettable;
772 Inset* LyXParagraph::GetInset(int pos)
775 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
776 return NextAfterFootnote()->GetInset(pos - last - 1);
778 lyxerr.print(LString("ERROR (LyXParagraph::GetInset): position does not exist: ") + pos);
784 InsetTable *tmpi = insettable;
786 while (tmpi && tmpi->pos != pos)
792 lyxerr.print(LString("ERROR (LyXParagraph::GetInset): "
793 "Inset does not exist: ") + pos);
794 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
795 // Did this commenting out introduce a bug? So far I have not
796 // seen any, please enlighten me. (Lgb)
797 // My guess is that since the inset does not exist, we might
798 // as well replace it with a space to prevent crashes. (Asger)
804 // Gets uninstantiated font setting at position.
805 // Optimized after profiling. (Asger)
806 LyXFont LyXParagraph::GetFontSettings(int pos)
809 FontTable *tmp = fonttable;
811 if (pos >= tmp->pos && pos <= tmp->pos_end)
817 /* > because last is the next unused position, and you can
818 * use it if you want */
819 else if (pos > last) {
820 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
821 return NextAfterFootnote()->GetFontSettings(pos - last - 1);
823 // Why is it an error to ask for the font of a
824 // position that does not exist? Would it be
825 // enough for this to be anable on debug?
826 // We want strict error checking, but it's ok to only
827 // have it when debugging. (Asger)
829 LString("ERROR (LyXParagraph::GetFontSettings): "
830 "position does not exist. ") + pos);
833 return GetFontSettings(pos - 1);
835 return LyXFont(LyXFont::ALL_INHERIT);
839 // Gets the fully instantiated font at a given position in a paragraph
840 // This is basically the same function as LyXText::GetFont() in text2.C.
841 // The difference is that this one is used for generating the LaTeX file,
842 // and thus cosmetic "improvements" are disallowed: This has to deliver
843 // the true picture of the buffer. (Asger)
844 // If position is -1, we get the layout font of the paragraph.
845 // If position is -2, we get the font of the manual label of the paragraph.
846 LyXFont LyXParagraph::getFont(int pos)
849 LyXLayout *layout = lyxstyle.Style(GetCurrentTextClass(),
853 if (layout->labeltype == LABEL_MANUAL)
854 main_body = BeginningOfMainBody();
859 layoutfont = layout->labelfont;
861 layoutfont = layout->font;
862 tmpfont = GetFontSettings(pos);
863 tmpfont.realize(layoutfont);
865 // process layoutfont for pos == -1 and labelfont for pos < -1
867 tmpfont = layout->font;
869 tmpfont = layout->labelfont;
872 // check for environment font information
873 char par_depth = GetDepth();
874 LyXParagraph * par = this;
875 while (par && par_depth && !tmpfont.resolved()) {
876 par = par->DepthHook(par_depth - 1);
878 tmpfont.realize(lyxstyle.
879 Style(GetCurrentTextClass(),
880 par->GetLayout())->font);
881 par_depth = par->GetDepth();
885 tmpfont.realize(lyxstyle.TextClass(GetCurrentTextClass())->defaultfont);
890 /// Returns the height of the highest font in range
891 LyXFont::FONT_SIZE LyXParagraph::HighestFontInRange(int startpos, int endpos) const
893 LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
895 FontTable *tmp = fonttable;
897 if (startpos <= tmp->pos_end && endpos >= tmp->pos) {
898 LyXFont::FONT_SIZE size = tmp->font.size();
899 if (size > maxsize && size<=LyXFont::SIZE_HUGER)
908 char LyXParagraph::GetChar(int pos)
911 /* a workaround to 'fix' some bugs in text-class */
913 // This function is important. It should not work around bugs.
914 // Let's find the bugs instead and fix them. (Asger)
915 lyxerr.print(LString("FATAL ERROR (LyXParagraph::GetChar):"
916 " bad position ") + pos);
925 /* > because last is the next unused position, and you can
926 * use it if you want */
927 else if (pos > last) {
928 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
929 return NextAfterFootnote()->GetChar(pos - last - 1);
931 lyxerr.print("ERROR (LyXParagraph::GetChar): "
932 "position does not exist.");
934 } else { // pos==last
935 /* we should have a footnote environment */
936 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
937 // Notice that LyX does request the last char from time to time. (Asger)
938 // lyxerr.print("ERROR (LyXParagraph::GetChar): "
939 // "expected footnote.");
942 switch (next->footnotekind) {
943 case LyXParagraph::FOOTNOTE:
944 return LYX_META_FOOTNOTE;
945 case LyXParagraph::MARGIN:
946 return LYX_META_MARGIN;
947 case LyXParagraph::FIG:
948 case LyXParagraph::WIDE_FIG:
950 case LyXParagraph::TAB:
951 case LyXParagraph::WIDE_TAB:
953 case LyXParagraph::ALGORITHM:
954 return LYX_META_ALGORITHM;
956 // if (next->footnotekind == LyXParagraph::FOOTNOTE)
957 // return LYX_META_FOOTNOTE;
958 // if (next->footnotekind == LyXParagraph::MARGIN)
959 // return LYX_META_MARGIN;
960 // if (next->footnotekind == LyXParagraph::FIG)
961 // return LYX_META_FIG;
962 // if (next->footnotekind == LyXParagraph::TAB)
963 // return LYX_META_TAB;
964 // if (next->footnotekind == LyXParagraph::ALGORITHM)
965 // return LYX_META_ALGORITHM;
966 // lyxerr.print("ERROR (LyXParagraph::GetChar): "
967 // "unknown footnote kind.");
968 // return 'F'; /* this should not happen! */
969 // This _can_ not happen, due to the type of next->footnotekind
970 // being LyXParagraph::footnot_kind
971 return '\0'; // to shut up gcc
976 LString LyXParagraph::GetWord(int & lastpos)
979 //Added 98/9/21 by REH
980 // return an LString of the current word, and the end of the word
983 // the current word is defined as starting at the first character from
984 // the immediate left of lastpospos which meets the definition of IsLetter(),
985 // continuing to the last character to the right of this meeting
989 // i just left this in from GetChar()
992 /* a workaround to 'fix' some bugs in text-class */
994 // This function is important. It should not work around bugs.
995 // Let's find the bugs instead and fix them. (Asger)
996 lyxerr.print(LString("FATAL ERROR (LyXParagraph::GetWord):"
997 " bad position ") + lastpos);
1007 //i think the devcode aborts before this, but why not be
1009 if (lastpos < 0) lastpos=0;
1012 // move back until we have a letter
1014 //there's no real reason to have firstpos & lastpos as
1015 //separate variables as this is written, but maybe someon
1016 // will want to return firstpos in the future.
1018 //since someone might have typed a punctuation first
1019 int firstpos = lastpos;
1021 while ((firstpos >=0) && !IsLetter(firstpos))
1024 // now find the beginning by looking for a nonletter
1026 while ((firstpos>=0) && IsLetter(firstpos))
1029 // the above is now pointing to the preceeding non-letter
1033 // so copy characters into theword until we get a nonletter
1034 // note that this can easily exceed lastpos, wich means
1035 // that if used in the middle of a word, the whole word
1038 while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1045 int LyXParagraph::Last()
1047 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1048 return last + NextAfterFootnote()->Last() + 1; /* the 1 is the symbol
1049 * for the footnote */
1055 LyXParagraph *LyXParagraph::ParFromPos(int pos)
1057 /* > because last is the next unused position, and you can
1058 * use it if you want */
1060 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1061 return NextAfterFootnote()->ParFromPos(pos - last - 1);
1063 lyxerr.print("ERROR (LyXParagraph::ParFromPos): "
1064 "position does not exist.");
1072 int LyXParagraph::PositionInParFromPos(int pos)
1074 /* > because last is the next unused position, and you can
1075 * use it if you want */
1077 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1078 return NextAfterFootnote()->PositionInParFromPos(pos - last - 1);
1081 "ERROR (LyXParagraph::PositionInParFromPos): "
1082 "position does not exist.");
1090 void LyXParagraph::SetFont(int pos, LyXFont const & font)
1092 /* > because last is the next unused position, and you can
1093 * use it if you want */
1095 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1096 NextAfterFootnote()->SetFont(pos - last - 1, font);
1098 lyxerr.print("ERROR (LyXParagraph::SetFont): "
1099 "position does not exist.");
1104 LyXFont patternfont(LyXFont::ALL_INHERIT);
1106 // First, reduce font against layout/label font
1107 // Update: The SetCharFont() routine in text2.C already reduces font, so
1108 // we don't need to do that here. (Asger)
1109 // No need to simplify this because it will disappear in a new kernel. (Asger)
1111 // Next search font table
1115 FontTable *tmp = fonttable;
1116 while (tmp && !found) {
1117 if (pos >= tmp->pos && pos <= tmp->pos_end)
1124 /* if we did not find a font entry, but if the font at hand
1125 * is the same as default, we just forget it */
1126 if (font == patternfont)
1129 /* ok, we did not find a font entry. But maybe there is exactly
1130 * the needed font entry one position left */
1133 while (tmp2 && !found) {
1134 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1140 /* ok there is one. maybe it is exactly the needed font */
1141 if (tmp2->font == font) {
1142 /* put the position under the font */
1147 /* Add a new entry in the
1148 * fonttable for the position */
1149 tmp = new FontTable;
1152 tmp->font = patternfont;
1153 tmp->next = fonttable;
1157 /* we found a font entry. maybe we have to split it and create
1160 if (tmp->pos != tmp->pos_end) { /* more than one character */
1162 if (pos == tmp->pos) {
1163 /* maybe we could enlarge the left fonttable */
1167 while (tmp2 && !found) {
1168 if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1174 /* Is there is one, and is it exactly the needed font? */
1175 if (found && tmp2->font == font) {
1176 /* put the position under the font */
1182 /* Add a new entry in the
1183 * fonttable for the position */
1184 tmp2 = new FontTable;
1185 tmp2->pos = pos + 1;
1186 tmp2->pos_end = tmp->pos_end;
1187 tmp2->font = tmp->font;
1189 tmp2->next = fonttable;
1192 else if (pos == tmp->pos_end) {
1193 /* Add a new entry in the
1194 * fonttable for the position */
1195 tmp2 = new FontTable;
1196 tmp2->pos = tmp->pos;
1197 tmp2->pos_end = tmp->pos_end - 1;
1198 tmp2->font = tmp->font;
1199 tmp->pos = tmp->pos_end;
1200 tmp2->next = fonttable;
1204 /* Add a new entry in the
1205 * fonttable for the position */
1206 tmp2 = new FontTable;
1207 tmp2->pos = tmp->pos;
1208 tmp2->pos_end = pos - 1;
1209 tmp2->font = tmp->font;
1210 tmp2->next = fonttable;
1213 tmp2 = new FontTable;
1214 tmp2->pos = pos + 1;
1215 tmp2->pos_end = tmp->pos_end;
1216 tmp2->font = tmp->font;
1217 tmp2->next = fonttable;
1230 /* this function is able to hide closed footnotes */
1231 LyXParagraph *LyXParagraph::Next()
1234 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1236 while (tmp && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1238 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1239 return tmp->Next(); /* there can be more than one footnote
1240 * in a logical paragraph */
1242 return next; /* this should never happen! */
1249 LyXParagraph *LyXParagraph::NextAfterFootnote()
1252 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1254 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1256 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1257 return tmp; /* there can be more than one footnote
1258 * in a logical paragraph */
1260 return next; /* this should never happen! */
1267 LyXParagraph *LyXParagraph::PreviousBeforeFootnote()
1270 if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1272 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1273 tmp = tmp->previous;
1274 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1275 return tmp; /* there can be more than one footnote
1276 * in a logical paragraph */
1278 return previous; /* this should never happen! */
1285 LyXParagraph *LyXParagraph::LastPhysicalPar()
1288 if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1292 while (tmp->next && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1293 tmp = tmp->NextAfterFootnote();
1300 LyXParagraph *LyXParagraph::FirstPhysicalPar()
1304 LyXParagraph *tmppar = this;
1306 while (tmppar && (tmppar->IsDummy()
1307 || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1308 tmppar = tmppar->previous;
1311 return this; /* this should never happen! */
1317 /* this function is able to hide closed footnotes */
1318 LyXParagraph *LyXParagraph::Previous()
1320 LyXParagraph *tmp = previous;
1324 if (tmp->previous && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1325 tmp = tmp->previous;
1326 while (tmp && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1327 tmp = tmp->previous;
1328 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
1329 return tmp->next->Previous();
1339 void LyXParagraph::BreakParagraph(int pos, int flag)
1341 int i, pos_end, pos_first;
1343 /* create a new paragraph */
1344 LyXParagraph *par = ParFromPos(pos);
1345 LyXParagraph *firstpar = FirstPhysicalPar();
1347 LyXParagraph *tmp = new LyXParagraph(par);
1349 tmp->footnoteflag = footnoteflag;
1350 tmp->footnotekind = footnotekind;
1352 /* this is an idea for a more userfriendly layout handling, I will
1353 * see what the users say */
1355 /* layout stays the same with latex-environments */
1357 tmp->SetOnlyLayout(firstpar->layout);
1358 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1361 if (Last() > pos || !Last() || flag == 2) {
1362 tmp->SetOnlyLayout(firstpar->layout);
1363 tmp->align = firstpar->align;
1364 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1366 tmp->line_bottom = firstpar->line_bottom;
1367 firstpar->line_bottom = false;
1368 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1369 firstpar->pagebreak_bottom = false;
1370 tmp->added_space_bottom = firstpar->added_space_bottom;
1371 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1373 tmp->depth = firstpar->depth;
1374 tmp->noindent = firstpar->noindent;
1376 /* copy everything behind the break-position to the new paragraph */
1378 while (ParFromPos(pos_first) != par)
1381 pos_end = pos_first + par->last - 1;
1383 /* make sure there is enough memory for the now larger
1384 paragraph. This is not neccessary, because
1385 InsertFromMinibuffer will enlarge the memory (it uses
1386 InsertChar of course). But doing it by hand
1387 is MUCH faster! (only one time, not thousend times!!) */
1389 tmp->Enlarge(0, pos_end - pos);
1391 for (i = pos; i <= pos_end; i++) {
1392 par->CutIntoMinibuffer(i - pos_first);
1393 tmp->InsertFromMinibuffer(i - pos);
1396 for (i = pos_end; i >= pos; i--)
1397 par->Erase(i - pos_first);
1398 /* free memory of the now shorter paragraph*/
1402 /* just an idea of me */
1404 tmp->line_top = firstpar->line_top;
1405 tmp->pagebreak_top = firstpar->pagebreak_top;
1406 tmp->added_space_top = firstpar->added_space_top;
1407 tmp->bibkey = firstpar->bibkey;
1409 /* layout stays the same with latex-environments */
1411 firstpar->SetOnlyLayout(tmp->layout);
1412 firstpar->SetLabelWidthString(tmp->labelwidthstring);
1413 firstpar->depth = tmp->depth;
1419 void LyXParagraph::MakeSameLayout(LyXParagraph *par)
1421 par = par->FirstPhysicalPar();
1422 footnoteflag = par->footnoteflag;
1423 footnotekind = par->footnotekind;
1425 layout = par->layout;
1426 align = par-> align;
1427 SetLabelWidthString(par->labelwidthstring);
1429 line_bottom = par->line_bottom;
1430 pagebreak_bottom = par->pagebreak_bottom;
1431 added_space_bottom = par->added_space_bottom;
1433 line_top = par->line_top;
1434 pagebreak_top = par->pagebreak_top;
1435 added_space_top = par->added_space_top;
1437 pextra_type = par->pextra_type;
1438 pextra_width = par->pextra_width;
1439 pextra_widthp = par->pextra_widthp;
1440 pextra_alignment = par->pextra_alignment;
1441 pextra_hfill = par->pextra_hfill;
1442 pextra_start_minipage = par->pextra_start_minipage;
1444 noindent = par->noindent;
1449 LyXParagraph *LyXParagraph::FirstSelfrowPar()
1451 LyXParagraph *tmppar;
1455 (tmppar->IsDummy() && tmppar->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1456 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1457 tmppar = tmppar->previous;
1460 return this; /* this should never happen! */
1466 LyXParagraph *LyXParagraph::Clone()
1470 /* create a new paragraph */
1471 LyXParagraph *result = new LyXParagraph();
1473 result->MakeSameLayout(this);
1475 /* this is because of the dummy layout of the paragraphs that
1477 result->layout = layout;
1479 /* table stuff -- begin*/
1481 result->table = table->Clone();
1483 result->table = NULL;
1484 /* table stuff -- end*/
1487 result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1490 /* copy everything behind the break-position to the new paragraph */
1492 /* make shure there is enough memory for the now larger paragraph.
1493 * This is not neccessary, because InsertFromMinibuffer will enlarge
1494 * the memory (it uses InsertChar of course). But doing it by hand
1495 * is MUCH faster! (only one time, not thousend times!!) */
1497 result->Enlarge(0, last+2);
1499 for (i = 0; i < last; i++) {
1500 CopyIntoMinibuffer(i);
1501 result->InsertFromMinibuffer(i);
1507 bool LyXParagraph::HasSameLayout(LyXParagraph* par)
1509 par = par->FirstPhysicalPar();
1512 par->footnoteflag == footnoteflag &&
1513 par->footnotekind == footnotekind &&
1515 par->layout == layout &&
1517 par->align == align &&
1519 par->line_bottom == line_bottom &&
1520 par->pagebreak_bottom == pagebreak_bottom &&
1521 par->added_space_bottom == added_space_bottom &&
1523 par->line_top == line_top &&
1524 par->pagebreak_top == pagebreak_top &&
1525 par->added_space_top == added_space_top &&
1527 par->pextra_type == pextra_type &&
1528 par->pextra_width == pextra_width &&
1529 par->pextra_widthp == pextra_widthp &&
1530 par->pextra_alignment == pextra_alignment &&
1531 par->pextra_hfill == pextra_hfill &&
1532 par->pextra_start_minipage == pextra_start_minipage &&
1534 par->table == table && // what means: NO TABLE AT ALL
1536 par->noindent == noindent &&
1537 par->depth == depth);
1541 void LyXParagraph::BreakParagraphConservative(int pos)
1543 int i, pos_end, pos_first;
1545 /* create a new paragraph */
1546 LyXParagraph *par = ParFromPos(pos);
1548 LyXParagraph *tmp = new LyXParagraph(par);
1550 tmp->MakeSameLayout(par);
1553 /* copy everything behind the break-position to the new
1556 while (ParFromPos(pos_first) != par)
1559 pos_end = pos_first + par->last - 1;
1561 /* make shure there is enough memory for the now larger
1562 paragraph. This is not neccessary, because
1563 InsertFromMinibuffer will enlarge the memory (it uses
1564 InsertChar of course). But doing it by hand
1565 is MUCH faster! (only one time, not thousend times!!) */
1567 tmp->Enlarge(0, pos_end - pos);
1569 for (i = pos; i <= pos_end; i++) {
1571 par->CutIntoMinibuffer(i - pos_first);
1572 tmp->InsertFromMinibuffer(i - pos);
1574 for (i = pos_end; i >= pos; i--)
1575 par->Erase(i - pos_first);
1577 /* free memory of the now shorter paragraph*/
1583 /* be carefull, this does not make any check at all */
1584 void LyXParagraph::PasteParagraph()
1586 int i, pos_end, pos_insert;
1587 LyXParagraph *the_next;
1589 /* copy the next paragraph to this one */
1592 LyXParagraph *firstpar = FirstPhysicalPar();
1594 /* first the DTP-stuff */
1595 firstpar->line_bottom = the_next->line_bottom;
1596 firstpar->added_space_bottom = the_next->added_space_bottom;
1597 firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1599 pos_end = the_next->last - 1;
1600 pos_insert = Last();
1602 /* enlarge the paragraph. This is faster than enlarge it
1603 * every 10th insertion. */
1605 Enlarge(pos_insert, pos_end);
1607 /* ok, now copy the paragraph */
1608 for (i = 0; i <= pos_end; i++) {
1609 the_next->CutIntoMinibuffer(i);
1610 InsertFromMinibuffer(pos_insert + i);
1613 /* delete the next paragraph */
1618 void LyXParagraph::OpenFootnote(int pos)
1620 LyXParagraph *par = ParFromPos(pos);
1622 while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1623 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1629 void LyXParagraph::CloseFootnote(int pos)
1631 LyXParagraph *par = ParFromPos(pos);
1633 while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1634 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1640 int LyXParagraph::GetLayout()
1642 return FirstPhysicalPar()->layout;
1646 char LyXParagraph::GetDepth()
1648 return FirstPhysicalPar()->depth;
1652 char LyXParagraph::GetAlign()
1654 return FirstPhysicalPar()->align;
1658 LString LyXParagraph::GetLabelString()
1660 return FirstPhysicalPar()->labelstring;
1664 int LyXParagraph::GetFirstCounter(int i)
1666 return FirstPhysicalPar()->counter[i];
1670 /* the next two functions are for the manual labels */
1671 LString LyXParagraph::GetLabelWidthString()
1673 if (!FirstPhysicalPar()->labelwidthstring.empty())
1674 return FirstPhysicalPar()->labelwidthstring;
1676 return _("Senseless with this layout!");
1680 void LyXParagraph::SetLabelWidthString(LString const & s)
1682 LyXParagraph *par = FirstPhysicalPar();
1684 par->labelwidthstring = s;
1688 void LyXParagraph::SetOnlyLayout(char new_layout)
1691 *par = FirstPhysicalPar(),
1695 par->layout = new_layout;
1696 /* table stuff -- begin*/
1699 /* table stuff -- end*/
1700 if (par->pextra_type == PEXTRA_NONE) {
1701 if (par->Previous()) {
1702 ppar = par->Previous()->FirstPhysicalPar();
1705 && (ppar->depth > par->depth))
1706 ppar = ppar->Previous()->FirstPhysicalPar();
1709 npar = par->Next()->NextAfterFootnote();
1712 && (npar->depth > par->depth))
1713 npar = npar->Next()->NextAfterFootnote();
1715 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1717 p1 = ppar->pextra_width,
1718 p2 = ppar->pextra_widthp;
1719 ppar->SetPExtraType(ppar->pextra_type,
1720 p1.c_str(),p2.c_str());
1722 if ((par->pextra_type == PEXTRA_NONE) &&
1723 npar && (npar->pextra_type != PEXTRA_NONE)) {
1725 p1 = npar->pextra_width,
1726 p2 = npar->pextra_widthp;
1727 npar->SetPExtraType(npar->pextra_type,
1728 p1.c_str(),p2.c_str());
1734 void LyXParagraph::SetLayout(char new_layout)
1737 *par = FirstPhysicalPar(),
1741 par->layout = new_layout;
1742 par->labelwidthstring.clean();
1743 par->align = LYX_ALIGN_LAYOUT;
1745 par->added_space_top = VSpace(VSpace::NONE);
1746 par->added_space_bottom = VSpace(VSpace::NONE);
1747 /* table stuff -- begin*/
1750 /* table stuff -- end*/
1751 if (par->pextra_type == PEXTRA_NONE) {
1752 if (par->Previous()) {
1753 ppar = par->Previous()->FirstPhysicalPar();
1756 && (ppar->depth > par->depth))
1757 ppar = ppar->Previous()->FirstPhysicalPar();
1760 npar = par->Next()->NextAfterFootnote();
1763 && (npar->depth > par->depth))
1764 npar = npar->Next()->NextAfterFootnote();
1766 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1768 p1 = ppar->pextra_width,
1769 p2 = ppar->pextra_widthp;
1770 ppar->SetPExtraType(ppar->pextra_type,
1771 p1.c_str(),p2.c_str());
1773 if ((par->pextra_type == PEXTRA_NONE) &&
1774 npar && (npar->pextra_type != PEXTRA_NONE)) {
1776 p1 = npar->pextra_width,
1777 p2 = npar->pextra_widthp;
1778 npar->SetPExtraType(npar->pextra_type,
1779 p1.c_str(),p2.c_str());
1785 /* if the layout of a paragraph contains a manual label, the beginning of the
1786 * main body is the beginning of the second word. This is what the par-
1787 * function returns. If the layout does not contain a label, the main
1788 * body always starts with position 0. This differentiation is necessary,
1789 * because there cannot be a newline or a blank <= the beginning of the
1790 * main body in TeX. */
1792 int LyXParagraph::BeginningOfMainBody()
1794 if (FirstPhysicalPar() != this)
1799 // while (i < last && !(i > 1 && GetChar(i-1)==' ')
1800 // && GetChar(i)!=LYX_META_NEWLINE)
1802 // Unroll the first two cycles of this loop
1803 // and remember the previous character to remove unnecessary GetChar() calls
1806 && GetChar(i) != LYX_META_NEWLINE) {
1808 char previous_char, temp;
1810 && (previous_char = GetChar(i)) != LYX_META_NEWLINE) {
1811 // Yes, this ^ is supposed to be "=" not "=="
1814 && previous_char != ' '
1815 && (temp = GetChar(i)) != LYX_META_NEWLINE) {
1817 previous_char = temp;
1822 if (i==0 && i == last &&
1823 !(footnoteflag==LyXParagraph::NO_FOOTNOTE
1824 && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1826 i++; /* the cursor should not jump
1827 * to the main body if there
1833 LyXParagraph* LyXParagraph::DepthHook(int deth)
1835 LyXParagraph *newpar = this;
1840 newpar = newpar->FirstPhysicalPar()->Previous();
1841 } while (newpar && newpar->GetDepth() > deth
1842 && newpar->footnoteflag == footnoteflag);
1845 if (Previous() || GetDepth())
1846 lyxerr.print("ERROR (LyXParagraph::DepthHook): "
1850 return newpar->FirstPhysicalPar();
1854 int LyXParagraph::AutoDeleteInsets()
1856 InsetTable *tmpi = insettable;
1857 InsetTable *tmpi2 = tmpi;
1863 if (tmpi2->inset->AutoDelete()) {
1869 "ERROR (LyXParagraph::AutoDeleteInsets): "
1870 "cannot auto-delete insets");
1876 Inset* LyXParagraph::ReturnNextInsetPointer(int &pos)
1878 InsetTable *tmpi = insettable;
1879 InsetTable *tmpi2 = NULL;
1881 if (tmpi->pos >= pos) {
1882 if (!tmpi2 || tmpi->pos < tmpi2->pos)
1889 return tmpi2->inset;
1896 /* returns -1 if inset not found */
1897 int LyXParagraph::GetPositionOfInset(Inset* inset)
1899 /* find the entry */
1900 InsetTable *tmpi = insettable;
1901 while (tmpi && tmpi->inset != inset) {
1904 if (tmpi && tmpi->inset)
1907 /* think about footnotes */
1908 if (footnoteflag == LyXParagraph::NO_FOOTNOTE
1909 && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1911 NextAfterFootnote()->GetPositionOfInset(inset);
1913 return last + 1 + further;
1920 void LyXParagraph::readSimpleWholeFile(FILE *myfile)
1924 FileInfo fileInfo(fileno(myfile));
1925 long file_size = fileInfo.getSize();
1926 /* it is horrible, I know, but faster.
1927 * I should not use InsertString for that :-( */
1929 /* I will write a better insertion in the future */
1930 Enlarge(0, file_size + 10);
1934 if (!feof(myfile)) {
1938 } while (!feof(myfile));
1944 LyXParagraph* LyXParagraph::TeXOnePar(LString &file, TexRow &texrow,
1945 LString &foot, TexRow &foot_texrow,
1948 lyxerr.debug(LString("TeXOnePar... ") + (long)this, Error::LATEX);
1949 LyXParagraph *par = next;
1950 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), layout);
1952 bool further_blank_line = false;
1954 lyxerr.print("ERROR (LyXParagraph::TeXOnePar) is dummy.");
1956 if (start_of_appendix) {
1957 file += "\\appendix\n";
1961 if (tex_code_break_column && style->isCommand()){
1966 if (pagebreak_top) {
1967 file += "\\newpage";
1968 further_blank_line = true;
1970 if (added_space_top.kind() != VSpace::NONE) {
1971 file += added_space_top.asLatexCommand();
1972 further_blank_line = true;
1976 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
1977 file += "\\vspace{-1\\parskip}";
1978 further_blank_line = true;
1981 if (further_blank_line){
1986 switch (style->latextype) {
1989 file += style->latexname;
1990 file += style->latexparam;
1992 case LATEX_ITEM_ENVIRONMENT:
1994 bibkey->Latex(file, false);
1998 case LATEX_LIST_ENVIRONMENT:
2005 bool need_par = SimpleTeXOnePar(file, texrow);
2007 // Spit out footnotes
2008 while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2009 && par->footnoteflag != footnoteflag) {
2010 par = par->TeXFootnote(file, texrow,
2011 foot, foot_texrow, foot_count);
2012 par->SimpleTeXOnePar(file, texrow);
2016 // Make sure that \\par is done with the font of the last
2017 // character if this has another size as the default.
2018 // This is necessary because LaTeX (and LyX on the screen)
2019 // calculates the space between the baselines according
2020 // to this font. (Matthias)
2021 LyXFont font = getFont(Last()-1);
2023 if (style->resfont.size() != font.size()) {
2025 file += font.latexSize();
2029 } else if (lyxstyle.Style(GetCurrentTextClass(),
2030 GetLayout())->isCommand()){
2031 if (style->resfont.size() != font.size()) {
2033 file += font.latexSize();
2037 } else if (style->resfont.size() != font.size()){
2038 file += "{\\" + font.latexSize() + " \\par}";
2041 switch (style->latextype) {
2042 case LATEX_ITEM_ENVIRONMENT:
2043 case LATEX_LIST_ENVIRONMENT:
2044 if (par && (depth < par->depth)) {
2049 case LATEX_ENVIRONMENT:
2050 // if its the last paragraph of the current environment
2051 // skip it otherwise fall through
2053 && (par->layout != layout
2054 || par->depth != depth
2055 || par->pextra_type != pextra_type))
2058 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2059 && footnotekind != LyXParagraph::FOOTNOTE
2060 && footnotekind != LyXParagraph::MARGIN
2064 // don't insert this if we would be adding it
2065 // before or after a table in a float. This
2066 // little trick is needed in order to allow
2067 // use of tables in \subfigures or \subtables.
2073 further_blank_line = false;
2075 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2076 further_blank_line = true;
2079 if (added_space_bottom.kind() != VSpace::NONE) {
2080 file += added_space_bottom.asLatexCommand();
2081 further_blank_line = true;
2084 if (pagebreak_bottom) {
2085 file += "\\newpage";
2086 further_blank_line = true;
2089 if (further_blank_line){
2094 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2095 par->footnoteflag == LyXParagraph::NO_FOOTNOTE) // &&
2096 // (pextra_type != PEXTRA_MINIPAGE ||
2097 /* (par && !par->pextra_type == PEXTRA_MINIPAGE)) */ ) {
2102 lyxerr.debug(LString("TeXOnePar...done ") + (long)par, Error::LATEX);
2107 // This one spits out the text of the paragraph
2108 bool LyXParagraph::SimpleTeXOnePar(LString &file, TexRow &texrow)
2110 lyxerr.debug(LString("SimpleTeXOnePar... ") + (long)this,
2114 return SimpleTeXOneTablePar(file, texrow);
2120 bool return_value = false;
2121 //bool underbar = false;
2123 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2126 /* maybe we have to create a optional argument */
2127 if (style->labeltype != LABEL_MANUAL)
2130 main_body = BeginningOfMainBody();
2132 if (main_body > 0) {
2134 basefont = getFont(-2); // Get label font
2136 basefont = getFont(-1); // Get layout font
2144 if (style->isCommand()) {
2147 } else if (align != LYX_ALIGN_LAYOUT) {
2150 return_value = true;
2154 // Which font is currently active?
2155 LyXFont running_font = basefont;
2156 // Do we have an open font change?
2157 bool open_font = false;
2159 texrow.start(this, 0);
2161 for (int i = 0; i < last; i++) {
2163 // First char in paragraph or after label?
2164 if (i == main_body && !IsDummy()) {
2165 if (main_body > 0) {
2167 column += running_font.latexWriteEndChanges(file, basefont);
2170 basefont = getFont(-1); // Now use the layout font
2171 running_font = basefont;
2175 if (style->isCommand()) {
2178 } else if (align != LYX_ALIGN_LAYOUT) {
2181 return_value = true;
2185 file += "\\noindent ";
2189 case LYX_ALIGN_LEFT:
2190 file += "\\raggedright ";
2193 case LYX_ALIGN_RIGHT:
2194 file += "\\raggedleft ";
2197 case LYX_ALIGN_CENTER:
2198 file += "\\centering ";
2206 // Fully instantiated font
2207 LyXFont font = getFont(i);
2209 // Spaces at end of font change are simulated to be
2210 // outside font change, i.e. we write "\textXX{text} "
2211 // rather than "\textXX{text }". (Asger)
2212 if (open_font && c == ' ' && i <= last-2
2213 && !getFont(i+1).equalExceptLatex(running_font)
2214 && !getFont(i+1).equalExceptLatex(font)) {
2215 font = getFont(i+1);
2218 // We end font definition before blanks
2219 if (!font.equalExceptLatex(running_font) && open_font) {
2220 column += running_font.latexWriteEndChanges(file, basefont);
2221 running_font = basefont;
2225 // Blanks are printed before start of fontswitch
2227 // Do not print the separation of the optional argument
2228 if (i != main_body - 1) {
2229 SimpleTeXBlanks(file, texrow, i, column, font, style);
2233 // Do we need to change font?
2234 if (!font.equalExceptLatex(running_font)
2235 && i != main_body-1) {
2236 column += font.latexWriteStartChanges(file, basefont);
2237 running_font = font;
2241 if (c == LYX_META_NEWLINE) {
2242 // newlines are handled differently here than
2243 // the default in SimpleTeXSpecialChars().
2244 if (!style->newline_allowed
2245 || font.latex() == LyXFont::ON) {
2249 column += running_font.latexWriteEndChanges(file, basefont);
2252 basefont = getFont(-1);
2253 running_font = basefont;
2254 if (font.family() ==
2255 LyXFont::TYPEWRITER_FAMILY) {
2261 texrow.start(this, i+1);
2264 SimpleTeXSpecialChars(file, texrow,
2265 font, running_font, basefont,
2266 open_font, style, i, column, c);
2270 // If we have an open font definition, we have to close it
2272 running_font.latexWriteEndChanges(file, basefont);
2275 /* needed if there is an optional argument but no contents */
2276 if (main_body > 0 && main_body == last) {
2278 return_value = false;
2281 lyxerr.debug(LString("SimpleTeXOnePar...done ") + (long)this,
2283 return return_value;
2287 // This one spits out the text of a table paragraph
2288 bool LyXParagraph::SimpleTeXOneTablePar(LString &file, TexRow &texrow)
2290 lyxerr.debug(LString("SimpleTeXOneTablePar... ")+
2291 (long)this, Error::LATEX);
2295 bool return_value = false;
2296 int current_cell_number = -1;
2298 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2301 basefont = getFont(-1); // Get layout font
2302 // Which font is currently active?
2303 LyXFont running_font = basefont;
2304 // Do we have an open font change?
2305 bool open_font = false;
2308 if (!IsDummy()) { // it is dummy if it is in a float!!!
2309 if (style->isCommand()) {
2312 } else if (align != LYX_ALIGN_LAYOUT) {
2315 return_value = true;
2318 file += "\\noindent ";
2322 case LYX_ALIGN_LEFT:
2323 file += "\\raggedright ";
2326 case LYX_ALIGN_RIGHT:
2327 file += "\\raggedleft ";
2330 case LYX_ALIGN_CENTER:
2331 file += "\\centering ";
2336 current_cell_number = -1;
2337 tmp = table->TexEndOfCell(file,current_cell_number);
2341 texrow.start(this, 0);
2343 for (int i = 0; i < last; i++) {
2345 if (table->IsContRow(current_cell_number+1)) {
2346 if (c == LYX_META_NEWLINE)
2347 current_cell_number++;
2352 // Fully instantiated font
2353 LyXFont font = getFont(i);
2355 // Spaces at end of font change are simulated to be outside font change.
2356 // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
2357 if (open_font && c == ' ' && i <= last-2
2358 && getFont(i+1) != running_font && getFont(i+1) != font) {
2359 font = getFont(i+1);
2362 // We end font definition before blanks
2363 if (font != running_font && open_font) {
2364 column += running_font.latexWriteEndChanges(file, basefont);
2365 running_font = basefont;
2368 // Blanks are printed before start of fontswitch
2370 SimpleTeXBlanks(file, texrow, i, column, font, style);
2372 // Do we need to change font?
2373 if (font != running_font) {
2374 column += font.latexWriteStartChanges(file, basefont);
2375 running_font = font;
2378 // Do we need to turn on LaTeX mode?
2379 if (font.latex() != running_font.latex()) {
2380 if (font.latex() == LyXFont::ON
2381 && style->needprotect) {
2382 file += "\\protect ";
2386 if (c == LYX_META_NEWLINE) {
2387 // special case for inside a table
2388 // different from default case in SimpleTeXSpecialChars()
2390 column += running_font.latexWriteEndChanges(file, basefont);
2393 basefont = getFont(-1);
2394 running_font = basefont;
2395 current_cell_number++;
2396 if (table->CellHasContRow(current_cell_number) >= 0) {
2397 TeXContTableRows(file, i+1, current_cell_number, column, texrow);
2399 // if this cell follow only ContRows till end don't
2400 // put the EndOfCell because it is put after the
2402 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2403 current_cell_number--;
2406 int tmp = table->TexEndOfCell(file, current_cell_number);
2409 } else if (tmp < 0) {
2415 texrow.start(this, i+1);
2417 SimpleTeXSpecialChars(file, texrow,
2418 font, running_font, basefont,
2419 open_font, style, i, column, c);
2423 // If we have an open font definition, we have to close it
2425 running_font.latexWriteEndChanges(file, basefont);
2427 current_cell_number++;
2428 tmp = table->TexEndOfCell(file, current_cell_number);
2431 lyxerr.debug(LString("SimpleTeXOneTablePar...done ")+(long)this, Error::LATEX);
2432 return return_value;
2436 // This one spits out the text off ContRows in tables
2437 bool LyXParagraph::TeXContTableRows(LString &file, int i,
2438 int current_cell_number,
2439 int &column, TexRow &texrow)
2441 lyxerr.debug(LString("TeXContTableRows... ") +
2442 (long)this, Error::LATEX);
2450 bool return_value = false;
2451 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2454 basefont = getFont(-1); // Get layout font
2455 // Which font is currently active?
2456 LyXFont running_font = basefont;
2457 // Do we have an open font change?
2458 bool open_font = false;
2461 cell = table->CellHasContRow(current_cell_number);
2462 current_cell_number++;
2464 // first find the right position
2466 for (; (i<last) && (current_cell_number<cell); i++) {
2468 if (c == LYX_META_NEWLINE)
2469 current_cell_number++;
2473 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2477 } else if ((c != ' ') && (c != LYX_META_NEWLINE)) {
2480 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE); i++) {
2483 // Fully instantiated font
2484 LyXFont font = getFont(i);
2486 // Spaces at end of font change are simulated to be outside font change.
2487 // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
2488 if (open_font && c == ' ' && i <= last-2
2489 && getFont(i+1) != running_font && getFont(i+1) != font) {
2490 font = getFont(i+1);
2493 // We end font definition before blanks
2494 if (font != running_font && open_font) {
2495 column += running_font.latexWriteEndChanges(file, basefont);
2496 running_font = basefont;
2499 // Blanks are printed before start of fontswitch
2501 SimpleTeXBlanks(file, texrow, i, column, font, style);
2503 // Do we need to change font?
2504 if (font != running_font) {
2505 column += font.latexWriteStartChanges(file, basefont);
2506 running_font = font;
2509 // Do we need to turn on LaTeX mode?
2510 if (font.latex() != running_font.latex()) {
2511 if (font.latex() == LyXFont::ON
2512 && style->needprotect)
2514 file += "\\protect ";
2518 SimpleTeXSpecialChars(file, texrow, font, running_font, basefont,
2519 open_font, style, i, column, c);
2521 // If we have an open font definition, we have to close it
2523 running_font.latexWriteEndChanges(file, basefont);
2526 basefont = getFont(-1);
2527 running_font = basefont;
2528 cell = table->CellHasContRow(current_cell_number);
2530 lyxerr.debug(LString("TeXContTableRows...done ")+(long)this, Error::LATEX);
2531 return return_value;
2535 bool LyXParagraph::linuxDocConvertChar(char c, LString &sgml_string)
2537 bool retval = false;
2539 case LYX_META_HFILL:
2540 sgml_string.clean();
2542 case LYX_META_PROTECTED_SEPARATOR:
2545 case LYX_META_NEWLINE:
2549 sgml_string = "&";
2552 sgml_string = "<";
2555 sgml_string = ">";
2558 sgml_string = "$";
2561 sgml_string = "#";
2564 sgml_string = "%";
2567 sgml_string = "[";
2570 sgml_string = "]";
2573 sgml_string = "{";
2576 sgml_string = "}";
2579 sgml_string = "˜";
2582 sgml_string = "&dquot;";
2585 sgml_string = "\";
2591 case '\0': /* Ignore :-) */
2592 sgml_string.clean();
2601 void LyXParagraph::SimpleDocBookOneTablePar(LString &file, LString &extra,
2602 int & desc_on, int depth)
2606 lyxerr.debug(LString("SimpleDocbookOneTablePar... ") +
2607 (long)this, Error::LATEX);
2609 bool return_value = false;
2610 int current_cell_number = -1;
2611 LyXFont font1,font2;
2615 LString emph="emphasis";
2616 bool emph_flag=false;
2617 int char_line_count=0;
2619 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2621 if (style->labeltype != LABEL_MANUAL)
2624 main_body = BeginningOfMainBody();
2626 /* gets paragraph main font */
2628 font1 = style->labelfont;
2630 font1 = style->font;
2632 char_line_count = depth;
2633 addNewlineAndDepth(file, depth);
2634 if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2635 file += "<INFORMALTABLE>";
2636 addNewlineAndDepth(file, ++depth);
2638 current_cell_number = -1;
2639 tmp = table->DocBookEndOfCell(file,current_cell_number, depth);
2641 /* parsing main loop */
2642 for (int i = 0; i < last; i++) {
2644 if (table->IsContRow(current_cell_number+1)) {
2645 if (c == LYX_META_NEWLINE)
2646 current_cell_number++;
2651 // Fully instantiated font
2654 /* handle <emphasis> tag */
2655 if (font1.emph() != font2.emph() && i) {
2656 if (font2.emph() == LyXFont::ON) {
2657 file += "<emphasis>";
2659 } else if (emph_flag) {
2660 file += "</emphasis>";
2664 if (c == LYX_META_NEWLINE) {
2665 // we have only to control for emphasis open here!
2667 file += "</emphasis>";
2670 font1 = font2 = getFont(-1);
2671 current_cell_number++;
2672 if (table->CellHasContRow(current_cell_number) >= 0) {
2673 DocBookContTableRows(file, extra, desc_on, i+1,
2674 current_cell_number,
2677 // if this cell follow only ContRows till end don't
2678 // put the EndOfCell because it is put after the
2680 if (table->ShouldBeVeryLastCell(current_cell_number)) {
2681 current_cell_number--;
2684 tmp=table->DocBookEndOfCell(file, current_cell_number,
2689 } else if (c == LYX_META_INSET) {
2690 inset = GetInset(i);
2692 inset->DocBook(tmp_out);
2694 // This code needs some explanation:
2695 // Two insets are treated specially
2696 // label if it is the first element in a command paragraph
2698 // graphics inside tables or figure floats can't go on
2699 // title (the equivalente in latex for this case is caption
2700 // and title should come first
2703 if(desc_on!=3 || i!=0) {
2704 if(tmp_out[0]=='@') {
2706 extra += tmp_out.frontStrip('@');
2708 file += tmp_out.frontStrip('@');
2712 } else if (font2.latex() == LyXFont::ON) {
2713 // "TeX"-Mode on ==> SGML-Mode on.
2718 LString sgml_string;
2719 if (linuxDocConvertChar(c, sgml_string)
2720 && !style->free_spacing) {
2721 // in freespacing mode, spaces are
2722 // non-breaking characters
2727 file += "</term><listitem><para>";
2733 file += sgml_string;
2739 /* needed if there is an optional argument but no contents */
2740 if (main_body > 0 && main_body == last) {
2741 font1 = style->font;
2745 file += "</emphasis>";
2748 current_cell_number++;
2749 tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
2750 /* resets description flag correctly */
2753 /* <term> not closed... */
2757 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2758 file += "</INFORMALTABLE>";
2760 lyxerr.debug(LString("SimpleDocbookOneTablePar...done ") +
2761 (long)this, Error::LATEX);
2764 void LyXParagraph::DocBookContTableRows(LString &file, LString &extra,
2765 int & desc_on, int i,
2766 int current_cell_number, int &column)
2771 lyxerr.debug(LString("DocBookContTableRows... ") +
2772 (long)this, Error::LATEX);
2773 int tmp, cell, lastpos;
2774 LyXFont font1,font2;
2778 LString emph="emphasis";
2779 bool emph_flag=false;
2780 int char_line_count=0;
2782 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2784 if (style->labeltype != LABEL_MANUAL)
2787 main_body = BeginningOfMainBody();
2789 /* gets paragraph main font */
2791 font1 = style->labelfont;
2793 font1 = style->font;
2796 cell = table->CellHasContRow(current_cell_number);
2797 current_cell_number++;
2799 // first find the right position
2801 for (; (i<last) && (current_cell_number<cell); i++) {
2803 if (c == LYX_META_NEWLINE)
2804 current_cell_number++;
2808 // I don't know how to handle this so I comment it
2809 // for the moment (Jug)
2810 // if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2811 // file += " \\\\\n";
2814 if ((c != ' ') && (c != LYX_META_NEWLINE)) {
2817 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE); i++) {
2820 // Fully instantiated font
2823 /* handle <emphasis> tag */
2824 if (font1.emph() != font2.emph() && i) {
2825 if (font2.emph() == LyXFont::ON) {
2826 file += "<emphasis>";
2828 } else if (emph_flag) {
2829 file += "</emphasis>";
2833 if (c == LYX_META_INSET) {
2834 inset = GetInset(i);
2836 inset->DocBook(tmp_out);
2838 // This code needs some explanation:
2839 // Two insets are treated specially
2840 // label if it is the first element in a command paragraph
2842 // graphics inside tables or figure floats can't go on
2843 // title (the equivalente in latex for this case is caption
2844 // and title should come first
2847 if(desc_on!=3 || i!=0) {
2848 if(tmp_out[0]=='@') {
2850 extra += tmp_out.frontStrip('@');
2852 file += tmp_out.frontStrip('@');
2856 } else if (font2.latex() == LyXFont::ON) {
2857 // "TeX"-Mode on ==> SGML-Mode on.
2862 LString sgml_string;
2863 if (linuxDocConvertChar(c, sgml_string)
2864 && !style->free_spacing) {
2865 // in freespacing mode, spaces are
2866 // non-breaking characters
2871 file += "</term><listitem><para>";
2877 file += sgml_string;
2881 // we have only to control for emphasis open here!
2883 file += "</emphasis>";
2886 font1 = font2 = getFont(-1);
2887 cell = table->CellHasContRow(current_cell_number);
2889 lyxerr.debug(LString("DocBookContTableRows...done ") +
2890 (long)this, Error::LATEX);
2895 void LyXParagraph::SimpleTeXBlanks(LString &file, TexRow &texrow,
2896 int const i, int &column, LyXFont const &font,
2897 LyXLayout const * const style)
2899 if (column > tex_code_break_column
2901 && GetChar(i-1) != ' '
2903 // In LaTeX mode, we don't want to
2904 // break lines since some commands
2906 && ! (font.latex() == LyXFont::ON)
2907 // same in FreeSpacing mode
2908 && !style->free_spacing
2909 // In typewriter mode, we want to avoid
2910 // ! . ? : at the end of a line
2911 && !(font.family() == LyXFont::TYPEWRITER_FAMILY
2912 && (GetChar(i-1) == '.'
2913 || GetChar(i-1) == '?'
2914 || GetChar(i-1) == ':'
2915 || GetChar(i-1) == '!'))) {
2916 if (tex_code_break_column == 0) {
2917 // in batchmode we need LaTeX to still
2918 // see it as a space not as an extra '\n'
2924 texrow.start(this, i+1);
2926 } else if (font.latex() == LyXFont::OFF) {
2927 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
2937 void LyXParagraph::SimpleTeXSpecialChars(LString &file, TexRow &texrow,
2938 LyXFont &font, LyXFont &running_font, LyXFont &basefont,
2939 bool &open_font, LyXLayout const * const style,
2940 int &i, int &column, char const c)
2944 // Two major modes: LaTeX or plain
2945 // Handle here those cases common to both modes
2946 // and then split to handle the two modes separately.
2948 case LYX_META_INSET:
2949 inset = GetInset(i);
2951 int len = file.length();
2952 int tmp = inset->Latex(file, style->isCommand());
2957 column += file.length() - len;
2965 case LYX_META_NEWLINE:
2967 column += running_font.latexWriteEndChanges(file, basefont);
2970 basefont = getFont(-1);
2971 running_font = basefont;
2974 case LYX_META_HFILL:
2975 file += "\\hfill{}";
2980 // And now for the special cases within each mode
2981 // Are we in LaTeX mode?
2982 if (font.latex() == LyXFont::ON) {
2983 // at present we only have one option
2984 // but I'll leave it as a switch statement
2985 // so its simpler to extend. (ARRae)
2987 case LYX_META_PROTECTED_SEPARATOR:
2992 // make sure that we will not print
2993 // error generating chars to the tex
2994 // file. This test would not be needed
2995 // if it were done in the buffer
3003 // Plain mode (i.e. not LaTeX)
3005 case LYX_META_PROTECTED_SEPARATOR:
3010 file += "\\textbackslash{}";
3014 case '°': case '±': case '²': case '³':
3015 case '×': case '÷': case '¹': case 'ª':
3016 case 'º': case '¬': case 'µ':
3017 if (current_view->currentBuffer()->params.inputenc == "latin1") {
3018 file += "\\ensuremath{";
3027 case '|': case '<': case '>':
3028 // In T1 encoding, these characters exist
3029 if (lyxrc->fontenc == "T1") {
3031 //... but we should avoid ligatures
3032 if ((c == '>' || c == '<')
3034 && GetChar(i+1) == c){
3035 file += "\\textcompwordmark{}";
3040 // Typewriter font also has them
3041 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3045 // Otherwise, we use what LaTeX
3049 file += "\\textless{}";
3053 file += "\\textgreater{}";
3057 file += "\\textbar{}";
3063 case '-': // "--" in Typewriter mode -> "-{}-"
3065 && GetChar(i+1) == '-'
3066 && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3075 file += "\\char`\\\"{}";
3080 if (current_view->currentBuffer()->params.inputenc == "default") {
3081 file += "\\pounds{}";
3089 case '%': case '#': case '{':
3103 case '*': case '[': case ']':
3104 // avoid being mistaken for optional arguments
3112 /* blanks are printed before font switching */
3113 // Sure? I am not! (try nice-latex)
3114 // I am sure it's correct. LyX might be smarter
3115 // in the future, but for now, nothing wrong is
3120 /* idea for labels --- begin*/
3124 && font.family() != LyXFont::TYPEWRITER_FAMILY
3125 && GetChar(i+1) == 'y'
3126 && GetChar(i+2) == 'X') {
3134 && font.family() != LyXFont::TYPEWRITER_FAMILY
3135 && GetChar(i+1) == 'e'
3136 && GetChar(i+2) == 'X') {
3141 /* check for LaTeX2e */
3144 && font.family() != LyXFont::TYPEWRITER_FAMILY
3145 && GetChar(i+1) == 'a'
3146 && GetChar(i+2) == 'T'
3147 && GetChar(i+3) == 'e'
3148 && GetChar(i+4) == 'X'
3149 && GetChar(i+5) == '2'
3150 && GetChar(i+6) == 'e') {
3151 file += "\\LaTeXe{}";
3155 /* check for LaTeX */
3158 && font.family() != LyXFont::TYPEWRITER_FAMILY
3159 && GetChar(i+1) == 'a'
3160 && GetChar(i+2) == 'T'
3161 && GetChar(i+3) == 'e'
3162 && GetChar(i+4) == 'X') {
3163 file += "\\LaTeX{}";
3166 /* idea for labels --- end*/
3167 } else if (c != '\0') {
3177 bool LyXParagraph::RoffContTableRows(FILE *fp, int i, int actcell)
3183 font1 = LyXFont(LyXFont::ALL_INHERIT),
3196 fname2 = TmpFileName(LString(),"RAT2");
3198 cell = table->CellHasContRow(actcell);
3201 // first find the right position
3203 for (; (i<last) && (actcell<cell); i++) {
3205 if (c == LYX_META_NEWLINE)
3210 if ((c != ' ') && (c != LYX_META_NEWLINE))
3212 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE); i++) {
3213 font2 = GetFontSettings(i);
3214 if (font1.latex() != font2.latex()) {
3215 if (font2.latex() != LyXFont::OFF)
3220 case LYX_META_INSET:
3221 if ((inset = GetInset(i))) {
3222 if (!(fp2=fopen(fname2.c_str(),"w+"))) {
3223 WriteAlert(_("LYX_ERROR:"), _("Cannot open temporary file:"), fname2);
3226 inset->Latex(fp2,-1);
3239 case LYX_META_NEWLINE:
3241 case LYX_META_HFILL:
3243 case LYX_META_PROTECTED_SEPARATOR:
3246 fprintf(fp, "\\\\");
3250 fprintf(fp, "%c", c);
3252 lyxerr.debug("RoffAsciiTable: NULL char in structure.");
3256 cell = table->CellHasContRow(actcell);
3261 LyXParagraph * LyXParagraph::TeXDeeper(LString &file, TexRow &texrow,
3262 LString &foot, TexRow &foot_texrow,
3265 lyxerr.debug(LString("TeXDeeper... ") + (long)this, Error::LATEX);
3266 LyXParagraph *par = this;
3268 while (par && par->depth == depth) {
3270 lyxerr.print("ERROR (LyXParagraph::TeXDeeper)");
3271 if (lyxstyle.Style(GetCurrentTextClass(),
3272 par->layout)->isEnvironment()
3273 || par->pextra_type != PEXTRA_NONE)
3275 par = par->TeXEnvironment(file, texrow,
3279 par = par->TeXOnePar(file, texrow,
3284 lyxerr.debug(LString("TeXDeeper...done ") + (long)par, Error::LATEX);
3290 LyXParagraph* LyXParagraph::TeXEnvironment(LString &file, TexRow &texrow,
3291 LString &foot, TexRow &foot_texrow,
3295 eindent_open = false;
3297 foot_this_level = false;
3298 // flags when footnotetext should be appended to file.
3300 minipage_open = false;
3302 minipage_open_depth = 0;
3304 par_sep = current_view->currentBuffer()->params.paragraph_separation;
3306 lyxerr.debug(LString("TeXEnvironment... ") + long(this), Error::LATEX);
3308 lyxerr.print("ERROR (LyXParagraph::TeXEnvironment)");
3310 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), layout);
3312 if (pextra_type == PEXTRA_INDENT) {
3313 if (!pextra_width.empty()) {
3314 file += "\\begin{LyXParagraphIndent}{"
3315 + pextra_width + "}\n";
3317 //float ib = atof(pextra_widthp.c_str())/100;
3318 // LString can't handle floats at present (971109)
3319 // so I'll do a conversion by hand knowing that
3320 // the limits are 0.0 to 1.0. ARRae.
3321 file += "\\begin{LyXParagraphIndent}{";
3322 switch (pextra_widthp.length()) {
3328 file += pextra_widthp;
3332 file += pextra_widthp;
3334 file += "\\columnwidth}\n";
3337 eindent_open = true;
3339 if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3340 if (pextra_hfill && Previous() &&
3341 (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3342 file += "\\hfill{}\n";
3345 if (par_sep == LYX_PARSEP_INDENT) {
3346 file += "{\\setlength\\parindent{0pt}\n";
3349 file += "\\begin{minipage}";
3350 switch(pextra_alignment) {
3351 case MINIPAGE_ALIGN_TOP:
3354 case MINIPAGE_ALIGN_MIDDLE:
3357 case MINIPAGE_ALIGN_BOTTOM:
3361 if (!pextra_width.empty()) {
3363 file += pextra_width + "}\n";
3365 //float ib = atof(par->pextra_width.c_str())/100;
3366 // LString can't handle floats at present
3367 // so I'll do a conversion by hand knowing that
3368 // the limits are 0.0 to 1.0. ARRae.
3370 switch (pextra_widthp.length()) {
3376 file += pextra_widthp;
3380 file += pextra_widthp;
3382 file += "\\columnwidth}\n";
3385 if (par_sep == LYX_PARSEP_INDENT) {
3386 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3389 minipage_open = true;
3390 minipage_open_depth = depth;
3393 #ifdef WITH_WARNINGS
3394 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3395 //I disabled it because it breaks when lists span on several
3398 if (style->isEnvironment()){
3399 if (style->latextype == LATEX_LIST_ENVIRONMENT) {
3400 #ifdef FANCY_FOOTNOTE_CODE
3401 if (foot_count < 0) {
3402 // flag that footnote[mark][text] should be
3403 // used for any footnotes from now on
3405 foot_this_level = true;
3408 file += "\\begin{" + style->latexname + "}{"
3409 + labelwidthstring + "}\n";
3410 } else if (style->labeltype == LABEL_BIBLIO) {
3412 file += "\\begin{" + style->latexname + "}{"
3413 + bibitemWidthest() + "}\n";
3414 } else if (style->latextype == LATEX_ITEM_ENVIRONMENT) {
3415 #ifdef FANCY_FOOTNOTE_CODE
3416 if (foot_count < 0) {
3417 // flag that footnote[mark][text] should be
3418 // used for any footnotes from now on
3420 foot_this_level = true;
3423 file += "\\begin{" + style->latexname + '}'
3424 + style->latexparam + '\n';
3426 file += "\\begin{" + style->latexname + '}'
3427 + style->latexparam + '\n';
3430 LyXParagraph *par = this;
3432 par = par->TeXOnePar(file, texrow,
3433 foot, foot_texrow, foot_count);
3435 if (eindent_open && par && par->pextra_type != PEXTRA_INDENT) {
3436 file += "\\end{LyXParagraphIndent}\n";
3438 eindent_open = false;
3439 if (!style->isEnvironment())
3443 if (minipage_open && par && !style->isEnvironment() &&
3444 (par->pextra_type == PEXTRA_MINIPAGE) &&
3445 par->pextra_start_minipage) {
3446 file += "\\end{minipage}\n";
3448 if (par_sep == LYX_PARSEP_INDENT) {
3452 minipage_open = false;
3454 if (par && par->depth > depth) {
3455 if (lyxstyle.Style(GetCurrentTextClass(),
3456 par->layout)->isParagraph()
3458 && !file.suffixIs("\n\n")) {
3459 // There should be at least one '\n' already
3460 // but we need there to be two for Standard
3461 // paragraphs that are depth-increment'ed to be
3462 // output correctly. However, tables can also be
3463 // paragraphs so don't adjust them. ARRae
3467 par = par->TeXDeeper(file, texrow,
3468 foot, foot_texrow, foot_count);
3470 if (par && par->layout == layout && par->depth == depth &&
3471 (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3472 if (par->pextra_hfill && par->Previous() &&
3473 (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3474 file += "\\hfill{}\n";
3479 if (par_sep == LYX_PARSEP_INDENT) {
3480 file += "{\\setlength\\parindent{0pt}\n";
3483 file += "\\begin{minipage}";
3484 switch(par->pextra_alignment) {
3485 case MINIPAGE_ALIGN_TOP:
3488 case MINIPAGE_ALIGN_MIDDLE:
3491 case MINIPAGE_ALIGN_BOTTOM:
3495 if (!par->pextra_width.empty()) {
3497 file += par->pextra_width;
3500 //float ib = atof(par->pextra_widthp.c_str())/100;
3501 // LString can't handle floats at present
3502 // so I'll do a conversion by hand knowing that
3503 // the limits are 0.0 to 1.0. ARRae.
3505 switch (par->pextra_widthp.length()) {
3511 file += par->pextra_widthp;
3515 file += par->pextra_widthp;
3517 file += "\\columnwidth}\n";
3520 if (par_sep == LYX_PARSEP_INDENT) {
3521 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3524 minipage_open = true;
3525 minipage_open_depth = par->depth;
3528 && par->layout == layout
3529 && par->depth == depth
3530 && par->pextra_type == pextra_type);
3532 if (style->isEnvironment()) {
3533 file += "\\end{" + style->latexname + '}';
3534 // maybe this should go after the minipage closes?
3535 if (foot_this_level) {
3536 if (foot_count >= 1) {
3537 if (foot_count > 1) {
3538 file += "\\addtocounter{footnote}{-";
3539 file += foot_count - 1;
3543 texrow += foot_texrow;
3545 foot_texrow.reset();
3550 if (minipage_open && (minipage_open_depth == depth) &&
3551 (!par || par->pextra_start_minipage ||
3552 par->pextra_type != PEXTRA_MINIPAGE)) {
3553 file += "\\end{minipage}\n";
3555 if (par_sep == LYX_PARSEP_INDENT) {
3559 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3560 file += "\\medskip\n\n";
3564 minipage_open = false;
3567 file += "\\end{LyXParagraphIndent}\n";
3570 // if (tex_code_break_column){
3571 if (!(par && (par->pextra_type==PEXTRA_MINIPAGE)
3572 && par->pextra_hfill)) {
3576 lyxerr.debug(LString("TeXEnvironment...done ")
3577 + (long)par, Error::LATEX);
3578 return par; // ale970302
3582 LyXParagraph * LyXParagraph::TeXFootnote(LString &file, TexRow &texrow,
3583 LString &foot, TexRow &foot_texrow,
3586 lyxerr.debug(LString("TeXFootnote... ")
3587 + (long)this, Error::LATEX);
3588 if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3589 lyxerr.print("ERROR (LyXParagraph::TeXFootnote): "
3592 LyXParagraph *par = this;
3593 LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(),
3594 previous->GetLayout());
3596 if (style->needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3597 lyxerr.print("ERROR (LyXParagraph::TeXFootnote): "
3598 "Float other than footnote in command"
3599 " with moving argument is illegal");
3602 if (footnotekind != LyXParagraph::FOOTNOTE
3603 && footnotekind != LyXParagraph::MARGIN
3605 && !file.suffixIs('\n')) {
3606 // we need to ensure that real floats like tables and figures
3607 // have their \begin{} on a new line otherwise we can get
3608 // incorrect results when using the endfloat.sty package
3609 // especially if two floats follow one another. ARRae 981022
3610 // NOTE: if the file is length 0 it must have just been
3611 // written out so we assume it ended with a '\n'
3616 BufferParams *params = ¤t_view->currentBuffer()->params;
3617 bool footer_in_body = true;
3618 switch (footnotekind) {
3619 case LyXParagraph::FOOTNOTE:
3620 if (style->intitle) {
3621 file += "\\thanks{\n";
3622 footer_in_body = false;
3624 if (foot_count == -1) {
3625 // we're at depth 0 so we can use:
3626 file += "\\footnote{%\n";
3627 footer_in_body = false;
3629 file += "\\footnotemark{}%\n";
3631 // we only need this when there are
3632 // multiple footnotes
3633 foot += "\\stepcounter{footnote}";
3635 foot += "\\footnotetext{%\n";
3636 foot_texrow.start(this,0);
3637 foot_texrow.newline();
3642 case LyXParagraph::MARGIN:
3643 file += "\\marginpar{\n";
3645 case LyXParagraph::FIG:
3646 if (pextra_type == PEXTRA_FLOATFLT
3647 && (!pextra_width.empty()
3648 || !pextra_widthp.empty())) {
3650 if (!pextra_width.empty())
3651 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
3652 pextra_width.c_str());
3654 sprintf(bufr, "\\begin{floatingfigure}{%f\\textwidth}\n",
3655 atoi(pextra_widthp.c_str())/100.0);
3658 file += "\\begin{figure}";
3659 if (!params->float_placement.empty()) {
3661 file += params->float_placement;
3668 case LyXParagraph::TAB:
3669 file += "\\begin{table}";
3670 if (!params->float_placement.empty()) {
3672 file += params->float_placement;
3678 case LyXParagraph::WIDE_FIG:
3679 file += "\\begin{figure*}";
3680 if (!params->float_placement.empty()) {
3682 file += params->float_placement;
3688 case LyXParagraph::WIDE_TAB:
3689 file += "\\begin{table*}";
3690 if (!params->float_placement.empty()) {
3692 file += params->float_placement;
3698 case LyXParagraph::ALGORITHM:
3699 file += "\\begin{algorithm}\n";
3704 if (footnotekind != LyXParagraph::FOOTNOTE
3705 || !footer_in_body) {
3706 // Process text for all floats except footnotes in body
3708 LyXLayout *style = lyxstyle.Style(GetCurrentTextClass(),
3711 lyxerr.print("ERROR (LyXParagraph::TeXFootnote)");
3712 if (style->isEnvironment()
3713 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3714 // Allows the use of minipages within float environments.
3715 // Shouldn't be circular because we don't support
3716 // footnotes inside floats (yet). ARRae
3717 par = par->TeXEnvironment(file, texrow,
3721 par = par->TeXOnePar(file, texrow,
3726 if (par && !par->IsDummy() && par->depth > depth) {
3727 par = par->TeXDeeper(file, texrow,
3731 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3733 // process footnotes > depth 0 or in environments separately
3734 // NOTE: Currently don't support footnotes within footnotes
3735 // even though that is possible using the \footnotemark
3737 TexRow dummy_texrow;
3738 int dummy_count = 0;
3740 LyXLayout *style = lyxstyle.Style(GetCurrentTextClass(),
3743 lyxerr.print("ERROR (LyXParagraph::TeXFootnote)");
3744 if (style->isEnvironment()
3745 || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3746 // Allows the use of minipages within float environments.
3747 // Shouldn't be circular because we don't support
3748 // footnotes inside floats (yet). ARRae
3749 par = par->TeXEnvironment(foot, foot_texrow,
3750 dummy, dummy_texrow,
3753 par = par->TeXOnePar(foot, foot_texrow,
3754 dummy, dummy_texrow,
3758 if (par && !par->IsDummy() && par->depth > depth) {
3759 par = par->TeXDeeper(foot, foot_texrow,
3760 dummy, dummy_texrow,
3763 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3765 lyxerr.print("ERROR (LyXParagraph::TeXFootnote): "
3766 "Footnote in a Footnote -- not supported");
3770 switch (footnotekind) {
3771 case LyXParagraph::FOOTNOTE:
3772 if (footer_in_body) {
3773 // This helps tell which of the multiple
3774 // footnotetexts an error was in.
3776 foot_texrow.newline();
3781 case LyXParagraph::MARGIN:
3784 case LyXParagraph::FIG:
3785 if (pextra_type == PEXTRA_FLOATFLT
3786 && (!pextra_width.empty()
3787 || !pextra_widthp.empty()))
3788 file += "\\end{floatingfigure}";
3790 file += "\\end{figure}";
3792 case LyXParagraph::TAB:
3793 file += "\\end{table}";
3795 case LyXParagraph::WIDE_FIG:
3796 file += "\\end{figure*}";
3798 case LyXParagraph::WIDE_TAB:
3799 file += "\\end{table*}";
3801 case LyXParagraph::ALGORITHM:
3802 file += "\\end{algorithm}";
3806 if (footnotekind != LyXParagraph::FOOTNOTE
3807 && footnotekind != LyXParagraph::MARGIN) {
3808 // we need to ensure that real floats like tables and figures
3809 // have their \end{} on a line of their own otherwise we can
3810 // get incorrect results when using the endfloat.sty package.
3815 lyxerr.debug(LString("TeXFootnote...done ") +
3816 long(par->next), Error::LATEX);
3821 void LyXParagraph::SetPExtraType(int type, const char *width,const char *widthp)
3824 pextra_width = width;
3825 pextra_widthp = widthp;
3827 if (lyxstyle.Style(GetCurrentTextClass(),
3828 layout)->isEnvironment()) {
3833 while (par && (par->layout == layout) && (par->depth == depth)) {
3835 par = par->Previous();
3837 par = par->FirstPhysicalPar();
3838 while (par && par->depth > depth) {
3839 par = par->Previous();
3841 par = par->FirstPhysicalPar();
3845 while (par && (par->layout == layout) && (par->depth == depth)) {
3846 par->pextra_type = type;
3847 par->pextra_width = width;
3848 par->pextra_widthp = widthp;
3849 par = par->NextAfterFootnote();
3850 if (par && (par->depth > depth))
3851 par->SetPExtraType(type,width,widthp);
3852 while (par && ((par->depth > depth) || par->IsDummy()))
3853 par = par->NextAfterFootnote();
3858 void LyXParagraph::UnsetPExtraType()
3860 if (pextra_type == PEXTRA_NONE)
3863 pextra_type = PEXTRA_NONE;
3864 pextra_width.clean();
3865 pextra_widthp.clean();
3867 if (lyxstyle.Style(GetCurrentTextClass(),
3868 layout)->isEnvironment()) {
3873 while (par && (par->layout == layout) && (par->depth == depth)) {
3875 par = par->Previous();
3877 par = par->FirstPhysicalPar();
3878 while (par && par->depth > depth) {
3879 par = par->Previous();
3881 par = par->FirstPhysicalPar();
3885 while (par && (par->layout == layout) && (par->depth == depth)) {
3886 par->pextra_type = PEXTRA_NONE;
3887 par->pextra_width.clean();
3888 par->pextra_widthp.clean();
3889 par = par->NextAfterFootnote();
3890 if (par && (par->depth > depth))
3891 par->UnsetPExtraType();
3892 while (par && ((par->depth > depth) || par->IsDummy()))
3893 par = par->NextAfterFootnote();