home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 52
/
Amiga_Dream_52.iso
/
Linux
/
Divers
/
lyx-0.13.2.tar.gz
/
lyx-0.13.2.tar
/
lyx-0.13.2
/
src
/
paragraph.C
< prev
next >
Wrap
C/C++ Source or Header
|
1998-04-23
|
96KB
|
3,752 lines
/* This file is part of
* ======================================================
*
* LyX, The Document Processor
*
* Copyright (C) 1995 Matthias Ettrich
* Copyright (C) 1995-1998 The LyX Team.
*
*======================================================*/
#include <config.h>
#ifdef __GNUG__
#pragma implementation "lyxparagraph.h"
#endif
#include "lyxparagraph.h"
#include "lyxrc.h"
#include "layout.h"
#include "tex-strings.h"
#include "bufferparams.h"
#include "FileInfo.h"
#include "error.h"
#include "LaTeXFeatures.h"
#include "insetinclude.h"
#include "filetools.h"
#include "lyx_gui_misc.h"
#include "texrow.h"
// $Id: paragraph.C,v 1.1.1.1 1998/04/23 16:02:56 larsbj Exp $
#if !defined(lint) && !defined(WITH_WARNINGS)
static char vcid[] = "$Id: paragraph.C,v 1.1.1.1 1998/04/23 16:02:56 larsbj Exp $";
#endif /* lint */
#define INITIAL_SIZE_PAR 10 /*Number of bytes in one paragraph*/
#define STEP_SIZE_PAR 10 /*Number of bytes added when reallocated*/
extern unsigned char GetCurrentTextClass(); // this should be fixed/removed
int tex_code_break_column;
// this is a bad idea, but how can LyXParagraph find its buffer to get
// parameters? (JMarc)
extern BufferView *current_view;
extern LyXRC *lyxrc;
// ale970405
extern LString bibitemWidthest();
/* this is a minibuffer */
static char minibuffer_char;
static LyXFont minibuffer_font;
static Inset *minibuffer_inset;
/* the counter for the paragraph id's */
static paragraph_id = 0;
LyXParagraph::LyXParagraph()
{
size = INITIAL_SIZE_PAR;
last = 0;
text = new char[size];
for (int i=0; i<10; i++) counter[i] = 0;
enumdepth = 0;
itemdepth = 0;
next = NULL;
previous = NULL;
fonttable = NULL;
insettable = NULL;
footnoteflag = LyXParagraph::NO_FOOTNOTE;
align = LYX_ALIGN_BLOCK;
/* table stuff -- begin*/
table = NULL;
/* table stuff -- end*/
id = paragraph_id++;
bibkey = NULL; // ale970302
Clear();
}
/* this konstruktor inserts the new paragraph in a list */
LyXParagraph::LyXParagraph(LyXParagraph *par)
{
size = INITIAL_SIZE_PAR;
last = 0;
text = new char[size];
for (int i=0; i<10; i++) counter[i] = 0;
enumdepth = 0;
itemdepth = 0;
next = par->next;
if (next)
next->previous = this;
previous = par;
previous->next = this;
fonttable = NULL;
insettable = NULL;
footnoteflag = LyXParagraph::NO_FOOTNOTE;
footnotekind = LyXParagraph::FOOTNOTE;
/* table stuff -- begin*/
table = NULL;
/* table stuff -- end*/
id = paragraph_id++;
bibkey = NULL; // ale970302
// ale970302
// fprintf(stderr, "new bib "); fflush(stderr);
// if (par->bibkey) {
// bibkey = new InsetBibKey(par->bibkey);
// }
Clear();
}
/// Used by the spellchecker
bool LyXParagraph::IsLetter(int pos){
unsigned char c = GetChar(pos);
if (IsLetterChar(c))
return true;
// We want to pass the ' and escape chars to ispell
LString extra = lyxrc->isp_esc_chars + '\'';
char ch[2];
ch[0] = c;
ch[1] = 0;
return extra.contains(ch);
}
void LyXParagraph::writeFile(FILE *file, BufferParams ¶ms,
char footflag, char dth)
{
LyXFont font1, font2;
Inset *inset;
int column = 0;
int h = 0;
char c = 0;
if (footnoteflag != LyXParagraph::NO_FOOTNOTE
|| !previous
|| previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
/* The beginning or the end of a footnote environment? */
if (footflag != footnoteflag) {
footflag = footnoteflag;
if (footflag) {
fprintf(file, "\n\\begin_float %s ",
string_footnotekinds[footnotekind]);
}
else {
fprintf(file, "\n\\end_float ");
}
}
/* The beginning or end of a deeper (i.e. nested) area? */
if (dth != depth) {
if (depth > dth) {
while (depth > dth) {
fprintf(file, "\n\\begin_deeper ");
dth++;
}
}
else {
while (depth < dth) {
fprintf(file, "\n\\end_deeper ");
dth--;
}
}
}
/* First write the layout */
fprintf(file, "\n\\layout %s\n",
lyxstyle.NameOfLayout(params.textclass,layout).c_str());
/* maybe some vertical spaces */
if (added_space_top.kind() != VSpace::NONE)
fprintf(file, "\\added_space_top %s ",
added_space_top.asLyXCommand().c_str());
if (added_space_bottom.kind() != VSpace::NONE)
fprintf(file, "\\added_space_bottom %s ",
added_space_bottom.asLyXCommand().c_str());
/* The labelwidth string used in lists */
if (!labelwidthstring.empty())
fprintf(file, "\\labelwidthstring %s\n",
labelwidthstring.c_str());
/* Lines above or below? */
if (line_top)
fprintf(file, "\\line_top ");
if (line_bottom)
fprintf(file, "\\line_bottom ");
/* Pagebreaks above or below? */
if (pagebreak_top)
fprintf(file, "\\pagebreak_top ");
if (pagebreak_bottom)
fprintf(file, "\\pagebreak_bottom ");
/* Noindent? */
if (noindent)
fprintf(file, "\\noindent ");
/* Alignment? */
if (align != LYX_ALIGN_LAYOUT) {
switch (align) {
case LYX_ALIGN_LEFT: h = 1; break;
case LYX_ALIGN_RIGHT: h = 2; break;
case LYX_ALIGN_CENTER: h = 3; break;
default: h = 0; break;
}
fprintf(file, "\\align %s ", string_align[h]);
}
if (pextra_type != PEXTRA_NONE) {
fprintf(file, "\\pextra_type %d", pextra_type);
if (pextra_type == PEXTRA_MINIPAGE) {
fprintf(file, " \\pextra_alignment %d",
pextra_alignment);
if (pextra_hfill)
fprintf(file, " \\pextra_hfill %d",
pextra_hfill);
if (pextra_start_minipage)
fprintf(file, " \\pextra_start_minipage %d",
pextra_start_minipage);
}
if (!pextra_width.empty()) {
fprintf(file, " \\pextra_width %s",
VSpace(pextra_width).asLyXCommand().c_str());
} else if (!pextra_widthp.empty()) {
fprintf(file, " \\pextra_widthp %s",pextra_widthp.c_str());
}
fprintf(file,"\n");
}
}
else {
/* Dummy layout. This means that a footnote ended */
fprintf(file, "\n\\end_float ");
footflag = LyXParagraph::NO_FOOTNOTE;
}
/* It might be a table */
if (table){
fprintf(file, "\\LyXTable\n");
table->Write(file);
}
// bibitem ale970302
if (bibkey)
bibkey->Write(file);
font1 = LyXFont(LyXFont::ALL_INHERIT);
column = 0;
for (int i = 0; i < last; i++) {
if (!i){
fprintf(file, "\n");
column = 0;
}
// Write font changes
font2 = GetFontSettings(i);
if (font2 != font1) {
font2.lyxWriteChanges(font1, file);
column = 0;
font1 = font2;
}
c = GetChar(i);
switch (c) {
case LYX_META_INSET:
inset = GetInset(i);
if (inset)
if (inset->DirectWrite()) {
// international char, let it write
// code directly so it's shorter in
// the file
inset->Write(file);
} else {
fprintf(file, "\n\\begin_inset ");
inset->Write(file);
fprintf(file, "\n\\end_inset \n");
fprintf(file, "\n");
column = 0;
}
break;
case LYX_META_NEWLINE:
fprintf(file, "\n\\newline \n");
column = 0;
break;
case LYX_META_HFILL:
fprintf(file, "\n\\hfill \n");
column = 0;
break;
case LYX_META_PROTECTED_SEPARATOR:
fprintf(file, "\n\\protected_separator \n");
column = 0;
break;
case '\\':
fprintf(file, "\n\\backslash \n");
column = 0;
break;
case '.':
if (i + 1 < last && GetChar(i + 1) == ' ') {
fprintf(file, ".\n");
column = 0;
} else
fprintf(file, ".");
break;
default:
if ((column > 70 && c==' ')
|| column > 79){
fprintf(file, "\n");
column = 0;
}
// this check is to amend a bug. LyX sometimes
// inserts '\0' this could cause problems.
if (c != '\0')
fprintf(file, "%c", c);
else
lyxerr.print("ERROR (LyXParagraph::writeFile):"
" NULL char in structure.");
column++;
break;
}
}
// now write the next paragraph
if (next)
next->writeFile(file, params, footflag, dth);
}
void LyXParagraph::validate(LaTeXFeatures &features)
{
// this will be useful later
LyXLayout *layout = lyxstyle.Style(GetCurrentTextClass(),
GetLayout());
// check the params.
if (line_top || line_bottom)
features.lyxline = true;
// then the layouts
features.layout[GetLayout()] = true;
// then the fonts
FontTable *tmpfonttable = fonttable;
while (tmpfonttable) {
if (tmpfonttable->font.noun() == LyXFont::ON) {
lyxerr.debug(LString("font.noun: ")
+ int(tmpfonttable->font.noun()),
Error::LATEX);
features.noun = true;
lyxerr.debug("Noun enabled. Font: "
+tmpfonttable->font.stateText(),
Error::LATEX);
}
switch (tmpfonttable->font.color()) {
case LyXFont::NONE:
case LyXFont::INHERIT_COLOR:
case LyXFont::IGNORE_COLOR:
break;
default:
features.color = true;
lyxerr.debug("Color enabled. Font: "
+tmpfonttable->font.stateText(),
Error::LATEX);
}
tmpfonttable = tmpfonttable->next;
}
// then the insets
InsetTable *tmpinsettable = insettable;
while (tmpinsettable) {
if (tmpinsettable->inset) {
tmpinsettable->inset->Validate(features);
}
tmpinsettable = tmpinsettable->next;
}
if (table && table->IsLongTable())
features.longtable = true;
if (pextra_type == PEXTRA_INDENT)
features.LyXParagraphIndent = true;
if (pextra_type == PEXTRA_FLOATFLT)
features.floatflt = true;
if (layout->needprotect
&& next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
features.NeedLyXFootnoteCode = true;
if ((current_view->currentBuffer()->params.paragraph_separation == LYX_PARSEP_INDENT) &&
(pextra_type == PEXTRA_MINIPAGE))
features.NeedLyXMinipageIndent = true;
if (table && table->NeedRotating())
features.rotating = true;
}
/* first few functions needed for cut and paste and paragraph breaking */
void LyXParagraph::CopyIntoMinibuffer(int pos)
{
minibuffer_char = GetChar(pos);
minibuffer_font = GetFontSettings(pos);
if (minibuffer_char == LYX_META_INSET) {
if (GetInset(pos)) {
minibuffer_inset = GetInset(pos)->Clone();
} else {
minibuffer_inset = NULL;
minibuffer_char = ' ';
// This reflects what GetInset() does (ARRae)
}
}
}
void LyXParagraph::CutIntoMinibuffer(int pos)
{
minibuffer_char = GetChar(pos);
minibuffer_font = GetFontSettings(pos);
if (minibuffer_char == LYX_META_INSET) {
if (GetInset(pos)) {
minibuffer_inset = GetInset(pos);
} else {
minibuffer_inset = NULL;
minibuffer_char = ' ';
// This reflects what GetInset() does (ARRae)
}
/* this is a little hack since I want exactly the inset,
not just a clone. Otherwise the inset would be deleted
when calling Erase(pos) */
/* and it's only useful inside the if{} above
since the else{} means its not there (ARRae) */
/* find the entry */
InsetTable *tmpi = insettable;
while (tmpi && tmpi->pos != pos) {
tmpi=tmpi->next;
}
if (tmpi) { /* this should always be true */
tmpi->inset = NULL;
}
}
/* Erase(pos); now the caller is responsible for that*/
}
void LyXParagraph::InsertFromMinibuffer(int pos)
{
InsertChar(pos, minibuffer_char);
SetFont(pos, minibuffer_font);
if (minibuffer_char == LYX_META_INSET)
InsertInset(pos, minibuffer_inset);
}
/* end of minibuffer */
void LyXParagraph::Clear()
{
line_top = false;
line_bottom = false;
pagebreak_top = false;
pagebreak_bottom = false;
added_space_top = VSpace::NONE;
added_space_bottom = VSpace::NONE;
align = LYX_ALIGN_LAYOUT;
depth = 0;
noindent = false;
pextra_type = PEXTRA_NONE;
pextra_width.erase();
pextra_widthp.erase();
pextra_alignment = MINIPAGE_ALIGN_TOP;
pextra_hfill = false;
pextra_start_minipage = false;
labelstring.erase();
labelwidthstring.erase();
layout = 0;
}
/* the destructor removes the new paragraph from the list */
LyXParagraph::~LyXParagraph()
{
if (previous)
previous->next = next;
if (next)
next->previous = previous;
if (text)
delete[] text;
InsetTable *tmpinset;
while (insettable) {
tmpinset = insettable;
insettable = insettable->next;
if (tmpinset->inset)
delete tmpinset->inset;
delete tmpinset;
if (insettable && insettable->next == insettable) {
// somehow this recursion appears occasionally
// but I can't find where. This bandaid
// helps but isn't the best fix. (ARRae)
if (insettable->inset) {
delete insettable->inset;
}
delete insettable;
break;
}
}
FontTable *tmpfont;
while (fonttable) {
tmpfont = fonttable;
fonttable = fonttable->next;
delete tmpfont;
}
/* table stuff -- begin*/
if (table)
delete table;
/* table stuff -- end*/
// ale970302
if (bibkey)
delete bibkey;
}
void LyXParagraph::Erase(int pos)
{
int i;
/* > because last is the next unused position, and you can
* use it if you want */
if (pos > last) {
if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
NextAfterFootnote()->Erase(pos - last - 1);
else
lyxerr.print("ERROR (LyXParagraph::Erase): position does not exist.");
return;
}
if (pos < last) { // last is free for insertation, but should be empty
/* if it is an inset, delete the inset entry */
if (text[pos] == LYX_META_INSET) {
/* find the entry */
InsetTable *tmpi = insettable;
InsetTable *tmpi2 = tmpi;
while (tmpi && tmpi->pos != pos) {
tmpi2=tmpi;
tmpi=tmpi->next;
}
if (tmpi) { // this should always be true
if (tmpi->inset) // delete the inset if it exists
delete tmpi->inset;
if (tmpi == insettable)
insettable = tmpi->next;
else
tmpi2->next = tmpi->next;
delete tmpi;
}
}
// Shift rest of text
for (i = pos; i < last - 1; i++) {
text[i]=text[i+1];
}
last--;
/* erase entries in the tables */
int found = 0;
FontTable *tmp = fonttable;
FontTable *prev = NULL;
while (tmp && !found) {
if (pos >= tmp->pos && pos <= tmp->pos_end)
found = 1;
else {
prev = tmp;
tmp = tmp->next;
}
}
if (found && tmp->pos == tmp->pos_end) {
/* if it is a multi-character font entry, we just make
* it smaller (see update below), otherwise we should
* delete it */
if (prev)
prev->next = tmp->next;
else
fonttable = tmp->next;
delete tmp;
}
/* update all other entries */
tmp = fonttable;
while (tmp) {
if (tmp->pos > pos)
tmp->pos--;
if (tmp->pos_end >= pos)
tmp->pos_end--;
tmp = tmp->next;
}
/* update the inset table */
InsetTable *tmpi = insettable;
while (tmpi) {
if (tmpi->pos > pos)
tmpi->pos--;
tmpi=tmpi->next;
}
} else {
lyxerr.print("ERROR (LyXParagraph::Erase): can't erase non-existant char.");
}
}
/* pos is needed to specify the paragraph correctly. Remember the
* closed footnotes */
void LyXParagraph::Enlarge(int pos, int number)
{
int i;
/* > because last is the next unused position, and you can
* use it if you want */
if (pos > last) {
if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
NextAfterFootnote()->Enlarge(pos - last - 1, number);
else
lyxerr.print("ERROR (LyXParagraph::Enlarge): position does not exist.");
return;
}
if (size - last < number) {
size += number - size + last + STEP_SIZE_PAR;
char *tmp = new char[size];
for (i = 0; i < last; i++)
tmp[i] = text[i];
delete[] text;
text = tmp;
}
}
/* make the allocated memory fit to the needed size */
/* used to make a paragraph smaller */
void LyXParagraph::FitSize()
{
int i;
if (size - last > STEP_SIZE_PAR) {
size = last + STEP_SIZE_PAR;
char *tmp = new char[size];
for (i = 0; i < last; i++)
tmp[i] = text[i];
delete[] text;
text = tmp;
}
}
void LyXParagraph::InsertChar(int pos, char c)
{
register int i;
/* > because last is the next unused position, and you can
* use it if you want */
if (pos > last) {
if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
NextAfterFootnote()->InsertChar(pos - last - 1, c);
else
lyxerr.debug("ERROR (LyXParagraph::InsertChar): "
"position does not exist.");
return;
}
// Are we full? If so, enlarge.
if (last == size) {
size += STEP_SIZE_PAR;
char *tmp = new char[size];
for (i = 0; i < last; i++)
tmp[i] = text[i];
delete[] text;
text = tmp;
}
// Shift rest of character
for (i = last; i>pos; i--) {
text[i]=text[i-1];
}
text[pos]=c;
last++;
/* update the font table */
FontTable *tmp = fonttable;
while (tmp) {
if (tmp->pos >= pos)
tmp->pos++;
if (tmp->pos_end >= pos)
tmp->pos_end++;
tmp = tmp->next;
}
/* update the inset table */
InsetTable *tmpi = insettable;
while (tmpi) {
if (tmpi->pos >= pos)
tmpi->pos++;
tmpi=tmpi->next;
}
}
void LyXParagraph::InsertInset(int pos, Inset *inset)
{
/* > because last is the next unused position, and you can
* use it if you want */
if (pos > last) {
if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
NextAfterFootnote()->InsertInset(pos - last - 1, inset);
else
lyxerr.print("ERROR (LyXParagraph::InsertInset): "
"position does not exist: " + pos);
return;
}
if (text[pos]!=LYX_META_INSET) {
lyxerr.print("ERROR (LyXParagraph::InsertInset): "
"there is no LYX_META_INSET");
return;
}
if (inset) {
/* add a new entry in the inset table */
InsetTable *tmpi = new InsetTable;
tmpi->pos = pos;
tmpi->inset = inset;
tmpi->next = insettable;
insettable = tmpi;
}
}
Inset* LyXParagraph::GetInset(int pos)
{
if (pos >= last) {
if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
return NextAfterFootnote()->GetInset(pos - last - 1);
else {
lyxerr.print(LString("ERROR (LyXParagraph::GetInset): position does not exist: ") + pos);
}
return NULL;
}
/* find the inset */
InsetTable *tmpi = insettable;
while (tmpi && tmpi->pos != pos)
tmpi = tmpi->next;
if (tmpi)
return tmpi->inset;
else {
lyxerr.print(LString("ERROR (LyXParagraph::GetInset): "
"Inset does not exist: ") + pos);
text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
// Did this commenting out introduce a bug? So far I have not
// seen any, please enlighten me. (Lgb)
// My guess is that since the inset does not exist, we might
// as well replace it with a space to prevent crashes. (Asger)
return NULL;
}
}
// Gets uninstantiated font setting at position.
// Optimized after profiling. (Asger)
LyXFont LyXParagraph::GetFontSettings(int pos)
{
if (pos < last) {
FontTable *tmp = fonttable;
while (tmp) {
if (pos >= tmp->pos && pos <= tmp->pos_end)
return tmp->font;
tmp = tmp->next;
}
}
/* > because last is the next unused position, and you can
* use it if you want */
else if (pos > last) {
if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
return NextAfterFootnote()->GetFontSettings(pos - last - 1);
else {
// Why is it an error to ask for the font of a
// position that does not exist? Would it be
// enough for this to be anable on debug?
// We want strict error checking, but it's ok to only
// have it when debugging. (Asger)
lyxerr.print(
LString("ERROR (LyXParagraph::GetFontSettings): "
"position does not exist. ") + pos);
}
} else if (pos) {
return GetFontSettings(pos - 1);
}
return LyXFont(LyXFont::ALL_INHERIT);
}
// Gets the fully instantiated font at a given position in a paragraph
// This is basically the same function as LyXText::GetFont() in text2.C.
// The difference is that this one is used for generating the LaTeX file,
// and thus cosmetic "improvements" are disallowed: This has to deliver
// the true picture of the buffer. (Asger)
// If position is -1, we get the layout font of the paragraph.
// If position is -2, we get the font of the manual label of the paragraph.
LyXFont LyXParagraph::getFont(int pos)
{
LyXFont tmpfont;
LyXLayout *layout = lyxstyle.Style(GetCurrentTextClass(),
GetLayout());
int main_body=0;
if (layout->labeltype == LABEL_MANUAL)
main_body = BeginningOfMainBody();
if (pos >= 0){
LyXFont layoutfont;
if (pos < main_body)
layoutfont = layout->labelfont;
else
layoutfont = layout->font;
tmpfont = GetFontSettings(pos);
tmpfont.realize(layoutfont);
} else {
// process layoutfont for pos == -1 and labelfont for pos < -1
if (pos == -1)
tmpfont = layout->font;
else
tmpfont = layout->labelfont;
}
// check for environment font information
char par_depth = GetDepth();
LyXParagraph * par = this;
while (par && par_depth && !tmpfont.resolved()) {
par = par->DepthHook(par_depth - 1);
if (par) {
tmpfont.realize(lyxstyle.
Style(GetCurrentTextClass(),
par->GetLayout())->font);
par_depth = par->GetDepth();
}
}
tmpfont.realize(lyxstyle.TextClass(GetCurrentTextClass())->defaultfont);
return tmpfont;
}
/// Returns the height of the highest font in range
LyXFont::FONT_SIZE LyXParagraph::HighestFontInRange(int startpos, int endpos) const
{
LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
FontTable *tmp = fonttable;
while (tmp) {
if (startpos <= tmp->pos_end && endpos >= tmp->pos) {
LyXFont::FONT_SIZE size = tmp->font.size();
if (size > maxsize && size<=LyXFont::SIZE_HUGER)
maxsize = size;
}
tmp = tmp->next;
}
return maxsize;
}
char LyXParagraph::GetChar(int pos)
{
#ifdef DEVEL_VERSION
/* a workaround to 'fix' some bugs in text-class */
if (pos < 0) {
// This function is important. It should not work around bugs.
// Let's find the bugs instead and fix them. (Asger)
lyxerr.print(LString("FATAL ERROR (LyXParagraph::GetChar):"
" bad position ") + pos);
abort();
}
#endif
if (pos < last) {
return text[pos];
}
/* > because last is the next unused position, and you can
* use it if you want */
else if (pos > last) {
if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
return NextAfterFootnote()->GetChar(pos - last - 1);
else
lyxerr.print("ERROR (LyXParagraph::GetChar): "
"position does not exist.");
return 'F';
} else { // pos==last
/* we should have a footnote environment */
if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
// Notice that LyX does request the last char from time to time. (Asger)
// lyxerr.print("ERROR (LyXParagraph::GetChar): "
// "expected footnote.");
return 'F';
}
switch (next->footnotekind) {
case LyXParagraph::FOOTNOTE:
return LYX_META_FOOTNOTE;
case LyXParagraph::MARGIN:
return LYX_META_MARGIN;
case LyXParagraph::FIG:
case LyXParagraph::WIDE_FIG:
return LYX_META_FIG;
case LyXParagraph::TAB:
case LyXParagraph::WIDE_TAB:
return LYX_META_TAB;
case LyXParagraph::ALGORITHM:
return LYX_META_ALGORITHM;
}
// if (next->footnotekind == LyXParagraph::FOOTNOTE)
// return LYX_META_FOOTNOTE;
// if (next->footnotekind == LyXParagraph::MARGIN)
// return LYX_META_MARGIN;
// if (next->footnotekind == LyXParagraph::FIG)
// return LYX_META_FIG;
// if (next->footnotekind == LyXParagraph::TAB)
// return LYX_META_TAB;
// if (next->footnotekind == LyXParagraph::ALGORITHM)
// return LYX_META_ALGORITHM;
// lyxerr.print("ERROR (LyXParagraph::GetChar): "
// "unknown footnote kind.");
// return 'F'; /* this should not happen! */
// This _can_ not happen, due to the type of next->footnotekind
// being LyXParagraph::footnot_kind
return 'F'; // to shut up gcc
}
}
int LyXParagraph::Last()
{
if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
return last + NextAfterFootnote()->Last() + 1; /* the 1 is the symbol
* for the footnote */
else
return last;
}
LyXParagraph *LyXParagraph::ParFromPos(int pos)
{
/* > because last is the next unused position, and you can
* use it if you want */
if (pos > last) {
if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
return NextAfterFootnote()->ParFromPos(pos - last - 1);
else
lyxerr.print("ERROR (LyXParagraph::ParFromPos): "
"position does not exist.");
return this;
}
else
return this;
}
int LyXParagraph::PositionInParFromPos(int pos)
{
/* > because last is the next unused position, and you can
* use it if you want */
if (pos > last) {
if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
return NextAfterFootnote()->PositionInParFromPos(pos - last - 1);
else
lyxerr.print(
"ERROR (LyXParagraph::PositionInParFromPos): "
"position does not exist.");
return pos;
}
else
return pos;
}
void LyXParagraph::SetFont(int pos, LyXFont const & font)
{
/* > because last is the next unused position, and you can
* use it if you want */
if (pos > last) {
if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
NextAfterFootnote()->SetFont(pos - last - 1, font);
} else {
lyxerr.print("ERROR (LyXParagraph::SetFont): "
"position does not exist.");
}
return;
}
LyXFont patternfont(LyXFont::ALL_INHERIT);
// First, reduce font against layout/label font
// Update: The SetCharFont() routine in text2.C already reduces font, so
// we don't need to do that here. (Asger)
// No need to simplify this because it will disappear in a new kernel. (Asger)
// Next search font table
FontTable *tmp2;
bool found = false;
FontTable *tmp = fonttable;
while (tmp && !found) {
if (pos >= tmp->pos && pos <= tmp->pos_end)
found = true;
else
tmp = tmp->next;
}
if (!found) {
/* if we did not find a font entry, but if the font at hand
* is the same as default, we just forget it */
if (font == patternfont)
return;
/* ok, we did not find a font entry. But maybe there is exactly
* the needed font entry one position left */
found = false;
tmp2 = fonttable;
while (tmp2 && !found) {
if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
found = true;
else
tmp2 = tmp2->next;
}
if (found) {
/* ok there is one. maybe it is exactly the needed font */
if (tmp2->font == font) {
/* put the position under the font */
tmp2->pos_end++;
return;
}
}
/* Add a new entry in the
* fonttable for the position */
tmp = new FontTable;
tmp->pos = pos;
tmp->pos_end = pos;
tmp->font = patternfont;
tmp->next = fonttable;
fonttable = tmp;
}
else {
/* we found a font entry. maybe we have to split it and create
* a new one */
if (tmp->pos != tmp->pos_end) { /* more than one character */
if (pos == tmp->pos) {
/* maybe we could enlarge the left fonttable */
found = false;
tmp2 = fonttable;
while (tmp2 && !found) {
if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
found = true;
else
tmp2 = tmp2->next;
}
/* Is there is one, and is it exactly the needed font? */
if (found && tmp2->font == font) {
/* put the position under the font */
tmp2->pos_end++;
tmp->pos++;
return;
}
/* Add a new entry in the
* fonttable for the position */
tmp2 = new FontTable;
tmp2->pos = pos + 1;
tmp2->pos_end = tmp->pos_end;
tmp2->font = tmp->font;
tmp->pos_end = pos;
tmp2->next = fonttable;
fonttable = tmp2;
}
else if (pos == tmp->pos_end) {
/* Add a new entry in the
* fonttable for the position */
tmp2 = new FontTable;
tmp2->pos = tmp->pos;
tmp2->pos_end = tmp->pos_end - 1;
tmp2->font = tmp->font;
tmp->pos = tmp->pos_end;
tmp2->next = fonttable;
fonttable = tmp2;
}
else {
/* Add a new entry in the
* fonttable for the position */
tmp2 = new FontTable;
tmp2->pos = tmp->pos;
tmp2->pos_end = pos - 1;
tmp2->font = tmp->font;
tmp2->next = fonttable;
fonttable = tmp2;
tmp2 = new FontTable;
tmp2->pos = pos + 1;
tmp2->pos_end = tmp->pos_end;
tmp2->font = tmp->font;
tmp2->next = fonttable;
fonttable = tmp2;
tmp->pos = pos;
tmp->pos_end = pos;
}
}
}
tmp->font = font;
}
/* this function is able to hide closed footnotes */
LyXParagraph *LyXParagraph::Next()
{
LyXParagraph *tmp;
if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
tmp = next;
while (tmp && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
tmp = tmp->next;
if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
return tmp->Next(); /* there can be more than one footnote
* in a logical paragraph */
else
return next; /* this should never happen! */
}
else
return next;
}
LyXParagraph *LyXParagraph::NextAfterFootnote()
{
LyXParagraph *tmp;
if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
tmp = next;
while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
tmp = tmp->next;
if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
return tmp; /* there can be more than one footnote
* in a logical paragraph */
else
return next; /* this should never happen! */
}
else
return next;
}
LyXParagraph *LyXParagraph::PreviousBeforeFootnote()
{
LyXParagraph *tmp;
if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
tmp = next;
while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
tmp = tmp->previous;
if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
return tmp; /* there can be more than one footnote
* in a logical paragraph */
else
return previous; /* this should never happen! */
}
else
return previous;
}
LyXParagraph *LyXParagraph::LastPhysicalPar()
{
LyXParagraph *tmp;
if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
return this;
tmp = this;
while (tmp->next && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
tmp = tmp->NextAfterFootnote();
return tmp;
}
LyXParagraph *LyXParagraph::FirstPhysicalPar()
{
if (!IsDummy())
return this;
LyXParagraph *tmppar = this;
while (tmppar && (tmppar->IsDummy()
|| tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
tmppar = tmppar->previous;
if (!tmppar)
return this; /* this should never happen! */
else
return tmppar;
}
/* this function is able to hide closed footnotes */
LyXParagraph *LyXParagraph::Previous()
{
LyXParagraph *tmp = previous;
if (!tmp)
return tmp;
if (tmp->previous && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
tmp = tmp->previous;
while (tmp && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
tmp = tmp->previous;
if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
return tmp->next->Previous();
else
return previous;
}
else
return previous;
}
void LyXParagraph::BreakParagraph(int pos, int flag)
{
int i, pos_end, pos_first;
/* create a new paragraph */
LyXParagraph *par = ParFromPos(pos);
LyXParagraph *firstpar = FirstPhysicalPar();
LyXParagraph *tmp = new LyXParagraph(par);
tmp->footnoteflag = footnoteflag;
tmp->footnotekind = footnotekind;
/* this is an idea for a more userfriendly layout handling, I will
* see what the users say */
/* layout stays the same with latex-environments */
if (flag) {
tmp->SetOnlyLayout(firstpar->layout);
tmp->SetLabelWidthString(firstpar->labelwidthstring);
}
if (Last() > pos || !Last() || flag == 2) {
tmp->SetOnlyLayout(firstpar->layout);
tmp->align = firstpar->align;
tmp->SetLabelWidthString(firstpar->labelwidthstring);
tmp->line_bottom = firstpar->line_bottom;
firstpar->line_bottom = false;
tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
firstpar->pagebreak_bottom = false;
tmp->added_space_bottom = firstpar->added_space_bottom;
firstpar->added_space_bottom = VSpace::NONE;
tmp->depth = firstpar->depth;
tmp->noindent = firstpar->noindent;
/* copy everything behind the break-position to the new paragraph */
pos_first = 0;
while (ParFromPos(pos_first) != par)
pos_first++;
pos_end = pos_first + par->last - 1;
/* make sure there is enough memory for the now larger
paragraph. This is not neccessary, because
InsertFromMinibuffer will enlarge the memory (it uses
InsertChar of course). But doing it by hand
is MUCH faster! (only one time, not thousend times!!) */
tmp->Enlarge(0, pos_end - pos);
for (i = pos; i <= pos_end; i++) {
par->CutIntoMinibuffer(i - pos_first);
tmp->InsertFromMinibuffer(i - pos);
}
for (i = pos_end; i >= pos; i--)
par->Erase(i - pos_first);
/* free memory of the now shorter paragraph*/
par->FitSize();
}
/* just an idea of me */
if (!pos) {
tmp->line_top = firstpar->line_top;
tmp->pagebreak_top = firstpar->pagebreak_top;
tmp->added_space_top = firstpar->added_space_top;
firstpar->Clear();
/* layout stays the same with latex-environments */
if (flag) {
firstpar->SetOnlyLayout(tmp->layout);
firstpar->SetLabelWidthString(tmp->labelwidthstring);
firstpar->depth = tmp->depth;
}
}
}
void LyXParagraph::MakeSameLayout(LyXParagraph *par)
{
par = par->FirstPhysicalPar();
footnoteflag = par->footnoteflag;
footnotekind = par->footnotekind;
layout = par->layout;
align = par-> align;
SetLabelWidthString(par->labelwidthstring);
line_bottom = par->line_bottom;
pagebreak_bottom = par->pagebreak_bottom;
added_space_bottom = par->added_space_bottom;
line_top = par->line_top;
pagebreak_top = par->pagebreak_top;
added_space_top = par->added_space_top;
pextra_type = par->pextra_type;
pextra_width = par->pextra_width;
pextra_widthp = par->pextra_widthp;
pextra_alignment = par->pextra_alignment;
pextra_hfill = par->pextra_hfill;
pextra_start_minipage = par->pextra_start_minipage;
noindent = par->noindent;
depth = par->depth;
}
LyXParagraph *LyXParagraph::FirstSelfrowPar()
{
LyXParagraph *tmppar;
tmppar = this;
while (tmppar && (
(tmppar->IsDummy() && tmppar->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
|| tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
tmppar = tmppar->previous;
if (!tmppar)
return this; /* this should never happen! */
else
return tmppar;
}
LyXParagraph *LyXParagraph::Clone()
{
int i;
/* create a new paragraph */
LyXParagraph *result = new LyXParagraph();
result->MakeSameLayout(this);
/* this is because of the dummy layout of the paragraphs that
follow footnotes */
result->layout = layout;
/* table stuff -- begin*/
if (table)
result->table = table->Clone();
else
result->table = NULL;
/* table stuff -- end*/
// ale970302
result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
/* copy everything behind the break-position to the new paragraph */
/* make shure there is enough memory for the now larger paragraph.
* This is not neccessary, because InsertFromMinibuffer will enlarge
* the memory (it uses InsertChar of course). But doing it by hand
* is MUCH faster! (only one time, not thousend times!!) */
result->Enlarge(0, last+2);
for (i = 0; i < last; i++) {
CopyIntoMinibuffer(i);
result->InsertFromMinibuffer(i);
}
return result;
}
bool LyXParagraph::HasSameLayout(LyXParagraph* par)
{
par = par->FirstPhysicalPar();
return (
par->footnoteflag == footnoteflag &&
par->footnotekind == footnotekind &&
par->layout == layout &&
par->align == align &&
par->line_bottom == line_bottom &&
par->pagebreak_bottom == pagebreak_bottom &&
par->added_space_bottom == added_space_bottom &&
par->line_top == line_top &&
par->pagebreak_top == pagebreak_top &&
par->added_space_top == added_space_top &&
par->pextra_type == pextra_type &&
par->pextra_width == pextra_width &&
par->pextra_widthp == pextra_widthp &&
par->pextra_alignment == pextra_alignment &&
par->pextra_hfill == pextra_hfill &&
par->pextra_start_minipage == pextra_start_minipage &&
par->table == table && // what means: NO TABLE AT ALL
par->noindent == noindent &&
par->depth == depth);
}
void LyXParagraph::BreakParagraphConservative(int pos)
{
int i, pos_end, pos_first;
/* create a new paragraph */
LyXParagraph *par = ParFromPos(pos);
LyXParagraph *tmp = new LyXParagraph(par);
tmp->MakeSameLayout(par);
if (Last() > pos) {
/* copy everything behind the break-position to the new
paragraph */
pos_first = 0;
while (ParFromPos(pos_first) != par)
pos_first++;
pos_end = pos_first + par->last - 1;
/* make shure there is enough memory for the now larger
paragraph. This is not neccessary, because
InsertFromMinibuffer will enlarge the memory (it uses
InsertChar of course). But doing it by hand
is MUCH faster! (only one time, not thousend times!!) */
tmp->Enlarge(0, pos_end - pos);
for (i = pos; i <= pos_end; i++) {
par->CutIntoMinibuffer(i - pos_first);
tmp->InsertFromMinibuffer(i - pos);
}
for (i = pos_end; i >= pos; i--)
par->Erase(i - pos_first);
/* free memory of the now shorter paragraph*/
par->FitSize();
}
}
/* be carefull, this does not make any check at all */
void LyXParagraph::PasteParagraph()
{
int i, pos_end, pos_insert;
LyXParagraph *the_next;
/* copy the next paragraph to this one */
the_next = Next();
LyXParagraph *firstpar = FirstPhysicalPar();
/* first the DTP-stuff */
firstpar->line_bottom = the_next->line_bottom;
firstpar->added_space_bottom = the_next->added_space_bottom;
firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
pos_end = the_next->last - 1;
pos_insert = Last();
/* enlarge the paragraph. This is faster than enlarge it
* every 10th insertion. */
if (pos_end >= 0)
Enlarge(pos_insert, pos_end);
/* ok, now copy the paragraph */
for (i = 0; i <= pos_end; i++) {
the_next->CutIntoMinibuffer(i);
InsertFromMinibuffer(pos_insert + i);
}
/* delete the next paragraph */
delete the_next;
}
void LyXParagraph::OpenFootnote(int pos)
{
LyXParagraph *par = ParFromPos(pos);
par = par->next;
while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
par = par->next;
}
}
void LyXParagraph::CloseFootnote(int pos)
{
LyXParagraph *par = ParFromPos(pos);
par = par->next;
while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
par = par->next;
}
}
int LyXParagraph::GetLayout()
{
return FirstPhysicalPar()->layout;
}
char LyXParagraph::GetDepth()
{
return FirstPhysicalPar()->depth;
}
char LyXParagraph::GetAlign()
{
return FirstPhysicalPar()->align;
}
LString LyXParagraph::GetLabelString()
{
return FirstPhysicalPar()->labelstring;
}
unsigned char LyXParagraph::GetCounter(int i)
{
return FirstPhysicalPar()->counter[i];
}
/* the next two functions are for the manual labels */
LString LyXParagraph::GetLabelWidthString()
{
if (!FirstPhysicalPar()->labelwidthstring.empty())
return FirstPhysicalPar()->labelwidthstring;
else
return _("Senseless with this layout!");
}
void LyXParagraph::SetLabelWidthString(LString const & s)
{
LyXParagraph *par = FirstPhysicalPar();
par->labelwidthstring = s;
}
void LyXParagraph::SetOnlyLayout(char new_layout)
{
LyXParagraph
*par = FirstPhysicalPar(),
*ppar = NULL,
*npar = NULL;
par->layout = new_layout;
/* table stuff -- begin*/
if (table)
par->layout = 0;
/* table stuff -- end*/
if (par->pextra_type == PEXTRA_NONE) {
if (par->Previous()) {
ppar = par->Previous()->FirstPhysicalPar();
while(ppar
&& ppar->Previous()
&& (ppar->depth > par->depth))
ppar = ppar->Previous()->FirstPhysicalPar();
}
if (par->Next()) {
npar = par->Next()->NextAfterFootnote();
while(npar
&& npar->Next()
&& (npar->depth > par->depth))
npar = npar->Next()->NextAfterFootnote();
}
if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
LString
p1 = ppar->pextra_width,
p2 = ppar->pextra_widthp;
ppar->SetPExtraType(ppar->pextra_type,
p1.c_str(),p2.c_str());
}
if ((par->pextra_type == PEXTRA_NONE) &&
npar && (npar->pextra_type != PEXTRA_NONE)) {
LString
p1 = npar->pextra_width,
p2 = npar->pextra_widthp;
npar->SetPExtraType(npar->pextra_type,
p1.c_str(),p2.c_str());
}
}
}
void LyXParagraph::SetLayout(char new_layout)
{
LyXParagraph
*par = FirstPhysicalPar(),
*ppar = NULL,
*npar = NULL;
par->layout = new_layout;
par->labelwidthstring.erase();
par->align = LYX_ALIGN_LAYOUT;
//par->depth = 0;
par->added_space_top = VSpace::NONE;
par->added_space_bottom = VSpace::NONE;
/* table stuff -- begin*/
if (table)
par->layout = 0;
/* table stuff -- end*/
if (par->pextra_type == PEXTRA_NONE) {
if (par->Previous()) {
ppar = par->Previous()->FirstPhysicalPar();
while(ppar
&& ppar->Previous()
&& (ppar->depth > par->depth))
ppar = ppar->Previous()->FirstPhysicalPar();
}
if (par->Next()) {
npar = par->Next()->NextAfterFootnote();
while(npar
&& npar->Next()
&& (npar->depth > par->depth))
npar = npar->Next()->NextAfterFootnote();
}
if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
LString
p1 = ppar->pextra_width,
p2 = ppar->pextra_widthp;
ppar->SetPExtraType(ppar->pextra_type,
p1.c_str(),p2.c_str());
}
if ((par->pextra_type == PEXTRA_NONE) &&
npar && (npar->pextra_type != PEXTRA_NONE)) {
LString
p1 = npar->pextra_width,
p2 = npar->pextra_widthp;
npar->SetPExtraType(npar->pextra_type,
p1.c_str(),p2.c_str());
}
}
}
/* if the layout of a paragraph contains a manual label, the beginning of the
* main body is the beginning of the second word. This is what the par-
* function returns. If the layout does not contain a label, the main
* body always starts with position 0. This differentiation is necessary,
* because there cannot be a newline or a blank <= the beginning of the
* main body in TeX. */
int LyXParagraph::BeginningOfMainBody()
{
if (FirstPhysicalPar() != this)
return -1;
int i = 0;
// while (i < last && !(i > 1 && GetChar(i-1)==' ')
// && GetChar(i)!=LYX_META_NEWLINE)
// i++;
// Unroll the first two cycles of this loop
// and remember the previous character to remove unnecessary GetChar() calls
if (i < last
&& GetChar(i) != LYX_META_NEWLINE) {
++i;
char previous_char, temp;
if (i < last
&& (previous_char = GetChar(i)) != LYX_META_NEWLINE) {
// Yes, this ^ is supposed to be "=" not "=="
++i;
while (i < last
&& previous_char != ' '
&& (temp = GetChar(i)) != LYX_META_NEWLINE) {
++i;
previous_char = temp;
}
}
}
if (i==0 && i == last &&
!(footnoteflag==LyXParagraph::NO_FOOTNOTE
&& next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
)
i++; /* the cursor should not jump
* to the main body if there
* is nothing in! */
return i;
}
LyXParagraph* LyXParagraph::DepthHook(int deth)
{
LyXParagraph *newpar = this;
if (deth < 0)
return NULL;
do {
newpar = newpar->FirstPhysicalPar()->Previous();
} while (newpar && newpar->GetDepth() > deth
&& newpar->footnoteflag == footnoteflag);
if (!newpar) {
if (Previous() || GetDepth())
lyxerr.print("ERROR (LyXParagraph::DepthHook): "
"no hook.");
newpar = this;
}
return newpar->FirstPhysicalPar();
}
int LyXParagraph::AutoDeleteInsets()
{
InsetTable *tmpi = insettable;
InsetTable *tmpi2 = tmpi;
int i=0;
while (tmpi) {
tmpi2 = tmpi;
tmpi = tmpi->next;
if (tmpi2->inset)
if (tmpi2->inset->AutoDelete()) {
i++;
Erase(tmpi2->pos);
} else {}
else
lyxerr.print(
"ERROR (LyXParagraph::AutoDeleteInsets): "
"cannot auto-delete insets");
}
return i;
}
Inset* LyXParagraph::ReturnNextInsetPointer(int &pos)
{
InsetTable *tmpi = insettable;
InsetTable *tmpi2 = NULL;
while (tmpi){
if (tmpi->pos >= pos) {
if (!tmpi2 || tmpi->pos < tmpi2->pos)
tmpi2 = tmpi;
}
tmpi=tmpi->next;
}
if (tmpi2){
pos = tmpi2->pos;
return tmpi2->inset;
}
else
return NULL;
}
/* returns -1 if inset not found */
int LyXParagraph::GetPositionOfInset(Inset* inset)
{
/* find the entry */
InsetTable *tmpi = insettable;
while (tmpi && tmpi->inset != inset) {
tmpi=tmpi->next;
}
if (tmpi && tmpi->inset)
return tmpi->pos;
else{
/* think about footnotes */
if (footnoteflag == LyXParagraph::NO_FOOTNOTE
&& next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
int further =
NextAfterFootnote()->GetPositionOfInset(inset);
if (further != -1)
return last + 1 + further;
}
return -1;
}
}
void LyXParagraph::readSimpleWholeFile(FILE *myfile)
{
char c;
FileInfo fileInfo(fileno(myfile));
long file_size = fileInfo.getSize();
/* it is horrible, I know, but faster.
* I should not use InsertString for that :-( */
/* I will write a better insertion in the future */
Enlarge(0, file_size + 10);
rewind(myfile);
if (!feof(myfile)) {
do {
c = fgetc(myfile);
InsertChar(last,c);
} while (!feof(myfile));
}
}
LyXParagraph* LyXParagraph::TeXOnePar(LString &file, TexRow &texrow,
LString &foot, TexRow &foot_texrow,
int &foot_count)
{
lyxerr.debug(LString("TeXOnePar... ") + (long)this, Error::LATEX);
LyXParagraph *par = next;
LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), layout);
bool further_blank_line = false;
if (IsDummy())
lyxerr.print("ERROR (LyXParagraph::TeXOnePar) is dummy.");
if (tex_code_break_column && style->isCommand()){
file += '\n';
texrow.newline();
}
if (pagebreak_top) {
file += "\\newpage";
further_blank_line = true;
}
if (added_space_top.kind() != VSpace::NONE) {
file += added_space_top.asLatexCommand();
further_blank_line = true;
}
if (line_top) {
file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
file += "\\vspace{-1\\parskip}";
further_blank_line = true;
}
if (further_blank_line){
file += '\n';
texrow.newline();
}
switch (style->latextype) {
case LATEX_COMMAND:
//arrae970411
if (style->latexparam.empty()) {
file += '\\';
file += style->latexname;
} else {
file += '\\';
file += style->latexname;
file += '[';
file += style->latexparam;
file += ']';
}
break;
case LATEX_ITEM_ENVIRONMENT:
if (bibkey)
bibkey->Latex(file, false);
else
file += "\\item ";
break;
case LATEX_LIST_ENVIRONMENT:
file += "\\item ";
break;
default:
break;
}
bool need_par = SimpleTeXOnePar(file, texrow);
// Spit out footnotes
while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
&& par->footnoteflag != footnoteflag) {
par = par->TeXFootnote(file, texrow,
foot, foot_texrow, foot_count);
par->SimpleTeXOnePar(file, texrow);
par = par->next;
}
// Make sure that \\par is done with the font of the last
// character if this has another size as the default.
// This is necessary because LaTeX (and LyX on the screen)
// calculates the space between the baselines according
// to this font. (Matthias)
LyXFont font = getFont(Last()-1);
if (need_par) {
if (style->resfont.size() != font.size()) {
file += '\\';
file += font.latexSize();
file += ' ';
}
file += "\\par}";
} else if (lyxstyle.Style(GetCurrentTextClass(),
GetLayout())->isCommand()){
if (style->resfont.size() != font.size()) {
file += '\\';
file += font.latexSize();
file += ' ';
}
file += '}';
} else if (style->resfont.size() != font.size()){
file += "{\\" + font.latexSize() + " \\par}";
}
switch (style->latextype) {
case LATEX_ITEM_ENVIRONMENT:
case LATEX_LIST_ENVIRONMENT:
if (par && (depth < par->depth)) {
file += '\n';
texrow.newline();
}
break;
case LATEX_ENVIRONMENT:
// if its the last paragraph of the current environment
// skip it otherwise fall through
if (par
&& !par->HasSameLayout(this)) {
break;
}
default:
file += '\n';
texrow.newline();
}
further_blank_line = false;
if (line_bottom) {
file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
further_blank_line = true;
}
if (added_space_bottom.kind() != VSpace::NONE) {
file += added_space_bottom.asLatexCommand();
further_blank_line = true;
}
if (pagebreak_bottom) {
file += "\\newpage";
further_blank_line = true;
}
if (further_blank_line){
file += '\n';
texrow.newline();
}
if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
par->footnoteflag == LyXParagraph::NO_FOOTNOTE) // &&
// (pextra_type != PEXTRA_MINIPAGE ||
/* (par && !par->pextra_type == PEXTRA_MINIPAGE)) */ ) {
file += '\n';
texrow.newline();
}
lyxerr.debug(LString("TeXOnePar...done ") + (long)par, Error::LATEX);
return par;
}
// This one spits out the text of the paragraph
bool LyXParagraph::SimpleTeXOnePar(LString &file, TexRow &texrow)
{
lyxerr.debug(LString("SimpleTeXOnePar... ")+(long)this, Error::LATEX);
if (table)
return SimpleTeXOneTablePar(file, texrow);
char c;
Inset *inset;
int main_body;
int column;
bool return_value = false;
//bool underbar = false;
LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
LyXFont basefont;
/* maybe we have to create a optional argument */
if (style->labeltype != LABEL_MANUAL)
main_body = 0;
else
main_body = BeginningOfMainBody();
if (main_body > 0) {
file += '[';
basefont = getFont(-2); // Get label font
} else
basefont = getFont(-1); // Get layout font
column = 0;
if (main_body >= 0 && !last && !IsDummy()){
if (style->isCommand()) {
file += '{';
column++;
} else if (align != LYX_ALIGN_LAYOUT) {
file += '{';
column++;
return_value = true;
}
}
// Which font is currently active?
LyXFont running_font = basefont;
// Do we have an open font change?
bool open_font = false;
texrow.start(this, 0);
for (int i = 0; i < last; i++) {
column++;
// First char in paragraph or after label?
if (i == main_body && !IsDummy()) {
if (main_body > 0) {
if (open_font) {
column += running_font.latexWriteEndChanges(file, basefont);
open_font = false;
}
basefont = getFont(-1); // Now use the layout font
running_font = basefont;
file += ']';
column++;
}
if (style->isCommand()) {
file += '{';
column++;
} else if (align != LYX_ALIGN_LAYOUT) {
file += '{';
column++;
return_value = true;
}
if (noindent) {
file += "\\noindent ";
column += 10;
}
switch (align) {
case LYX_ALIGN_LEFT:
file += "\\raggedright ";
column+=13;
break;
case LYX_ALIGN_RIGHT:
file += "\\raggedleft ";
column+=12;
break;
case LYX_ALIGN_CENTER:
file += "\\centering ";
column+=11;
break;
}
}
c = GetChar(i);
// Fully instantiated font
LyXFont font = getFont(i);
// Spaces at end of font change are simulated to be outside font change.
// i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
if (open_font && c == ' ' && i <= last-2
&& getFont(i+1) != running_font && getFont(i+1) != font) {
font = getFont(i+1);
}
// We end font definition before blanks
if (font != running_font && open_font) {
column += running_font.latexWriteEndChanges(file, basefont);
running_font = basefont;
open_font = false;
}
// Blanks are printed before start of fontswitch
if (c==' '){
// Do not print the separation of the optional argument
if (i != main_body - 1) {
if (column > tex_code_break_column
&& i && GetChar(i-1) != ' '
&& (i < last-1)
// In LaTeX mode, we don't want to
// break lines since some commands
// do not like this
&& font.latex() != LyXFont::ON
// same in FreeSpacing mode
&& !style->free_spacing
// In typewriter mode, we want to avoid
// ! . ? : at the end of a line
&& !(font.family() == LyXFont::TYPEWRITER_FAMILY
&& (GetChar(i-1) == '.'
|| GetChar(i-1) == '?'
|| GetChar(i-1) == ':'
|| GetChar(i-1) == '!'))) {
file += '\n';
texrow.newline();
texrow.start(this, i+1);
column = 0;
}
else if (font.latex() == LyXFont::OFF) {
if (font.family() == LyXFont::TYPEWRITER_FAMILY)
file += '~';
else
file += ' ';
}
}
}
// Do we need to change font?
if (font != running_font) {
column += font.latexWriteStartChanges(file, basefont);
running_font = font;
open_font = true;
}
// Do we need to turn on LaTeX mode?
if (font.latex() != running_font.latex()) {
if (font.latex() == LyXFont::ON
&& style->needprotect)
{
file += "\\protect ";
column += 9;
}
}
if (c == LYX_META_INSET) {
inset = GetInset(i);
if (inset) {
int len = file.length();
int tmp = inset->Latex(file, style->isCommand());
if (tmp)
column = 0;
else
column += file.length() - len;
//for (;tmp>0;tmp--)
for (;tmp--;)
texrow.newline();
}
} else {
// Are we in LaTeX mode?
if (font.latex() == LyXFont::ON) {
switch (c) {
case LYX_META_NEWLINE:
if (!style->newline_allowed)
file += '\n';
else {
if (open_font) {
column += running_font.latexWriteEndChanges(file, basefont);
open_font = false;
}
basefont = getFont(-1);
running_font = basefont;
file += "\\\\\n";
}
texrow.newline();
texrow.start(this, i+1);
column = 0;
break;
case LYX_META_HFILL:
file += "\\hfill{}";
column+=7;
break;
case LYX_META_PROTECTED_SEPARATOR:
file += '~';
break;
default:
// make sure that we will not print
// error generating chars to the tex
// file. This test would not be needed
// if it were done in the buffer
// itself.
if (c != '\0')
file += c;
break;
}
} else {
// Plain mode (i.e. not LaTeX)
switch (c) {
case LYX_META_NEWLINE:
if (!style->newline_allowed)
file += '\n';
else {
if (open_font) {
column += running_font.latexWriteEndChanges(file, basefont);
open_font = false;
}
basefont = getFont(-1);
running_font = basefont;
file += "\\\\\n";
}
texrow.newline();
texrow.start(this, i+1);
column = 0;
break;
case LYX_META_HFILL:
file += "\\hfill{}";
column+=7;
break;
case LYX_META_PROTECTED_SEPARATOR:
file += '~';
break;
case '\\':
if (lyxrc->fontenc=="T1"
|| font.family() == LyXFont::TYPEWRITER_FAMILY){
file += "\\char`\\\\{}";
column+=9;
}
else {
file += "\\ensuremath{\\backslash}";
column+=22;
}
break;
case '░': case '▒': case '▓': case '│':
case '╫': case '≈': case '╣': case '¬':
case '║': case '¼': case '╡':
if (current_view->currentBuffer()->params.inputenc == "latin1") {
file += "\\ensuremath{";
file += c;
file += '}';
column+=13;
} else
file += c;
break;
case '|': case '<': case '>':
if (lyxrc->fontenc=="T1") {
if ((c=='>' ||c=='<')
&& i <= last-2
&& GetChar(i+1)==c){
file += c;
file += "\\textcompwordmark{}";
column+=19;
} else
file += c;
} else if(font.family() == LyXFont::TYPEWRITER_FAMILY)
file += c;
else {
file +="\\ensuremath{";
file += c;
file += '}';
column+=13;
}
break;
case '-': // "--" in Typewriter mode -> "-{}-"
if (i <= last-2
&& GetChar(i+1) == '-'
&& font.family() == LyXFont::TYPEWRITER_FAMILY) {
file += "-{}";
column += 2;
} else
file += '-';
break;
case '\"':
file += "\\char`\\\"{}";
column+=9;
break;
case 'ú':
if (current_view->currentBuffer()->params.inputenc == "default") {
file += "\\pounds{}";
column+=8;
} else
file += c;
break;
case '$': case '&':
case '%': case '#': case '{':
case '}': case '_':
file += '\\';
file += c;
column +=1;
break;
case '^': case '~':
file += '\\';
file += c;
file += "{}";
column +=3;
break;
case '*': case '[': case ']':
// avoid being mistaken for optional arguments
file += '{';
file += c;
file += '}';
column +=2;
break;
case ' ':
/* blanks are printed before font switching */
// Sure? I am not! (try nice-latex)
// I am sure it's correct. LyX might be smarter
// in the future, but for now, nothing wrong is
// written. (Asger)
break;
default:
/* idea for labels --- begin*/
/* check for LyX */
if (c == 'L' && i <= last-3
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'y'
&& GetChar(i+2) == 'X'){
file += "\\LyX{}";
i+=2;
column += 5;
}
/* check for TeX */
else if (c == 'T' && i <= last-3
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'e'
&& GetChar(i+2) == 'X'){
file += "\\TeX{}";
i+=2;
column += 5;
}
/* check for LaTeX2e */
else if (c == 'L' && i <= last-7
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'a'
&& GetChar(i+2) == 'T'
&& GetChar(i+3) == 'e'
&& GetChar(i+4) == 'X'
&& GetChar(i+5) == '2'
&& GetChar(i+6) == 'e'){
file += "\\LaTeXe{}";
i+=6;
column += 8;
}
/* check for LaTeX */
else if (c == 'L' && i <= last-5
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'a'
&& GetChar(i+2) == 'T'
&& GetChar(i+3) == 'e'
&& GetChar(i+4) == 'X'){
file += "\\LaTeX{}";
i+=4;
column += 7;
}
else
/* idea for labels --- end*/
// same test as above
if (c != '\0')
file += c;
break;
}
}
}
}
// If we have an open font definition, we have to close it
if (open_font) {
running_font.latexWriteEndChanges(file, basefont);
}
/* needed if there is an optional argument but no contents */
if (main_body > 0 && main_body == last) {
file += "]~";
return_value = false;
}
lyxerr.debug(LString("SimpleTeXOnePar...done ") + (long)this, Error::LATEX);
return return_value;
}
// This one spits out the text of a table paragraph
bool LyXParagraph::SimpleTeXOneTablePar(LString &file, TexRow &texrow)
{
lyxerr.debug(LString("SimpleTeXOneTablePar... ")+(long)this, Error::LATEX);
char c;
Inset *inset;
int column, tmp;
bool return_value = false;
int current_cell_number = -1;
LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
LyXFont basefont;
basefont = getFont(-1); // Get layout font
// Which font is currently active?
LyXFont running_font = basefont;
// Do we have an open font change?
bool open_font = false;
column = 0;
#ifdef THIS_IS_WRONG
if (!last && !IsDummy()){
if (style->isCommand()) {
file += '{';
column++;
} else if (align != LYX_ALIGN_LAYOUT) {
file += '{';
column++;
return_value = true;
}
} else if (last && !IsDummy())
#else
if (!IsDummy())
#endif
{
if (style->isCommand()) {
file += '{';
column++;
} else if (align != LYX_ALIGN_LAYOUT) {
file += '{';
column++;
return_value = true;
}
if (noindent) {
file += "\\noindent ";
column += 10;
}
switch (align) {
case LYX_ALIGN_LEFT:
file += "\\raggedright ";
column+=13;
break;
case LYX_ALIGN_RIGHT:
file += "\\raggedleft ";
column+=12;
break;
case LYX_ALIGN_CENTER:
file += "\\centering ";
column+=11;
break;
}
current_cell_number = -1;
tmp = table->TexEndOfCell(file,current_cell_number);
for (;tmp>0;tmp--)
texrow.newline();
}
texrow.start(this, 0);
for (int i = 0; i < last; i++) {
c = GetChar(i);
if (table->IsContRow(current_cell_number+1)) {
if (c == LYX_META_NEWLINE)
current_cell_number++;
continue;
}
column++;
// Fully instantiated font
LyXFont font = getFont(i);
// We end font definition before blanks
if (font != running_font && open_font) {
column += running_font.latexWriteEndChanges(file, basefont);
running_font = basefont;
open_font = false;
}
// Blanks are printed before start of fontswitch
if (c==' '){
if (column > tex_code_break_column
&& i && GetChar(i-1) != ' '
&& (i < last-1) &&
// In LaTeX mode, we don't want to
// break lines since some commands
// do not like this
! (font.latex() == LyXFont::ON) &&
// In typewriter mode, we want to avoid
// ! . ? : at the end of a line
!(font.family() == LyXFont::TYPEWRITER_FAMILY &&
(GetChar(i-1) == '.' || GetChar(i-1) == '?' ||
GetChar(i-1) == ':' || GetChar(i-1) == '!')))
{
file += '\n';
texrow.newline();
texrow.start(this, i+1);
column = 0;
} else if (font.latex() == LyXFont::OFF) {
if (font.family() == LyXFont::TYPEWRITER_FAMILY)
file += '~';
else
file += ' ';
}
}
// Do we need to change font?
if (font != running_font) {
column += font.latexWriteStartChanges(file, basefont);
running_font = font;
open_font = true;
}
// Do we need to turn on LaTeX mode?
if (font.latex() != running_font.latex()) {
if (font.latex() == LyXFont::ON
&& style->needprotect)
{
file += "\\protect ";
column += 9;
}
}
if (c == LYX_META_INSET) {
inset = GetInset(i);
if (inset) {
tmp = inset->Latex(file, style->isCommand());
if (tmp)
column = 0;
for (;tmp--;)
texrow.newline();
}
} else {
// Are we in LaTeX mode?
if (font.latex() == LyXFont::ON) {
switch (c) {
case LYX_META_NEWLINE:
if (open_font) {
column += running_font.latexWriteEndChanges(file, basefont);
open_font = false;
}
basefont = getFont(-1);
running_font = basefont;
current_cell_number++;
if (table->CellHasContRow(current_cell_number)>=0)
TeXContTableRows(file, i+1,current_cell_number,column, texrow);
// if this cell follow only ContRows til end don't
// put the EndOfCell because it is put after the
// for(...)
if (table->ShouldBeVeryLastCell(current_cell_number))
break;
tmp = table->TexEndOfCell(file, current_cell_number);
if (tmp>0)
column = 0;
else if (tmp < 0)
tmp = -tmp;
for (;tmp--;)
texrow.newline();
texrow.start(this, i+1);
break;
case LYX_META_HFILL:
file += "\\hfill{}";
column+=7;
break;
case LYX_META_PROTECTED_SEPARATOR:
file += '~';
break;
default:
// make sure that we will not print
// error generating chars to the tex
// file. This test would not be needed
// if it were done in the buffer
// itself.
if (c != '\0')
file += c;
break;
}
} else {
// Plain mode (i.e. not LaTeX)
switch (c) {
case LYX_META_NEWLINE:
if (open_font) {
column += running_font.latexWriteEndChanges(file, basefont);
open_font = false;
}
basefont = getFont(-1);
running_font = basefont;
current_cell_number++;
if (table->CellHasContRow(current_cell_number)>=0)
TeXContTableRows(file,i+1,current_cell_number,column, texrow);
// if this cell follow only ContRows til end don't
// put the EndOfCell because it is put after the
// for(...)
if (table->ShouldBeVeryLastCell(current_cell_number))
break;
tmp = table->TexEndOfCell(file, current_cell_number);
if (tmp>0)
column = 0;
else if (tmp < 0)
tmp = -tmp;
for (;tmp>0;tmp--)
texrow.newline();
texrow.start(this, i+1);
break;
case LYX_META_HFILL:
file += "\\hfill{}";
column+=7;
break;
case LYX_META_PROTECTED_SEPARATOR:
file += '~';
break;
case '\\':
if (lyxrc->fontenc=="T1"
|| font.family() == LyXFont::TYPEWRITER_FAMILY){
file += "\\char`\\\\{}";
column+=9;
} else {
file += "\\ensuremath{\\backslash}";
column+=22;
}
break;
case '░': case '▒': case '▓': case '│':
case '╫': case '≈': case '╣': case '¬':
case '║': case '¼': case '╡':
if (current_view->currentBuffer()->params.inputenc == "latin1") {
file += "\\ensuremath{";
file += c;
file += '}';
column+=13;
} else
file += c;
break;
case '|': case '<': case '>':
if (lyxrc->fontenc=="T1") {
if ((c=='>' ||c=='<')
&& i <= last-2
&& GetChar(i+1)==c){
file += c;
file += "\\textcompwordmark{}";
column+=19;
} else
file += c;
} else if(font.family() == LyXFont::TYPEWRITER_FAMILY)
file += c;
else {
file += "\\ensuremath{";
file += c;
file += '}';
column+=13;
}
break;
case '-': // "--" in Typewriter mode -> "-{}-"
if (i <= last-2
&& GetChar(i+1) == '-'
&& font.family() == LyXFont::TYPEWRITER_FAMILY) {
file += "-{}";
column += 2;
} else
file += '-';
break;
case '\"':
file += "\\char`\\\"{}";
column+=9;
break;
case 'ú':
if (current_view->currentBuffer()->params.inputenc == "default") {
file += "\\pounds{}";
column+=8;
} else
file += c;
break;
case '$': case '&':
case '%': case '#': case '{':
case '}': case '_':
file += '\\';
file += c;
column +=1;
break;
case '^': case '~':
file += '\\';
file += c;
file += "{}";
column +=3;
break;
case '*': case '[': case ']':
// avoid being mistaken for optional arguments
file += '{';
file += c;
file += '}';
column +=2;
break;
case ' ':
/* blanks are printed before font switching */
// Sure? I am not! (try nice-latex)
// I am sure it's correct. LyX might be smarter
// in the future, but for now, nothing wrong is
// written. (Asger)
break;
default:
/* idea for labels --- begin*/
/* check for LyX */
if (c == 'L' && i <= last-3
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'y'
&& GetChar(i+2) == 'X'){
file += "\\LyX{}";
i+=2;
column += 5;
}
/* check for TeX */
else if (c == 'T' && i <= last-3
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'e'
&& GetChar(i+2) == 'X'){
file += "\\TeX{}";
i+=2;
column += 5;
}
/* check for LaTeX2e */
else if (c == 'L' && i <= last-7
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'a'
&& GetChar(i+2) == 'T'
&& GetChar(i+3) == 'e'
&& GetChar(i+4) == 'X'
&& GetChar(i+5) == '2'
&& GetChar(i+6) == 'e'){
file += "\\LaTeXe{}";
i+=6;
column += 8;
}
/* check for LaTeX */
else if (c == 'L' && i <= last-5
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'a'
&& GetChar(i+2) == 'T'
&& GetChar(i+3) == 'e'
&& GetChar(i+4) == 'X'){
file += "\\LaTeX{}";
i+=4;
column += 7;
} else
/* idea for labels --- end*/
// same test as above
if (c != '\0')
file += c;
break;
}
}
}
}
// If we have an open font definition, we have to close it
if (open_font) {
running_font.latexWriteEndChanges(file, basefont);
}
current_cell_number++;
tmp = table->TexEndOfCell(file, current_cell_number);
for (;tmp>0;tmp--)
texrow.newline();
lyxerr.debug(LString("SimpleTeXOneTablePar...done ")+(long)this, Error::LATEX);
return return_value;
}
// This one spits out the text off ContRows in tables
bool LyXParagraph::TeXContTableRows(LString &file, int i,
int current_cell_number,
int &column, TexRow &texrow)
{
lyxerr.debug(LString("TeXContTableRows... ")+(long)this, Error::LATEX);
if (!table)
return false;
char c;
Inset *inset;
int tmp, cell;
int lastpos;
bool return_value = false;
LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
LyXFont basefont;
basefont = getFont(-1); // Get layout font
// Which font is currently active?
LyXFont running_font = basefont;
// Do we have an open font change?
bool open_font = false;
lastpos = i;
cell = table->CellHasContRow(current_cell_number);
current_cell_number++;
while(cell >= 0) {
// first find the right position
i = lastpos;
for (; (i<last) && (current_cell_number<cell); i++) {
c = GetChar(i);
if (c == LYX_META_NEWLINE)
current_cell_number++;
}
lastpos = i;
c=GetChar(i);
if (table->Linebreaks(table->FirstVirtualCell(cell))) {
file += " \\\\\n";
texrow.newline();
column = 0;
} else if ((c != ' ') && (c != LYX_META_NEWLINE))
file += ' ';
for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE); i++) {
column++;
// Fully instantiated font
LyXFont font = getFont(i);
// We end font definition before blanks
if (font != running_font && open_font) {
column += running_font.latexWriteEndChanges(file, basefont);
running_font = basefont;
open_font = false;
}
// Blanks are printed before start of fontswitch
if (c==' '){
if (column > tex_code_break_column
&& i && GetChar(i-1) != ' '
&& (i < last-1) &&
// In LaTeX mode, we don't want to
// break lines since some commands
// do not like this
! (font.latex() == LyXFont::ON) &&
// In typewriter mode, we want to avoid
// ! . ? : at the end of a line
!(font.family() == LyXFont::TYPEWRITER_FAMILY &&
(GetChar(i-1) == '.' || GetChar(i-1) == '?' ||
GetChar(i-1) == ':' || GetChar(i-1) == '!')))
{
file += '\n';
texrow.newline();
texrow.start(this, i+1);
column = 0;
} else if (font.latex() == LyXFont::OFF) {
if (font.family() == LyXFont::TYPEWRITER_FAMILY)
file += '~';
else
file += ' ';
}
}
// Do we need to change font?
if (font != running_font) {
column += font.latexWriteStartChanges(file, basefont);
running_font = font;
open_font = true;
}
// Do we need to turn on LaTeX mode?
if (font.latex() != running_font.latex()) {
if (font.latex() == LyXFont::ON
&& style->needprotect)
{
file += "\\protect ";
column += 9;
}
}
if (c == LYX_META_INSET) {
inset = GetInset(i);
if (inset) {
tmp = inset->Latex(file, style->isCommand());
if (tmp)
column = 0;
for (;tmp--;)
texrow.newline();
}
} else {
// Are we in LaTeX mode?
if (font.latex() == LyXFont::ON) {
switch (c) {
case LYX_META_NEWLINE:
if (open_font) {
column += running_font.latexWriteEndChanges(file, basefont);
open_font = false;
}
basefont = getFont(-1);
running_font = basefont;
break;
case LYX_META_HFILL:
file += "\\hfill{}";
column+=7;
break;
case LYX_META_PROTECTED_SEPARATOR:
file += '~';
break;
default:
// make sure that we will not print
// error generating chars to the tex
// file. This test would not be needed
// if it were done in the buffer
// itself.
if (c != '\0')
file += (char)c;
break;
}
} else {
// Plain mode (i.e. not LaTeX)
switch (c) {
case LYX_META_NEWLINE:
if (open_font) {
column += running_font.latexWriteEndChanges(file, basefont);
open_font = false;
}
basefont = getFont(-1);
running_font = basefont;
break;
case LYX_META_HFILL:
file += "\\hfill{}";
column+=7;
break;
case LYX_META_PROTECTED_SEPARATOR:
file += '~';
break;
case '\\':
if (lyxrc->fontenc=="T1"
|| font.family() == LyXFont::TYPEWRITER_FAMILY){
file += "\\char`\\\\{}";
column+=9;
} else {
file += "\\ensuremath{\\backslash}";
column+=22;
}
break;
case '░': case '▒': case '▓': case '│':
case '╫': case '≈': case '╣': case '¬':
case '║': case '¼': case '╡':
if (current_view->currentBuffer()->params.inputenc == "latin1") {
file += "\\ensuremath{";
file += c;
file += '}';
column+=13;
} else
file += c;
break;
case '|': case '<': case '>':
if (lyxrc->fontenc=="T1") {
if ((c=='>' ||c=='<')
&& i <= last-2
&& GetChar(i+1)==c){
file += c;
file += "\\textcompwordmark{}";
column+=19;
} else
file += c;
} else if(font.family() == LyXFont::TYPEWRITER_FAMILY)
file += c;
else {
file += "\\ensuremath{";
file += c;
file += '}';
column+=13;
}
break;
case '-': // "--" in Typewriter mode -> "-{}-"
if (i <= last-2
&& GetChar(i+1) == '-'
&& font.family() == LyXFont::TYPEWRITER_FAMILY) {
file += "-{}";
column += 2;
} else
file += '-';
break;
case '\"':
file += "\\char`\\\"{}";
column+=9;
break;
case 'ú':
if (current_view->currentBuffer()->params.inputenc == "default") {
file += "\\pounds{}";
column+=8;
} else
file += c;
break;
case '$': case '&':
case '%': case '#': case '{':
case '}': case '_':
file += '\\';
file += c;
column +=1;
break;
case '^': case '~':
file += '\\';
file += c;
file += "{}";
column +=3;
break;
case '*': case '[': case ']':
// avoid being mistaken for optional arguments
file += '{';
file += c;
file += '}';
column +=2;
break;
case ' ':
/* blanks are printed before font switching */
// Sure? I am not! (try nice-latex)
// I am sure it's correct. LyX might be smarter
// in the future, but for now, nothing wrong is
// written. (Asger)
break;
default:
/* idea for labels --- begin*/
/* check for LyX */
if (c == 'L' && i <= last-3
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'y'
&& GetChar(i+2) == 'X'){
file += "\\LyX{}";
i+=2;
column += 5;
}
/* check for TeX */
else if (c == 'T' && i <= last-3
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'e'
&& GetChar(i+2) == 'X'){
file += "\\TeX{}";
i+=2;
column += 5;
}
/* check for LaTeX2e */
else if (c == 'L' && i <= last-7
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'a'
&& GetChar(i+2) == 'T'
&& GetChar(i+3) == 'e'
&& GetChar(i+4) == 'X'
&& GetChar(i+5) == '2'
&& GetChar(i+6) == 'e'){
file += "\\LaTeXe{}";
i+=6;
column += 8;
}
/* check for LaTeX */
else if (c == 'L' && i <= last-5
&& font.family()
!= LyXFont::TYPEWRITER_FAMILY
&& GetChar(i+1) == 'a'
&& GetChar(i+2) == 'T'
&& GetChar(i+3) == 'e'
&& GetChar(i+4) == 'X'){
file += "\\LaTeX{}";
i+=4;
column += 7;
} else
/* idea for labels --- end*/
// same test as above
if (c != '\0')
file += c;
break;
}
}
}
}
// If we have an open font definition, we have to close it
if (open_font) {
running_font.latexWriteEndChanges(file, basefont);
open_font=false;
}
basefont = getFont(-1);
running_font = basefont;
cell = table->CellHasContRow(current_cell_number);
}
lyxerr.debug(LString("TeXContTableRows...done ")+(long)this, Error::LATEX);
return return_value;
}
bool LyXParagraph::RoffContTableRows(FILE *fp, int i, int actcell)
{
if (!table)
return false;
LyXFont
font1 = LyXFont(LyXFont::ALL_INHERIT),
font2;
Inset
*inset;
int
lastpos, cell;
char
c;
LString
fname2;
FILE
*fp2;
fname2 = TmpFileName(LString(),"RAT2");
lastpos = i;
cell = table->CellHasContRow(actcell);
actcell++;
while(cell >= 0) {
// first find the right position
i = lastpos;
for (; (i<last) && (actcell<cell); i++) {
c = GetChar(i);
if (c == LYX_META_NEWLINE)
actcell++;
}
lastpos = i;
c=GetChar(i);
if ((c != ' ') && (c != LYX_META_NEWLINE))
fprintf(fp," ");
for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE); i++) {
font2 = GetFontSettings(i);
if (font1.latex() != font2.latex()) {
if (font2.latex() != LyXFont::OFF)
continue;
}
c = GetChar(i);
switch (c) {
case LYX_META_INSET:
if ((inset = GetInset(i))) {
if (!(fp2=fopen(fname2.c_str(),"w+"))) {
WriteAlert(_("LYX_ERROR:"), _("Cannot open temporary file:"), fname2);
return false;
}
inset->Latex(fp2,-1);
rewind(fp2);
c = fgetc(fp2);
while(!feof(fp2)) {
if (c == '\\')
fprintf(fp,"\\\\");
else
fputc(c,fp);
c = fgetc(fp2);
}
fclose(fp2);
}
break;
case LYX_META_NEWLINE:
break;
case LYX_META_HFILL:
break;
case LYX_META_PROTECTED_SEPARATOR:
break;
case '\\':
fprintf(fp, "\\\\");
break;
default:
if (c != '\0')
fprintf(fp, "%c", c);
else
lyxerr.debug("RoffAsciiTable: NULL char in structure.");
break;
}
}
cell = table->CellHasContRow(actcell);
}
return true;
}
LyXParagraph * LyXParagraph::TeXDeeper(LString &file, TexRow &texrow,
LString &foot, TexRow &foot_texrow,
int &foot_count)
{
lyxerr.debug(LString("TeXDeeper... ") + (long)this, Error::LATEX);
LyXParagraph *par = this;
while (par && par->depth == depth) {
if (par->IsDummy())
lyxerr.print("ERROR (LyXParagraph::TeXDeeper)");
if (lyxstyle.Style(GetCurrentTextClass(),
par->layout)->isEnvironment()
|| par->pextra_type != PEXTRA_NONE)
{
par = par->TeXEnvironment(file, texrow,
foot, foot_texrow,
foot_count);
} else {
par = par->TeXOnePar(file, texrow,
foot, foot_texrow,
foot_count);
}
}
lyxerr.debug(LString("TeXDeeper...done ") + (long)par, Error::LATEX);
return par;
}
LyXParagraph* LyXParagraph::TeXEnvironment(LString &file, TexRow &texrow,
LString &foot, TexRow &foot_texrow,
int &foot_count)
{
bool
eindent_open = false;
static bool
minipage_open = false;
static int
minipage_open_depth = 0;
char
par_sep = current_view->currentBuffer()->params.paragraph_separation;
lyxerr.debug(LString("TeXEnvironment... ") + long(this), Error::LATEX);
if (IsDummy())
lyxerr.print("ERROR (LyXParagraph::TeXEnvironment)");
LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), layout);
if (pextra_type == PEXTRA_INDENT) {
if (!pextra_width.empty()) {
file += "\\begin{LyXParagraphIndent}{"
+ pextra_width + "}\n";
} else {
//float ib = atof(pextra_widthp.c_str())/100;
// LString can't handle floats at present (971109)
// so I'll do a conversion by hand knowing that
// the limits are 0.0 to 1.0. ARRae.
file += "\\begin{LyXParagraphIndent}{";
switch (pextra_widthp.length()) {
case 3:
file += "1.00";
break;
case 2:
file += "0.";
file += pextra_widthp;
break;
case 1:
file += "0.0";
file += pextra_widthp;
}
file += "\\columnwidth}\n";
}
texrow.newline();
eindent_open = true;
}
if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
if (pextra_hfill && Previous() &&
(Previous()->pextra_type == PEXTRA_MINIPAGE)) {
file += "\\hfill{}\n";
texrow.newline();
}
if (par_sep == LYX_PARSEP_INDENT) {
file += "{\\setlength\\parindent{0pt}\n";
texrow.newline();
}
file += "\\begin{minipage}";
switch(pextra_alignment) {
case MINIPAGE_ALIGN_TOP:
file += "[t]";
break;
case MINIPAGE_ALIGN_MIDDLE:
file += "[m]";
break;
case MINIPAGE_ALIGN_BOTTOM:
file += "[b]";
break;
}
if (!pextra_width.empty()) {
file += '{';
file += pextra_width + "}\n";
} else {
//float ib = atof(par->pextra_width.c_str())/100;
// LString can't handle floats at present
// so I'll do a conversion by hand knowing that
// the limits are 0.0 to 1.0. ARRae.
file += '{';
switch (pextra_widthp.length()) {
case 3:
file += "1.00";
break;
case 2:
file += "0.";
file += pextra_widthp;
break;
case 1:
file += "0.0";
file += pextra_widthp;
}
file += "\\columnwidth}\n";
}
texrow.newline();
if (par_sep == LYX_PARSEP_INDENT) {
file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
texrow.newline();
}
minipage_open = true;
minipage_open_depth = depth;
}
if (style->isEnvironment()){
if (style->latextype == LATEX_LIST_ENVIRONMENT)
file += "\\begin{" + style->latexname + "}{"
+ labelwidthstring + "}\n";
else if (style->labeltype == LABEL_BIBLIO) {
// ale970405
file += "\\begin{" + style->latexname + "}{"
+ bibitemWidthest() + "}\n";
}
//arrae970411
else if (style->latexparam.empty())
file += "\\begin{" + style->latexname + "}\n";
else
file += "\\begin{" + style->latexname + "}{"
+ style->latexparam + "}\n";
texrow.newline();
}
LyXParagraph *par = this;
do {
par = par->TeXOnePar(file, texrow,
foot, foot_texrow, foot_count);
#if 0
if (eindent_open && par && par->pextra_type != PEXTRA_INDENT) {
file += "\\end{LyXParagraphIndent}\n";
texrow.newline();
eindent_open = false;
if (!style->isEnvironment())
break;
}
#endif
if (minipage_open && par && !style->isEnvironment() &&
(par->pextra_type == PEXTRA_MINIPAGE) &&
par->pextra_start_minipage) {
file += "\\end{minipage}\n";
texrow.newline();
if (par_sep == LYX_PARSEP_INDENT) {
file += "}\n";
texrow.newline();
}
minipage_open = false;
}
if (par && par->depth > depth) {
if (lyxstyle.Style(GetCurrentTextClass(),
par->layout)->isParagraph()
&& !par->table
&& !file.suffixIs("\n\n")) {
// There should be at least one '\n' already
// but we need there to be two for Standard
// paragraphs that are depth-increment'ed to be
// output correctly. However, tables can also be
// paragraphs so don't adjust them. ARRae
file += '\n';
texrow.newline();
}
par = par->TeXDeeper(file, texrow,
foot, foot_texrow, foot_count);
}
if (par && par->layout == layout && par->depth == depth &&
(par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
if (par->pextra_hfill && par->Previous() &&
(par->Previous()->pextra_type == PEXTRA_MINIPAGE))
file += "\\hfill{}\n";
else
file += '\n';
texrow.newline();
if (par_sep == LYX_PARSEP_INDENT) {
file += "{\\setlength\\parindent{0pt}\n";
texrow.newline();
}
file += "\\begin{minipage}";
switch(par->pextra_alignment) {
case MINIPAGE_ALIGN_TOP:
file += "[t]";
break;
case MINIPAGE_ALIGN_MIDDLE:
file += "[m]";
break;
case MINIPAGE_ALIGN_BOTTOM:
file += "[b]";
break;
}
if (!par->pextra_width.empty()) {
file += '{';
file += par->pextra_width;
file += "}\n";
} else {
//float ib = atof(par->pextra_widthp.c_str())/100;
// LString can't handle floats at present
// so I'll do a conversion by hand knowing that
// the limits are 0.0 to 1.0. ARRae.
file += '{';
switch (par->pextra_widthp.length()) {
case 3:
file += "1.00";
break;
case 2:
file += "0.";
file += par->pextra_widthp;
break;
case 1:
file += "0.0";
file += par->pextra_widthp;
}
file += "\\columnwidth}\n";
}
texrow.newline();
if (par_sep == LYX_PARSEP_INDENT) {
file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
texrow.newline();
}
minipage_open = true;
minipage_open_depth = par->depth;
}
} while (par
&& par->layout == layout
&& par->depth == depth
&& par->pextra_type == pextra_type);
if (style->isEnvironment()) {
file += "\\end{" + style->latexname + '}';
//texrow.newline();
}
if (minipage_open && (minipage_open_depth == depth) &&
(!par || par->pextra_start_minipage ||
par->pextra_type != PEXTRA_MINIPAGE)) {
file += "\\end{minipage}\n";
texrow.newline();
if (par_sep == LYX_PARSEP_INDENT) {
file += "}\n";
texrow.newline();
}
if (par && par->pextra_type != PEXTRA_MINIPAGE) {
file += "\\medskip\n\n";
texrow.newline();
texrow.newline();
}
minipage_open = false;
}
if (eindent_open) {
file += "\\end{LyXParagraphIndent}\n";
texrow.newline();
}
// if (tex_code_break_column){
if (!(par && (par->pextra_type==PEXTRA_MINIPAGE)
&& par->pextra_hfill)) {
file += '\n';
texrow.newline();
}
lyxerr.debug(LString("TeXEnvironment...done ")
+ (long)par, Error::LATEX);
return par; // ale970302
}
LyXParagraph * LyXParagraph::TeXFootnote(LString &file, TexRow &texrow,
LString &foot, TexRow &foot_texrow,
int &foot_count)
{
lyxerr.debug(LString("TeXFootnote... ")
+ (long)this, Error::LATEX);
if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
lyxerr.print("ERROR (LyXParagraph::TeXFootnote): "
"No footnote!");
LyXParagraph *par = this;
LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(),
previous->GetLayout());
if (style->needprotect && footnotekind != LyXParagraph::FOOTNOTE){
lyxerr.print("ERROR (LyXParagraph::TeXFootnote): "
"Float other than footnote in command"
" with moving argument is illegal");
}
BufferParams *params = ¤t_view->currentBuffer()->params;
bool footer_in_body = true;
switch (footnotekind) {
case LyXParagraph::FOOTNOTE:
if (style->intitle) {
file += "\\thanks{\n";
footer_in_body = false;
} else {
if (foot_count == -1) {
// we're at depth 0 so we can use:
file += "\\footnote{\n";
footer_in_body = false;
} else {
file += "\\footnotemark{}\n";
if (foot_count) {
// we only need this when there are
// multiple footnotes
foot += "\\stepcounter{footnote}";
}
foot += "\\footnotetext{\n";
foot_texrow.start(this,0);
foot_texrow.newline();
++foot_count;
}
}
break;
case LyXParagraph::MARGIN:
file += "\\marginpar{\n";
break;
case LyXParagraph::FIG:
if (pextra_type == PEXTRA_FLOATFLT
&& (!pextra_width.empty()
|| !pextra_widthp.empty())) {
char bufr[80];
if (!pextra_width.empty())
sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
pextra_width.c_str());
else
sprintf(bufr, "\\begin{floatingfigure}{%f\\textwidth}\n",
atoi(pextra_widthp.c_str())/100.0);
file += bufr;
} else {
file += "\\begin{figure}";
if (!params->float_placement.empty()) {
file += '[';
file += params->float_placement;
file += "]\n";
} else {
file += '\n';
}
}
break;
case LyXParagraph::TAB:
file += "\\begin{table}";
if (!params->float_placement.empty()) {
file += '[';
file += params->float_placement;
file += "]\n";
} else {
file += '\n';
}
break;
case LyXParagraph::WIDE_FIG:
file += "\\begin{figure*}";
if (!params->float_placement.empty()) {
file += '[';
file += params->float_placement;
file += "]\n";
} else {
file += '\n';
}
break;
case LyXParagraph::WIDE_TAB:
file += "\\begin{table*}";
if (!params->float_placement.empty()) {
file += '[';
file += params->float_placement;
file += "]\n";
} else {
file += '\n';
}
break;
case LyXParagraph::ALGORITHM:
file += "\\begin{algorithm}\n";
break;
}
texrow.newline();
if (footnotekind != LyXParagraph::FOOTNOTE
|| !footer_in_body) {
// Process text for all floats except footnotes in body
do {
LyXLayout *style = lyxstyle.Style(GetCurrentTextClass(),
par->layout);
if (par->IsDummy())
lyxerr.print("ERROR (LyXParagraph::TeXFootnote)");
if (style->isEnvironment()) {
par = par->TeXEnvironment(file, texrow,
foot, foot_texrow,
foot_count);
} else {
par = par->TeXOnePar(file, texrow,
foot, foot_texrow,
foot_count);
}
if (par && !par->IsDummy() && par->depth > depth) {
par = par->TeXDeeper(file, texrow,
foot, foot_texrow,
foot_count);
}
} while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
} else {
// process footnotes > depth 0 or in environments separately
// NOTE: Currently don't support footnotes within footnotes
// even though that is possible using the \footnotemark
LString dummy;
TexRow dummy_texrow;
int dummy_count = 0;
do {
LyXLayout *style = lyxstyle.Style(GetCurrentTextClass(),
par->layout);
if (par->IsDummy())
lyxerr.print("ERROR (LyXParagraph::TeXFootnote)");
if (style->isEnvironment()) {
par = par->TeXEnvironment(foot, foot_texrow,
dummy, dummy_texrow,
dummy_count);
} else {
par = par->TeXOnePar(foot, foot_texrow,
dummy, dummy_texrow,
dummy_count);
}
if (par && !par->IsDummy() && par->depth > depth) {
par = par->TeXDeeper(foot, foot_texrow,
dummy, dummy_texrow,
dummy_count);
}
} while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
if (dummy_count) {
lyxerr.print("ERROR (LyXParagraph::TeXFootnote): "
"Footnote in a Footnote -- not supported");
}
}
switch (footnotekind) {
case LyXParagraph::FOOTNOTE:
if (footer_in_body) {
// This helps tell which of the multiple
// footnotetexts an error was in.
foot += "}%\n";
foot_texrow.newline();
} else {
file += '}';
}
break;
case LyXParagraph::MARGIN:
file += '}';
break;
case LyXParagraph::FIG:
if (pextra_type == PEXTRA_FLOATFLT
&& (!pextra_width.empty()
|| !pextra_widthp.empty()))
file += "\\end{floatingfigure}";
else
file += "\\end{figure}";
break;
case LyXParagraph::TAB:
file += "\\end{table} ";
break;
case LyXParagraph::WIDE_FIG:
file += "\\end{figure*} ";
break;
case LyXParagraph::WIDE_TAB:
file += "\\end{table*} ";
break;
case LyXParagraph::ALGORITHM:
file += "\\end{algorithm} ";
break;
}
lyxerr.debug(LString("TeXFootnote...done ") +
long(par->next), Error::LATEX);
return par;
}
void LyXParagraph::SetPExtraType(int type, const char *width,const char *widthp)
{
pextra_type = type;
pextra_width = width;
pextra_widthp = widthp;
if (lyxstyle.Style(GetCurrentTextClass(),
layout)->isEnvironment()) {
LyXParagraph
*par = this,
*ppar = par;
while (par && (par->layout == layout) && (par->depth == depth)) {
ppar = par;
par = par->Previous();
if (par)
par = par->FirstPhysicalPar();
while (par && par->depth > depth) {
par = par->Previous();
if (par)
par = par->FirstPhysicalPar();
}
}
par = ppar;
while (par && (par->layout == layout) && (par->depth == depth)) {
par->pextra_type = type;
par->pextra_width = width;
par->pextra_widthp = widthp;
par = par->NextAfterFootnote();
if (par && (par->depth > depth))
par->SetPExtraType(type,width,widthp);
while (par && ((par->depth > depth) || par->IsDummy()))
par = par->NextAfterFootnote();
}
}
}
void LyXParagraph::UnsetPExtraType()
{
if (pextra_type == PEXTRA_NONE)
return;
pextra_type = PEXTRA_NONE;
pextra_width.erase();
pextra_widthp.erase();
if (lyxstyle.Style(GetCurrentTextClass(),
layout)->isEnvironment()) {
LyXParagraph
*par = this,
*ppar = par;
while (par && (par->layout == layout) && (par->depth == depth)) {
ppar = par;
par = par->Previous();
if (par)
par = par->FirstPhysicalPar();
while (par && par->depth > depth) {
par = par->Previous();
if (par)
par = par->FirstPhysicalPar();
}
}
par = ppar;
while (par && (par->layout == layout) && (par->depth == depth)) {
par->pextra_type = PEXTRA_NONE;
par->pextra_width.erase();
par->pextra_widthp.erase();
par = par->NextAfterFootnote();
if (par && (par->depth > depth))
par->UnsetPExtraType();
while (par && ((par->depth > depth) || par->IsDummy()))
par = par->NextAfterFootnote();
}
}
}