/* This file is part of *====================================================== * *LyX,TheDocumentProcessor * *Copyright(C)1995MatthiasEttrich *Copyright(C)1995-1998TheLyXTeam. *
*======================================================*/
while (par) {
InsertParagraph(par, lastrow);
par = par->Next();
} /* set cursor at the very top position */
selection = true; /* these setting is necessary *becauseofthedelete-empty- *paragraphmechanismin
* SetCursor */
SetCursor(firstrow->par, 0);
sel_cursor = cursor;
selection = false;
mark_set = false;
/* no rebreak necessary */
need_break_row = NULL;
undo_finished = true;
undo_frozen = false;
// Default layouttype for copy environment type
copylayouttype = 0;
}
// Destructor
LyXText::~LyXText()
{ // Delete all rows, this does not touch the paragraphs!
Row *tmprow = firstrow; while (firstrow) {
tmprow = firstrow->next; delete firstrow;
firstrow = tmprow;
}
}
// Gets the fully instantiated font at a given position in a paragraph // Basically the same routine as LyXParagraph::getFont() in paragraph.C. // The difference is that this one is used for displaying, and thus we // are allowed to make cosmetic improvements. For instance make footnotes // smaller. (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 LyXText::GetFont(LyXParagraph* par, int pos)
{
LyXLayout *layout =
lyxstyle.Style(parameters->textclass, par->GetLayout());
char par_depth = par->GetDepth(); // We specialize the 95% common case: if (par->footnoteflag == LyXParagraph::NO_FOOTNOTE && !par_depth) { if (pos >= 0){ // 95% goes here if (layout->labeltype == LABEL_MANUAL
&& pos < BeginningOfMainBody(par)) { // 1% goes here return par->GetFontSettings(pos).
realize(layout->reslabelfont);
} else return par->GetFontSettings(pos).
realize(layout->resfont);
} else { // 5% goes here. // process layoutfont for pos == -1 and labelfont for pos < -1 if (pos == -1) return layout->resfont; else return layout->reslabelfont;
}
}
// The uncommon case need not be optimized as much
LyXFont layoutfont, tmpfont;
if (pos >= 0){ // 95% goes here if (pos < BeginningOfMainBody(par)) { // 1% goes here
layoutfont = layout->labelfont;
} else { // 99% goes here
layoutfont = layout->font;
}
tmpfont = par->GetFontSettings(pos);
tmpfont.realize(layoutfont);
} else{ // 5% goes here. // process layoutfont for pos == -1 and labelfont for pos < -1 if (pos == -1)
tmpfont = layout->font; else
tmpfont = layout->labelfont;
}
// Resolve against environment font information //if (par->GetDepth()){ // already in while condition while (par && par_depth && !tmpfont.resolved()) {
par = par->DepthHook(par_depth - 1); if (par) {
tmpfont.realize(lyxstyle.
Style(parameters->textclass,
par->GetLayout())->font);
par_depth = par->GetDepth();
}
} //}
// Cosmetic improvement: If this is an open footnote, make the font // smaller. if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
&& par->footnotekind == LyXParagraph::FOOTNOTE) {
tmpfont.decSize();
}
return tmpfont;
}
void LyXText::SetCharFont(LyXParagraph *par, int pos, LyXFont font)
{ /* let the insets convert their font */ if (par->GetChar(pos) == LYX_META_INSET) { if (par->GetInset(pos))
font = par->GetInset(pos)->ConvertFont(font);
}
// Realize against environment font information if (par->GetDepth()){
LyXParagraph * tp = par; while (!layoutfont.resolved() && tp && tp->GetDepth()) {
tp = tp->DepthHook(tp->GetDepth()-1); if (tp)
layoutfont.realize(lyxstyle.
Style(parameters->textclass,
tp->GetLayout())->font);
}
}
// Now, reduce font against full layout font
font.reduce(layoutfont);
par->SetFont(pos, font);
}
/* inserts a new row behind the specified row, increments
* the touched counters */ void LyXText::InsertRow(Row *row, LyXParagraph *par, int pos)
{
Row *tmprow = new Row; if (!row) {
tmprow->previous = NULL;
tmprow->next = firstrow;
firstrow = tmprow;
} else {
tmprow->previous = row;
tmprow->next = row->next;
row->next = tmprow;
}
if (tmprow->next)
tmprow->next->previous = tmprow;
if (tmprow->previous)
tmprow->previous->next = tmprow;
tmprow->par = par;
tmprow->pos = pos;
if (row == lastrow)
lastrow = tmprow;
number_of_rows++; /* one more row */
}
/* removes the row and reset the touched counters */ void LyXText::RemoveRow(Row *row)
{ /* this must not happen before the currentrow for clear reasons. sothetrickisjusttosetthecurrentrowontotheprevious
row of this row */ long unused_y;
GetRow(row->par, row->pos, unused_y);
currentrow = currentrow->previous; if (currentrow)
currentrow_y -= currentrow->height; else
currentrow_y = 0;
if (row->next)
row->next->previous = row->previous; if (!row->previous) {
firstrow = row->next;
} else {
row->previous->next = row->next;
} if (row == lastrow)
lastrow = row->previous;
height -= row->height; /* the text becomes smaller */
delete row;
number_of_rows--; /* one row less */
}
/* remove all following rows of the paragraph of the specified row. */ void LyXText::RemoveParagraph(Row *row)
{
LyXParagraph *tmppar;
Row *tmprow;
/* insert the specified paragraph behind the specified row */ void LyXText::InsertParagraph(LyXParagraph *par, Row *row)
{
InsertRow(row, par, 0); /* insert a new row, starting
* at postition 0 */
SetCounter(par); /* set the counters */
/* and now append the whole paragraph behind the new row */ if (!row) {
firstrow->height = 0;
AppendParagraph(firstrow);
} else {
row->next->height = 0;
AppendParagraph(row->next);
}
}
/* if the cursor is not in an open footnote, or
* there is no open footnote in this paragraph, just return. */ if (cursor.par->footnoteflag != LyXParagraph::OPEN_FOOTNOTE) {
if (!par->next
|| par->next->footnoteflag != LyXParagraph::OPEN_FOOTNOTE) {
minibuffer->Set(_("Nothing to do")); return;
}
/* ok, move the cursor right before the footnote */
/* just a little faster than using CursorRight() */ for (cursor.pos=0; cursor.par->ParFromPos(cursor.pos)!=par; cursor.pos++); /* now the cursor is at the beginning of the physical par */
SetCursor(cursor.par, cursor.pos + cursor.par->ParFromPos(cursor.pos)->last);
} else { /* we are in a footnote, so let us move at the beginning */ /* while (cursor.par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) cursor.par=cursor.par->Previous();
SetCursor(cursor.par, cursor.par->Last()); */ /* this is just faster than using just CursorLeft() */
tmppar = cursor.par; while (tmppar->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { /* just a little bit faster than movin the cursor */
tmppar = tmppar->Previous();
}
SetCursor(tmppar, tmppar->Last());
}
/* the cursor must be exactly before the footnote */
par = cursor.par->ParFromPos(cursor.pos);
/* just necessary */ if (cursor.row->next)
SetHeightOfRow(cursor.row->next);
}
/* used in setlayout */ // Asger is not sure we want to do this... void LyXText::MakeFontEntriesLayoutSpecific(LyXParagraph *par)
{
LyXFont layoutfont, tmpfont;
/* set layout over selection and make a total rebreak of those paragraphs */ void LyXText::SetLayout(char layout)
{
LyXCursor tmpcursor;
/* if there is no selection just set the layout of the current paragraph */ if (!selection) {
sel_start_cursor = cursor; /* dummy selection */
sel_end_cursor = cursor;
}
/* we have to reset the selection, because the
* geometry could have changed */
SetCursor(sel_start_cursor.par, sel_start_cursor.pos);
sel_cursor = cursor;
SetCursor(sel_end_cursor.par, sel_end_cursor.pos);
UpdateCounters(cursor.row);
ClearSelection();
SetSelection();
SetCursor(tmpcursor.par, tmpcursor.pos);
}
/* increment depth over selection and
* make a total rebreak of those paragraphs */ void LyXText::IncDepth()
{ // If there is no selection, just use the current paragraph if (!selection) {
sel_start_cursor = cursor; /* dummy selection */
sel_end_cursor = cursor;
}
// We end at the next paragraph with depth 0
LyXParagraph *endpar = sel_end_cursor.par->LastPhysicalPar()->Next();
LyXParagraph *undoendpar = endpar;
if (endpar && endpar->GetDepth()) { while (endpar && endpar->GetDepth()) {
endpar = endpar->LastPhysicalPar()->Next();
undoendpar = endpar;
}
} elseif (endpar) {
endpar = endpar->Next(); /* because of parindents etc. */
}
LyXCursor tmpcursor = cursor; /* store the current cursor */
/* ok we have a selection. This is always between sel_start_cursor
* and sel_end cursor */
cursor = sel_start_cursor;
bool anything_changed = false;
while (true) { // NOTE: you can't change the depth of a bibliography entry if (cursor.par->footnoteflag ==
sel_start_cursor.par->footnoteflag
&& lyxstyle.Style(parameters->textclass,
cursor.par->GetLayout()
)->labeltype != LABEL_BIBLIO) {
LyXParagraph * prev = cursor.par->FirstPhysicalPar()->Previous(); if (prev
&& (prev->GetDepth() - cursor.par->GetDepth() > 0
|| (prev->GetDepth() == cursor.par->GetDepth()
&& lyxstyle.Style(parameters->textclass,
prev->GetLayout())->isEnvironment()))) {
cursor.par->FirstPhysicalPar()->depth++;
anything_changed = true;
}
} if (cursor.par == sel_end_cursor.par) break;
cursor.par = cursor.par->Next();
}
/* if nothing changed set all depth to 0 */ if (!anything_changed) {
cursor = sel_start_cursor; while (cursor.par != sel_end_cursor.par) {
cursor.par->FirstPhysicalPar()->depth = 0;
cursor.par = cursor.par->Next();
} if (cursor.par->footnoteflag == sel_start_cursor.par->footnoteflag)
cursor.par->FirstPhysicalPar()->depth = 0;
}
RedoParagraphs(sel_start_cursor, endpar);
/* we have to reset the selection, because the
* geometry could have changed */
SetCursor(sel_start_cursor.par, sel_start_cursor.pos);
sel_cursor = cursor;
SetCursor(sel_end_cursor.par, sel_end_cursor.pos);
UpdateCounters(cursor.row);
ClearSelection();
SetSelection();
SetCursor(tmpcursor.par, tmpcursor.pos);
}
/* decrement depth over selection and
* make a total rebreak of those paragraphs */ void LyXText::DecDepth()
{ /* if there is no selection just set the layout of the current paragraph */ if (!selection) {
sel_start_cursor = cursor; /* dummy selection */
sel_end_cursor = cursor;
}
LyXCursor tmpcursor = cursor; /* store the current cursor */
/* ok we have a selection. This is always between sel_start_cursor
* and sel_end cursor */
cursor = sel_start_cursor;
while (true) { if (cursor.par->footnoteflag ==
sel_start_cursor.par->footnoteflag) { if (cursor.par->FirstPhysicalPar()->depth)
cursor.par->FirstPhysicalPar()->depth--;
} if (cursor.par == sel_end_cursor.par) break;
cursor.par = cursor.par->Next();
}
RedoParagraphs(sel_start_cursor, endpar);
/* we have to reset the selection, because the
* geometry could have changed */
SetCursor(sel_start_cursor.par, sel_start_cursor.pos);
sel_cursor = cursor;
SetCursor(sel_end_cursor.par, sel_end_cursor.pos);
UpdateCounters(cursor.row);
ClearSelection();
SetSelection();
SetCursor(tmpcursor.par, tmpcursor.pos);
}
/* set font over selection and make a total rebreak of those paragraphs */ void LyXText::SetFont(LyXFont font, bool toggleall)
{ /* if there is no selection just set the current_font */ if (!selection) { // Determine basis font
LyXFont layoutfont; if (cursor.pos < BeginningOfMainBody(cursor.par))
layoutfont = GetFont(cursor.par, -2); else
layoutfont = GetFont(cursor.par, -1);
// Update current font
real_current_font.update(font,toggleall);
// Reduce to implicit settings
current_font = real_current_font;
current_font.reduce(layoutfont); // And resolve it completely
real_current_font.realize(layoutfont); return;
}
LyXCursor tmpcursor = cursor; /* store the current cursor */
/* ok we have a selection. This is always between sel_start_cursor
* and sel_end cursor */
SetUndo(Undo::EDIT,
sel_start_cursor.par->ParFromPos(sel_start_cursor.pos)->previous,
sel_end_cursor.par->ParFromPos(sel_end_cursor.pos)->next);
cursor = sel_start_cursor; while (cursor.par != sel_end_cursor.par ||
(cursor.par->footnoteflag == sel_start_cursor.par->footnoteflag
&& cursor.pos < sel_end_cursor.pos))
{ if (cursor.pos < cursor.par->Last()
&& cursor.par->footnoteflag
== sel_start_cursor.par->footnoteflag) { /* an open footnote *shouldbehave
* like a closed */
LyXFont newfont = GetFont(cursor.par,cursor.pos);
newfont.update(font,toggleall);
SetCharFont(cursor.par, cursor.pos, newfont);
cursor.pos++;
} else {
cursor.pos = 0;
cursor.par = cursor.par->Next();
}
}
/* we have to reset the selection, because the
* geometry could have changed */
SetCursor(sel_start_cursor.par, sel_start_cursor.pos);
sel_cursor = cursor;
SetCursor(sel_end_cursor.par, sel_end_cursor.pos);
ClearSelection();
SetSelection();
SetCursor(tmpcursor.par, tmpcursor.pos);
}
void LyXText::RedoHeightOfParagraph(LyXCursor cursor)
{
Row *tmprow;
LyXParagraph *first_phys_par; long y;
tmprow = cursor.row;
y = cursor.y - tmprow->baseline;
SetHeightOfRow(tmprow);
first_phys_par = tmprow->par->FirstPhysicalPar(); /* find the first row of the paragraph */ if (first_phys_par != tmprow->par) while (tmprow->previous && tmprow->previous->par != first_phys_par) {
tmprow = tmprow->previous;
y -= tmprow->height;
SetHeightOfRow(tmprow);
} while (tmprow->previous && tmprow->previous->par == first_phys_par) {
tmprow = tmprow->previous;
y -= tmprow->height;
SetHeightOfRow(tmprow);
}
/* we can set the refreshing parameters now */
status = LyXText::NEED_MORE_REFRESH;
refresh_y = y;
refresh_row = tmprow;
SetCursor(cursor.par, cursor.pos);
}
void LyXText::RedoDrawingOfParagraph(LyXCursor cursor)
{
Row *tmprow;
LyXParagraph *first_phys_par; long y;
tmprow = cursor.row;
y = cursor.y - tmprow->baseline;
SetHeightOfRow(tmprow);
first_phys_par = tmprow->par->FirstPhysicalPar(); /* find the first row of the paragraph */ if (first_phys_par != tmprow->par) while (tmprow->previous && tmprow->previous->par != first_phys_par) {
tmprow = tmprow->previous;
y -= tmprow->height;
} while (tmprow->previous && tmprow->previous->par == first_phys_par) {
tmprow = tmprow->previous;
y -= tmprow->height;
}
/* we can set the refreshing parameters now */ if (status == LyXText::UNCHANGED || y < refresh_y) {
refresh_y = y;
refresh_row = tmprow;
}
status = LyXText::NEED_MORE_REFRESH;
SetCursor(cursor.par, cursor.pos);
}
/* deletes and inserts again all paragaphs between the cursor *andthespecifiedpar
* This function is needed after SetLayout and SetFont etc. */ void LyXText::RedoParagraphs(LyXCursor cursor, LyXParagraph *endpar)
{
Row *tmprow, *tmprow2;
LyXParagraph *tmppar, *first_phys_par; long y;
tmprow = cursor.row;
y = cursor.y - tmprow->baseline;
if (!tmprow->previous){
first_phys_par = FirstParagraph(); // a trick/hack for UNDO
} else {
first_phys_par = tmprow->par->FirstPhysicalPar(); /* find the first row of the paragraph */ if (first_phys_par != tmprow->par) while (tmprow->previous && tmprow->previous->par != first_phys_par) {
tmprow = tmprow->previous;
y -= tmprow->height;
} while (tmprow->previous && tmprow->previous->par == first_phys_par) {
tmprow = tmprow->previous;
y -= tmprow->height;
}
}
/* we can set the refreshing parameters now */
status = LyXText::NEED_MORE_REFRESH;
refresh_y = y;
refresh_row = tmprow->previous; /* the real refresh row will *bedeleted,soIstore
* the previous here */ /* remove it */ if (tmprow->next)
tmppar = tmprow->next->par; else
tmppar = NULL; while (tmppar != endpar) {
RemoveRow(tmprow->next); if (tmprow->next)
tmppar = tmprow->next->par; else
tmppar = NULL;
}
/* remove the first one */
tmprow2 = tmprow; /* this is because tmprow->previous
* can be NULL */
tmprow = tmprow->previous;
RemoveRow(tmprow2);
tmppar = first_phys_par;
do { if (tmppar) {
InsertParagraph(tmppar, tmprow); if (!tmprow)
tmprow = firstrow; while (tmprow->next && tmprow->next->par == tmppar)
tmprow = tmprow->next;
tmppar = tmppar->Next();
}
} while (tmppar != endpar);
/* this is because of layout changes */ if (refresh_row) {
refresh_y -= refresh_row->height;
SetHeightOfRow(refresh_row);
} else {
refresh_row = firstrow;
refresh_y = 0;
SetHeightOfRow(refresh_row);
}
if (tmprow && tmprow->next)
SetHeightOfRow(tmprow->next);
/* restore the correct refresh row */ /* if (refresh_row) refresh_row=refresh_row->next; else
refresh_row = firstrow;*/
}
int LyXText::FullRebreak()
{ if (need_break_row) {
BreakAgain(need_break_row);
need_break_row = NULL; return1;
} return0;
}
/* important for the screen */
/* the cursor set functions have a special mechanism. When they *realize,thatyouleftanemptyparagraph,theywilldeleteit.
* They also delet the corresponding row */
/* need the selection cursor: */ void LyXText::SetSelection()
{ if (!selection) {
last_sel_cursor = sel_cursor;
sel_start_cursor = sel_cursor;
sel_end_cursor = sel_cursor;
}
selection = True;
/* first the toggling area */ if (cursor.y < last_sel_cursor.y ||
(cursor.y == last_sel_cursor.y && cursor.x < last_sel_cursor.x)) {
toggle_end_cursor = last_sel_cursor;
toggle_cursor = cursor;
} else {
toggle_end_cursor = cursor;
toggle_cursor = last_sel_cursor;
}
/* a selection with no contents is not a selection */ if (sel_start_cursor.x == sel_end_cursor.x &&
sel_start_cursor.y == sel_end_cursor.y)
selection = false;
}
/* returns a pointer to the row near the specified y-coordinate *(relativetothewholetext).yissettotherealbeginning
* of this row */
Row* LyXText::GetRowNearY(long& y)
{
Row* tmprow; long tmpy;
y = tmpy; /* return the real y */ return tmprow;
}
void LyXText::ToggleFree(LyXFont font, bool toggleall)
{ // If the mask is completely neutral, tell user if (font == LyXFont(LyXFont::ALL_IGNORE)){ // Could only happen with user style
minibuffer->Set(_("No font change defined. Use Character under" " the Layout menu to define font change.")); return;
}
// Try implicit word selection
LyXCursor resetCursor = cursor; int implicitSelection = SelectWordWhenUnderCursor();
// Set font
SetFont(font,toggleall); //minibuffer->Set(_("Font style changed"));
/* Implicit selections are cleared afterwards and cursor is set to the
original position. */ if (implicitSelection) {
ClearSelection();
cursor = resetCursor;
SetCursor( cursor.par, cursor.pos );
sel_cursor = cursor;
}
}
int LyXText::BeginningOfMainBody(LyXParagraph *par)
{ if (lyxstyle.Style(parameters->textclass, par->GetLayout())->labeltype != LABEL_MANUAL) return0; else return par->BeginningOfMainBody();
}
/* if there is a selection, reset every environment you can find
* in the selection, otherwise just the environment you are in */ void LyXText::MeltFootnoteEnvironment()
{
LyXParagraph *tmppar, *firsttmppar;
ClearSelection();
/* is is only allowed, if the cursor is IN an open footnote.
* Otherwise it is too dangerous */ if (cursor.par->footnoteflag != LyXParagraph::OPEN_FOOTNOTE) return;
while (tmppar->next && tmppar->next->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
tmppar = tmppar->next; /* I use next instead of Next(), *becausetherecannotbeany *footnotesinafootnote
* environment */
tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE;
/* remember the captions and empty paragraphs */ if ((lyxstyle.Style(parameters->textclass,
tmppar->GetLayout())->labeltype == LABEL_SENSITIVE)
|| !tmppar->Last())
tmppar->SetLayout(0);
}
/* now we will paste the ex-footnote, if the layouts allow it */ /* first restore the layout of the paragraph right behind the footnote*/ if (tmppar->next)
tmppar->next->MakeSameLayout(cursor.par);
/* first the end */ if ((!tmppar->GetLayout() && !tmppar->table)
|| (tmppar->Next() && (!tmppar->Next()->Last()
|| tmppar->Next()->HasSameLayout(tmppar)))) { if (tmppar->Next()->Last() && tmppar->Next()->IsLineSeparator(0))
tmppar->Next()->Erase(0);
tmppar->PasteParagraph();
}
tmppar = tmppar->Next(); /* make shure tmppar cannot be touched
* by the pasting of the beginning */
/* then the beginning */ /* if there is no space between the text and the footnote, so we insert *ablank
* (only if the previous par and the footnotepar are not empty!) */ if ((!firsttmppar->next->GetLayout() && !firsttmppar->next->table)
|| firsttmppar->HasSameLayout(firsttmppar->next)) { if (firsttmppar->last
&& !firsttmppar->IsSeparator(firsttmppar->last - 1)
&& first_footnote_par_is_not_empty) {
firsttmppar->next->InsertChar(0, ' ');
}
firsttmppar->PasteParagraph();
}
/* now redo the paragaphs */
RedoParagraphs(cursor, tmppar);
SetCursor(cursor.par, cursor.pos);
/* sometimes it can happen, that there is a counter change */
Row *row = cursor.row; while (row->next && row->par != tmppar && row->next->par != tmppar)
row = row->next;
UpdateCounters(row);
ClearSelection();
}
/* the DTP switches for paragraphs. LyX will store them in the *firstphysiclaparagraph.Whenaparagraphisbroken,thetopsettings *rest,thebottomsettingsaregiventothenewone.SoIcanmakeshure, *theydonotduplicatethemselfandyoucannnotmakedirtythingswith
* them! */
// make sure that the depth behind the selection are restored, too
LyXParagraph *endpar = sel_end_cursor.par->LastPhysicalPar()->Next();
LyXParagraph *undoendpar = endpar;
if (endpar && endpar->GetDepth()) { while (endpar && endpar->GetDepth()) {
endpar = endpar->LastPhysicalPar()->Next();
undoendpar = endpar;
}
} elseif (endpar) {
endpar = endpar->Next(); /* because of parindents etc. */
}
// make sure that the depth behind the selection are restored, too
LyXParagraph *endpar = sel_end_cursor.par->LastPhysicalPar()->Next();
LyXParagraph *undoendpar = endpar;
if (endpar && endpar->GetDepth()) { while (endpar && endpar->GetDepth()) {
endpar = endpar->LastPhysicalPar()->Next();
undoendpar = endpar;
}
} elseif (endpar) {
endpar = endpar->Next(); /* because of parindents etc. */
}
/* copy the prev-counters to this one, unless this is the start of a
footnote or of a bibliography or the very first paragraph */ if (par->Previous()
&& !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
&& par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
&& par->footnotekind == LyXParagraph::FOOTNOTE)
&& !(lyxstyle.Style(parameters->textclass,
par->Previous()->GetLayout()
)->labeltype != LABEL_BIBLIO
&& layout->labeltype == LABEL_BIBLIO)) { for (i=0; i<10; i++) {
par->counter[i]=par->Previous()->GetCounter(i);
}
par->appendix = par->Previous()->FirstPhysicalPar()->appendix; if (!par->appendix && par->start_of_appendix){
par->appendix = true; for (i=0; i<10; i++) {
par->counter[i]=0;
}
}
par->enumdepth = par->Previous()->FirstPhysicalPar()->enumdepth;
par->itemdepth = par->Previous()->FirstPhysicalPar()->itemdepth;
} else { for (i=0; i<10; i++) {
par->counter[i]=0;
}
par->appendix = par->start_of_appendix;
par->enumdepth = 0;
par->itemdepth = 0;
}
// if this is an open marginnote and this is the first // entry in the marginnote and the enclosing // environment is an enum/item then correct for the // LaTeX behaviour (ARRae) if(par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
&& par->footnotekind == LyXParagraph::MARGIN
&& par->Previous()
&& par->Previous()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE
&& (par->PreviousBeforeFootnote()
&& lyxstyle.Style(parameters->textclass,
par->PreviousBeforeFootnote()->GetLayout()
)->labeltype >= LABEL_COUNTER_ENUMI)) { // Any itemize or enumerate environment in a marginnote // that is embedded in an itemize or enumerate // paragraph is seen by LaTeX as being at a deeper // level within that enclosing itemization/enumeration // even if there is a "standard" layout at the start of // the marginnote.
par->enumdepth++;
par->itemdepth++;
}
/* Maybe we have to increment the enumeration depth. *BUT,enumerationinafootnoteisconsideredinisolationfromits *surroundingparagraphsodon'tincrementifthisisthe *firstlineofthefootnote *AND,bibliographiescan'thavetheirdepthchangedie.they *arealwaysofdepth0
*/ if (par->Previous()
&& par->Previous()->GetDepth() < par->GetDepth()
&& lyxstyle.Style(parameters->textclass,
par->Previous()->GetLayout()
)->labeltype == LABEL_COUNTER_ENUMI
&& par->enumdepth < 3
&& !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
&& par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
&& par->footnotekind == LyXParagraph::FOOTNOTE)
&& layout->labeltype != LABEL_BIBLIO) {
par->enumdepth++;
}
/* Maybe we have to decrement the enumeration depth, see note above */ if (par->Previous()
&& par->Previous()->GetDepth() > par->GetDepth()
&& !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
&& par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
&& par->footnotekind == LyXParagraph::FOOTNOTE)
&& layout->labeltype != LABEL_BIBLIO) {
par->enumdepth = par->DepthHook(par->GetDepth())->enumdepth;
par->counter[6 + par->enumdepth] =
par->DepthHook(par->GetDepth())->counter[6 + par->enumdepth]; /* reset the counters. *Adepthchangeislikeabreakinglayout
*/ for (i=6 + par->enumdepth + 1; i<10;i++)
par->counter[i]=0;
}
if (!par->labelstring.empty()) {
par->labelstring.clean();
}
if (layout->margintype == MARGIN_MANUAL) { if (par->labelwidthstring.empty()) {
par->SetLabelWidthString(layout->labelstring);
}
} else {
par->SetLabelWidthString(LString());
}
/* is it a layout that has an automatic label ? */ if (layout->labeltype >= LABEL_FIRST_COUNTER) {
i = layout->labeltype - LABEL_FIRST_COUNTER; if (i>=0 && i<=parameters->secnumdepth) {
par->counter[i]++; // increment the counter
char * s = newchar[50];
// Is there a label? Useful for Chapter layout if (!par->appendix){ if (!layout->labelstring.empty())
par->labelstring = layout->labelstring; else
par->labelstring.clean();
} else { if (!layout->labelstring_appendix.empty())
par->labelstring = layout->labelstring_appendix; else
par->labelstring.clean();
}
if (!par->appendix){ switch (2 * LABEL_FIRST_COUNTER -
textclass->maxcounter + i) { case LABEL_COUNTER_CHAPTER:
sprintf(s, "%d", par->counter[i]); break; case LABEL_COUNTER_SECTION:
sprintf(s, "%d.%d", par->counter[i - 1], par->counter[i]); break; case LABEL_COUNTER_SUBSECTION:
sprintf(s, "%d.%d.%d", par->counter[i-2], par->counter[i-1],par->counter[i]); break; case LABEL_COUNTER_SUBSUBSECTION:
sprintf(s, "%d.%d.%d.%d", par->counter[i-3], par->counter[i-2],par->counter[i-1],par->counter[i]); break; case LABEL_COUNTER_PARAGRAPH:
sprintf(s, "%d.%d.%d.%d.%d", par->counter[i-4], par->counter[i-3], par->counter[i-2],par->counter[i-1],par->counter[i]); break; case LABEL_COUNTER_SUBPARAGRAPH:
sprintf(s, "%d.%d.%d.%d.%d.%d", par->counter[i-5], par->counter[i-4], par->counter[i-3], par->counter[i-2],par->counter[i-1],par->counter[i]); break; default:
sprintf(s, "%d.", par->counter[i]); break;
}
} else { switch (2 * LABEL_FIRST_COUNTER - textclass->maxcounter+ i) { case LABEL_COUNTER_CHAPTER:
sprintf(s, "%s", alphaCounter(par->counter[i])); break; case LABEL_COUNTER_SECTION:
sprintf(s, "%s.%d", alphaCounter(par->counter[i - 1]), par->counter[i]); break; case LABEL_COUNTER_SUBSECTION:
sprintf(s, "%s.%d.%d", alphaCounter(par->counter[i-2]), par->counter[i-1],par->counter[i]); break; case LABEL_COUNTER_SUBSUBSECTION:
sprintf(s, "%s.%d.%d.%d", alphaCounter(par->counter[i-3]), par->counter[i-2],par->counter[i-1],par->counter[i]); break; case LABEL_COUNTER_PARAGRAPH:
sprintf(s, "%s.%d.%d.%d.%d", alphaCounter(par->counter[i-4]), par->counter[i-3], par->counter[i-2],par->counter[i-1],par->counter[i]); break; case LABEL_COUNTER_SUBPARAGRAPH:
sprintf(s, "%s.%d.%d.%d.%d.%d", alphaCounter(par->counter[i-5]), par->counter[i-4], par->counter[i-3], par->counter[i-2],par->counter[i-1],par->counter[i]); break; default:
sprintf(s, "%c.", par->counter[i]); break;
}
}
for (i += par->enumdepth + 1;i<10;i++)
par->counter[i]=0; /* reset the following counters */
}
} elseif (layout->labeltype == LABEL_BIBLIO) {// ale970302
i = LABEL_COUNTER_ENUMI - LABEL_FIRST_COUNTER + par->enumdepth;
par->counter[i]++; int number = par->counter[i]; if (!par->bibkey)
par->bibkey = new InsetBibKey();
par->bibkey->setCounter(number);
par->labelstring = layout->labelstring;
// In biblio should't be following counters but...
} else {
LString s = layout->labelstring;
/* the caption hack: */
if (layout->labeltype == LABEL_SENSITIVE) { if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
&& (par->footnotekind == LyXParagraph::FIG
|| par->footnotekind == LyXParagraph::WIDE_FIG))
s = "Figure:"; elseif (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
&& (par->footnotekind == LyXParagraph::TAB
|| par->footnotekind == LyXParagraph::WIDE_TAB))
s = "Table:"; elseif (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
&& par->footnotekind == LyXParagraph::ALGORITHM)
s = "Algorithm:"; else { /* par->SetLayout(0);
s = layout->labelstring; */
s = "Senseless: ";
}
}
par->labelstring = s;
/* reset the enumeration counter. They are always resetted
* when there is any other layout between */ for (i=6 + par->enumdepth; i<10;i++)
par->counter[i]=0;
}
}
/* Updates all counters BEHIND the row. Changed paragraphs
* with a dynamic left margin will be rebroken. */ void LyXText::UpdateCounters(Row *row)
{
LyXParagraph *par; if (!row) {
row = firstrow;
par = row->par;
} else { if (row->par->next && row->par->next->footnoteflag != LyXParagraph::OPEN_FOOTNOTE) {
par = row->par->LastPhysicalPar()->Next();
} else {
par = row->par->next;
}
}
while (par) { while (row->par != par)
row = row->next;
SetCounter(par);
/* now check for the headline layouts. remember that they
* have a dynamic left margin */ if (!par->IsDummy()
&& ( lyxstyle.Style(parameters->textclass, par->layout)->margintype == MARGIN_DYNAMIC
|| lyxstyle.Style(parameters->textclass, par->layout)->labeltype == LABEL_SENSITIVE)
){
/* Rebreak the paragraph */
RemoveParagraph(row);
AppendParagraph(row);
/* think about the damned open footnotes! */ while (par->Next() &&
(par->Next()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
|| par->Next()->IsDummy())){
par = par->Next(); if (par->IsDummy()) { while (row->par != par)
row = row->next;
RemoveParagraph(row);
AppendParagraph(row);
}
}
}
par = par->LastPhysicalPar()->Next();
}
}
/* insets an inset. */ void LyXText::InsertInset(Inset *inset)
{
SetUndo(Undo::INSERT,
cursor.par->ParFromPos(cursor.pos)->previous,
cursor.par->ParFromPos(cursor.pos)->next);
cursor.par->InsertChar(cursor.pos, LYX_META_INSET);
cursor.par->InsertInset(cursor.pos, inset);
InsertChar(LYX_META_INSET); /* just to rebreak and refresh correctly. *Thecharacterwillnotbeinserteda
* second time */
}
/* this is for the simple cut and paste mechanism */ static LyXParagraph *simple_cut_buffer = NULL; staticchar simple_cut_buffer_textclass = 0;
void DeleteSimpleCutBuffer()
{ if (!simple_cut_buffer) return;
LyXParagraph *tmppar;
void LyXText::CutSelection(bool doclear)
{ /* This doesn't make sense, if there is no selection */ if (!selection) { return;
}
/* OK, we have a selection. This is always between sel_start_cursor
* and sel_end cursor */
LyXParagraph *tmppar; int i;
/* Check whether there are half footnotes in the selection */ if (sel_start_cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE
|| sel_end_cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE){
tmppar = sel_start_cursor.par; while (tmppar != sel_end_cursor.par){ if (tmppar->footnoteflag != sel_end_cursor.par->footnoteflag){
WriteAlert(_("Impossible operation"), _("Don't know what to do with half floats."), _("sorry.")); return;
}
tmppar = tmppar->Next();
}
}
/* table stuff -- begin*/ if (sel_start_cursor.par->table || sel_end_cursor.par->table){ if ( sel_start_cursor.par != sel_end_cursor.par){
WriteAlert(_("Impossible operation"), _("Don't know what to do with half tables."), _("sorry.")); return;
}
sel_start_cursor.par->table->Reinit();
} /* table stuff -- end*/
// make sure that the depth behind the selection are restored, too
LyXParagraph *endpar = sel_end_cursor.par->LastPhysicalPar()->Next();
LyXParagraph *undoendpar = endpar;
if (endpar && endpar->GetDepth()) { while (endpar && endpar->GetDepth()) {
endpar = endpar->LastPhysicalPar()->Next();
undoendpar = endpar;
}
} elseif (endpar) {
endpar = endpar->Next(); /* because of parindents etc. */
}
char space_wrapped =
sel_end_cursor.par->IsLineSeparator(sel_end_cursor.pos); if (sel_end_cursor.pos > 0
&& sel_end_cursor.par->IsLineSeparator(sel_end_cursor.pos - 1)) {
sel_end_cursor.pos--; /* please break before a space at
* the end */
space_wrapped = True;
}
// cut behind a space if there is one while (sel_start_cursor.par->Last() > sel_start_cursor.pos
&& sel_start_cursor.par->IsLineSeparator(sel_start_cursor.pos)
&& (sel_start_cursor.par != sel_end_cursor.par
|| sel_start_cursor.pos < sel_end_cursor.pos))
sel_start_cursor.pos++;
/* there are two cases: cut only within one paragraph or
* more than one paragraph */
if (sel_start_cursor.par->ParFromPos(sel_start_cursor.pos)
== sel_end_cursor.par->ParFromPos(sel_end_cursor.pos)) { /* only within one paragraph */
simple_cut_buffer = new LyXParagraph(); for (i=sel_start_cursor.pos; i< sel_end_cursor.pos; i++){ /* table stuff -- begin*/ if (sel_start_cursor.par->table
&& sel_start_cursor.par->IsNewline(sel_start_cursor.pos)){
sel_start_cursor.par->CopyIntoMinibuffer(sel_start_cursor.pos);
sel_start_cursor.pos++;
} else { /* table stuff -- end*/
sel_start_cursor.par->CopyIntoMinibuffer(sel_start_cursor.pos);
sel_start_cursor.par->Erase(sel_start_cursor.pos);
}
simple_cut_buffer->InsertFromMinibuffer(simple_cut_buffer->Last());
} /* check for double spaces */ if (sel_start_cursor.pos &&
sel_start_cursor.par->Last()>sel_start_cursor.pos &&
sel_start_cursor.par->IsLineSeparator(sel_start_cursor.pos - 1) &&
sel_start_cursor.par->IsLineSeparator(sel_start_cursor.pos)){
sel_start_cursor.par->Erase(sel_start_cursor.pos);
} if (space_wrapped)
simple_cut_buffer->InsertChar(i - sel_start_cursor.pos, ' ');
endpar = sel_end_cursor.par->Next();
} else { /* cut more than one paragraph */
sel_end_cursor.par->BreakParagraphConservative(sel_end_cursor.pos); /* insert a space at the end if there was one */ if (space_wrapped)
sel_end_cursor.par->InsertChar(sel_end_cursor.par->Last(), ' ');
/* please break behind a space, if there is one. The space should
* be copied too */ if (sel_start_cursor.par->IsLineSeparator(sel_start_cursor.pos))
sel_start_cursor.pos++;
/* care about footnotes */ if (simple_cut_buffer->footnoteflag) {
LyXParagraph *tmppar = simple_cut_buffer; while (tmppar){
tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE;
tmppar = tmppar->next;
}
}
/* the cut selection should begin with standard layout */
simple_cut_buffer->Clear();
/* paste the paragraphs again, if possible */ if (doclear)
sel_start_cursor.par->Next()->ClearParagraph(); if (sel_start_cursor.par->FirstPhysicalPar()->HasSameLayout(sel_start_cursor.par->Next())
||
!sel_start_cursor.par->Next()->Last())
sel_start_cursor.par->ParFromPos(sel_start_cursor.pos)->PasteParagraph();
/* maybe a forgotten blank */ if (sel_start_cursor.pos
&& sel_start_cursor.par->IsLineSeparator(sel_start_cursor.pos)
&& sel_start_cursor.par->IsLineSeparator(sel_start_cursor.pos - 1)) {
sel_start_cursor.par->Erase(sel_start_cursor.pos);
}
}
/* sometimes necessary */ if (doclear)
sel_start_cursor.par->ClearParagraph();
/* this doesnt make sense, if there is no selection */ if (!selection) { return;
}
/* ok we have a selection. This is always between sel_start_cursor
* and sel_end cursor */
LyXParagraph *tmppar;
/* check wether there are half footnotes in the selection */ if (sel_start_cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE
|| sel_end_cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE){
tmppar = sel_start_cursor.par; while (tmppar != sel_end_cursor.par){ if (tmppar->footnoteflag != sel_end_cursor.par->footnoteflag){
WriteAlert(_("Impossible operation"), _("Don't know what to do with half floats."), _("sorry.")); return;
}
tmppar = tmppar->Next();
}
}
/* table stuff -- begin*/ if (sel_start_cursor.par->table || sel_end_cursor.par->table){ if ( sel_start_cursor.par != sel_end_cursor.par){
WriteAlert(_("Impossible operation"), _("Don't know what to do with half tables."), _("sorry.")); return;
}
} /* table stuff -- end*/
/* delete the simple_cut_buffer */
DeleteSimpleCutBuffer();
/* set the textclass */
simple_cut_buffer_textclass = parameters->textclass;
// copy behind a space if there is one while (sel_start_cursor.par->Last() > sel_start_cursor.pos
&& sel_start_cursor.par->IsLineSeparator(sel_start_cursor.pos)
&& (sel_start_cursor.par != sel_end_cursor.par
|| sel_start_cursor.pos < sel_end_cursor.pos))
sel_start_cursor.pos++;
/* there are two cases: copy only within one paragraph or more than one paragraph */ if (sel_start_cursor.par->ParFromPos(sel_start_cursor.pos)
== sel_end_cursor.par->ParFromPos(sel_end_cursor.pos)) { /* only within one paragraph */
simple_cut_buffer = new LyXParagraph(); for (i=sel_start_cursor.pos; i< sel_end_cursor.pos; i++){
sel_start_cursor.par->CopyIntoMinibuffer(i);
simple_cut_buffer->InsertFromMinibuffer(i - sel_start_cursor.pos);
}
} else { /* copy more than one paragraph */ /* clone the paragraphs within the selection*/
tmppar = sel_start_cursor.par->ParFromPos(sel_start_cursor.pos);
simple_cut_buffer = tmppar->Clone();
LyXParagraph *tmppar2 = simple_cut_buffer;
/* care about footnotes */ if (simple_cut_buffer->footnoteflag) {
tmppar = simple_cut_buffer; while (tmppar){
tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE;
tmppar = tmppar->next;
}
}
/* the simple_cut_buffer paragraph is too big */ int tmpi2;
tmpi2 = sel_start_cursor.par->PositionInParFromPos(sel_start_cursor.pos); for (;tmpi2;tmpi2--)
simple_cut_buffer->Erase(0);
/* now tmppar 2 is too big, delete all after sel_end_cursor.pos */
tmpi2 = sel_end_cursor.par->PositionInParFromPos(sel_end_cursor.pos); while (tmppar2->last > tmpi2) {
tmppar2->Erase(tmppar2->last-1);
}
}
}
void LyXText::PasteSelection()
{ /* this does not make sense, if there is nothing to paste */ if (!simple_cut_buffer) return;
LyXParagraph *tmppar;
LyXParagraph *endpar;
LyXCursor tmpcursor;
/* be carefull with footnotes in footnotes */ if (cursor.par->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
/* check whether the cut_buffer includes a footnote */
tmppar = simple_cut_buffer; while (tmppar && tmppar->footnoteflag == LyXParagraph::NO_FOOTNOTE)
tmppar = tmppar->next;
if (tmppar) {
WriteAlert(_("Impossible operation"),
_("Can't paste float into float!"), _("Sorry.")); return;
}
}
/* table stuff -- begin*/ if (cursor.par->table){ if (simple_cut_buffer->next){
WriteAlert(_("Impossible operation"),
_("Table cell cannot include more than one paragraph!"),
_("Sorry.")); return;
}
} /* table stuff -- end*/
/* There are two cases: cutbuffer only one paragraph or many */ if (!simple_cut_buffer->next) { /* only within a paragraph */
/* please break behind a space, if there is one */ while (tmpcursor.par->Last() > tmpcursor.pos
&& tmpcursor.par->IsLineSeparator(tmpcursor.pos))
tmpcursor.pos++;
/* make a copy of the simple cut_buffer */
tmppar = simple_cut_buffer;
LyXParagraph *simple_cut_clone = tmppar->Clone();
LyXParagraph *tmppar2 = simple_cut_clone; if (cursor.par->footnoteflag){
tmppar->footnoteflag = cursor.par->footnoteflag;
tmppar->footnotekind = cursor.par->footnotekind;
} while (tmppar->next) {
tmppar = tmppar->next;
tmppar2->next = tmppar->Clone();
tmppar2->next->previous = tmppar2;
tmppar2=tmppar2->next; if (cursor.par->footnoteflag){
tmppar->footnoteflag = cursor.par->footnoteflag;
tmppar->footnotekind = cursor.par->footnotekind;
}
}
/* make sure there is no class difference */
SwitchLayoutsBetweenClasses(simple_cut_buffer_textclass,
parameters->textclass,
simple_cut_buffer);
/* make the simple_cut_buffer exactly the same layout than
the cursor paragraph */
simple_cut_buffer->MakeSameLayout(cursor.par);
/* find the end of the buffer */
LyXParagraph *lastbuffer = simple_cut_buffer; while (lastbuffer->Next())
lastbuffer=lastbuffer->Next();
/* find the physical end of the buffer */
lastbuffer = simple_cut_buffer; while (lastbuffer->Next())
lastbuffer=lastbuffer->Next();
/* please break behind a space, if there is one. The space
* should be copied too */ if (cursor.par->Last() > cursor.pos && cursor.par->IsLineSeparator(cursor.pos))
cursor.pos++;
bool paste_the_end = false;
/* open the paragraph for inserting the simple_cut_buffer
if necessary */ if (cursor.par->Last() > cursor.pos || !cursor.par->Next()){
cursor.par->BreakParagraphConservative(cursor.pos);
paste_the_end = true;
}
/* be careful with double spaces */ if ((!cursor.par->Last()
|| cursor.par->IsLineSeparator(cursor.pos - 1)
|| cursor.par->IsNewline(cursor.pos - 1))
&& simple_cut_buffer->last
&& simple_cut_buffer->IsLineSeparator(0))
simple_cut_buffer->Erase(0);
/* set the end for redoing later */
endpar = cursor.par->ParFromPos(cursor.pos)->next->Next();
/* returns a pointer to the very first LyXParagraph */
LyXParagraph* LyXText::FirstParagraph()
{ return params->paragraph;
}
/* returns true if the specified string is at the specified position */ bool LyXText::IsStringInText(LyXParagraph *par, int pos, charconst* string)
{ if (par) { int i = 0; while (pos+i < par->Last() && string[i] &&
string[i]==par->GetChar(pos+i))
{
i++;
}
if (!string[i]) returntrue;
} returnfalse;
}
/* sets the selection over the number of characters of string, no check!! */ void LyXText::SetSelectionOverString(charconst* string)
{
sel_cursor = cursor; int i; for (i=0; string[i]; i++)
CursorRight();
SetSelection();
}
/* simple replacing. The font of the first selected character is used */ void LyXText::ReplaceSelectionWithString(charconst* string)
{
SetCursorParUndo();
FreezeUndo();
if (!selection) { /* create a dummy selection */
sel_end_cursor = cursor;
sel_start_cursor = cursor;
}
// Get font setting before we cut int pos = sel_end_cursor.pos;
LyXFont font = sel_start_cursor.par->GetFontSettings(sel_start_cursor.pos);
// Insert the new string for (int i=0; string[i];i++) {
sel_end_cursor.par->InsertChar(pos, string[i]);
sel_end_cursor.par->SetFont(pos, font);
pos++;
}
// Cut the selection
CutSelection();
UnFreezeUndo();
}
/* if the string can be found: return true and set the cursor to
* the new position */ bool LyXText::SearchForward(charconst* string)
{
LyXParagraph *par = cursor.par; int pos = cursor.pos;
while (par && !IsStringInText(par,pos,string)) { if (pos<par->Last()-1)
pos++; else {
pos = 0;
par = par->Next();
}
} if (par) {
SetCursor(par,pos); returntrue;
} else returnfalse;
}
do { if (pos>0)
pos--; else { // We skip empty paragraphs (Asger) do {
par = par->Previous(); if (par)
pos = par->Last()-1;
} while (par && pos<0);
}
} while (par && !IsStringInText(par,pos,string));
if (par) {
SetCursor(par,pos); returntrue;
} else returnfalse;
}
/* needed to insert the selection */ void LyXText::InsertStringA(char* string)
{
LyXParagraph *par = cursor.par; int pos = cursor.pos; int a = 0; int cell = 0;
LyXParagraph *endpar = cursor.par->Next();
SetCursorParUndo();
char flag = lyxstyle.Style(parameters->textclass,
cursor.par->GetLayout())->isEnvironment(); /* only to be sure, should not be neccessary */
ClearSelection();
/* insert the string, don't insert doublespace */ int i=0; int i2 = 0;
for (i2=i;string[i2]&&string[i2]!='\n';i2++);
par->Enlarge(pos, i2 - i); while (string[i]) { if (string[i]!='\n') { if (string[i]==' ' && (string[i+1]!=' ')
&& pos && par->GetChar(pos-1)!=' ') {
par->InsertChar(pos,' ');
pos++;
} elseif (par->table) { if (string[i] == '\t') { while((pos < par->last) &&
(par->GetChar(pos) != LYX_META_NEWLINE))
pos++; if (pos < par->last)
pos++; else// no more fields to fill skip the rest break;
} elseif ((string[i] != 13) &&
(((unsignedchar) string[i] & 127) >= ' ')) {
par->InsertChar(pos,string[i]);
pos++;
}
} elseif (string[i]==' ') {
par->InsertChar(pos,LYX_META_PROTECTED_SEPARATOR);
pos++;
} elseif (string[i]=='\t') { for (a=pos; a<(pos/8+1)*8 ; a++) {
par->InsertChar(a,LYX_META_PROTECTED_SEPARATOR);
}
pos = a;
} elseif (string[i]!=13 && // Ignore unprintables
((unsignedchar) string[i] & 127) >= ' ') {
par->InsertChar(pos,string[i]);
pos++;
}
} else { if (par->table) { if (!string[i+1]) {
pos++; break;
} while((pos < par->last) &&
(par->GetChar(pos) != LYX_META_NEWLINE))
pos++;
pos++;
cell=NumberOfCell(par,pos); while((pos < par->last) &&
!(par->table->IsFirstCell(cell))) { while((pos < par->last) &&
(par->GetChar(pos) != LYX_META_NEWLINE))
pos++;
pos++;
cell=NumberOfCell(par,pos);
} if (pos >= par->last) // no more fields to fill skip the rest break;
} else { if (!par->last) {
par->InsertChar(pos,LYX_META_PROTECTED_SEPARATOR);
pos++;
}
par->BreakParagraph(pos, flag);
par = par->Next();
pos = 0;
} for (i2=i;string[i2]&&string[i2]!='\n';i2++);
par->Enlarge(pos, i2 - i);
}
} while (res.par &&
!(res.par->GetChar(res.pos)==LYX_META_INSET
&& res.par->GetInset(res.pos)->LyxCode()==Inset::IGNORE_CODE));
if (res.par) {
SetCursor(res.par, res.pos); returntrue;
}
returnfalse;
}
int LyXText::SwitchLayoutsBetweenClasses(char class1, char class2,
LyXParagraph *par)
{
InsetError * new_inset = NULL; int ret = 0; if (!par || class1 == class2) return ret;
par = par->FirstPhysicalPar(); while (par) {
LString name = lyxstyle.NameOfLayout(class1, par->layout); int lay = lyxstyle.NumberOfLayout(class2, name); if (lay == -1) // layout not found // use default layout "Stadard" (0)
lay = 0;
par->layout = lay;
if (name != lyxstyle.NameOfLayout(class2, par->layout)) {
ret++;
LString s= "Layout had to be changed from\n"
+ name + " to " + lyxstyle.NameOfLayout(class2, par->layout)
+ "\nbecause of class conversion from\n"
+ lyxstyle.NameOfClass(class1) + " to "
+ lyxstyle.NameOfClass(class2);
new_inset = new InsetError(s);
par->InsertChar(0, LYX_META_INSET);
par->InsertInset(0, new_inset);
}
par = par->next;
} return ret;
}
void LyXText::CheckParagraph(LyXParagraph* par, int pos)
{
/* is there a break one row above */ if (row->previous && row->previous->par == row->par) {
z = NextBreakPoint(row->previous, paperwidth); if ( z >= row->pos) { /* set the dimensions of the row above */
y -= row->previous->height;
refresh_y = y;
refresh_row = row->previous;
status = LyXText::NEED_MORE_REFRESH;
BreakAgain(row->previous);
/* set the cursor again. Otherwise dungling pointers are possible */
SetCursor(cursor.par, cursor.pos);
sel_cursor = cursor; return;
}
}
int tmpheight = row->height; int tmplast = RowLast(row);
refresh_y = y;
refresh_row = row;
BreakAgain(row); if (row->height == tmpheight && RowLast(row) == tmplast)
status = LyXText::NEED_VERY_LITTLE_REFRESH; else
status = LyXText::NEED_MORE_REFRESH;
/* check the special right address boxes */ if (lyxstyle.Style(parameters->textclass, par->GetLayout())->margintype == MARGIN_RIGHT_ADDRESS_BOX) {
tmpcursor.par = par;
tmpcursor.row = row;
tmpcursor.y = y;
tmpcursor.x = 0;
tmpcursor.x_fix = 0;
tmpcursor.pos = pos;
RedoDrawingOfParagraph(tmpcursor);
}
}
/* set the cursor again. Otherwise dangling pointers are possible */ // also set the selection
/* returns 0 if inset wasn't found */ int LyXText::UpdateInset(Inset* inset)
{ int pos;
LyXParagraph *par;
/* first check the current paragraph */
pos = cursor.par->GetPositionOfInset(inset); if (pos != -1){
CheckParagraph(cursor.par, pos); return1;
}
/* check every paragraph */
par = FirstParagraph(); do { /* make sure the paragraph is open */ if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
pos = par->GetPositionOfInset(inset); if (pos != -1){
CheckParagraph(par, pos); return1;
}
}
par = par->Next();
} while (par);
void LyXText::SetCursorIntern(LyXParagraph *par, int pos)
{ long y;
Row *row; int left_margin;
LyXParagraph *tmppar;
/* correct the cursor position if impossible */ if (pos > par->Last()){
tmppar = par->ParFromPos(pos);
pos = par->PositionInParFromPos(pos);
par = tmppar;
} if (par->IsDummy() && par->previous &&
par->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) { while (par->previous &&
par->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
par = par->previous ;
} if (par->previous) {
par = par->previous;
}
pos += par->last + 1;
}
cursor.par = par;
cursor.pos = pos;
/* get the cursor y position in text */
row = GetRow(par, pos, y); /* y is now the beginning of the cursor row */
y += row->baseline; /* y is now the cursor baseline */
cursor.y = y;
/* this is the delete-empty-paragraph-mechanism. */ if (selection) return;
// Paragraph should not be deleted if empty if ((lyxstyle.Style(parameters->textclass,
old_cursor.par->GetLayout()))->keepempty) return;
LyXCursor tmpcursor;
if (old_cursor.par != cursor.par) { if ( (old_cursor.par->Last() == 0
|| (old_cursor.par->Last() == 1
&& (old_cursor.par->IsLineSeparator(0))))
&& old_cursor.par->FirstPhysicalPar()
== old_cursor.par->LastPhysicalPar() //&& ( // impossible to insert your own \caption with // this set. made it impossible to use the // optional argument... // also empty pars in fig or tab never was removed(?)(Lgb) //lyxstyle.Style(parameters->textclass, // old_cursor.par->GetLayout())->labeltype!=LABEL_SENSITIVE || // (old_cursor.par->footnoteflag == LyXParagraph::NO_FOOTNOTE //|| (old_cursor.par->footnotekind != LyXParagraph::FIG // && old_cursor.par->footnotekind != LyXParagraph::TAB)))
) {
/* ok, we will delete anything */
// make sure that you do not delete any environments if ((old_cursor.par->footnoteflag != LyXParagraph::OPEN_FOOTNOTE &&
!(old_cursor.row->previous
&& old_cursor.row->previous->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
&& !(old_cursor.row->next
&& old_cursor.row->next->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE))
||
(old_cursor.par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE &&
((old_cursor.row->previous
&& old_cursor.row->previous->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
||
(old_cursor.row->next
&& old_cursor.row->next->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE))
)){
status = LyXText::NEED_MORE_REFRESH;
deleted = true;
if (old_cursor.row->previous) {
refresh_row = old_cursor.row->previous;
refresh_y = old_cursor.y - old_cursor.row->baseline - refresh_row->height;
tmpcursor = cursor;
cursor = old_cursor; // that undo can restore the right cursor position
LyXParagraph *endpar = old_cursor.par->next; if (endpar && endpar->GetDepth()) { while (endpar && endpar->GetDepth()) {
endpar = endpar->LastPhysicalPar()->Next();
}
}
SetUndo(Undo::DELETE,
old_cursor.par->previous,
endpar);
cursor = tmpcursor;
/* delete old row */
RemoveRow(old_cursor.row); if (params->paragraph == old_cursor.par) {
params->paragraph = params->paragraph->next;
} /* delete old par */ delete old_cursor.par;
/* Breakagain the next par. Needed *becauseoftheparindentthat *canoccurordissappear.The *nextrowcanchangeitsheight,
* if there is another layout before */ if (refresh_row->next) {
BreakAgain(refresh_row->next);
UpdateCounters(refresh_row);
}
SetHeightOfRow(refresh_row);
} else {
refresh_row = old_cursor.row->next;
refresh_y = old_cursor.y - old_cursor.row->baseline;
tmpcursor = cursor;
cursor = old_cursor; // that undo can restore the right cursor position
LyXParagraph *endpar = old_cursor.par->next; if (endpar && endpar->GetDepth()) { while (endpar && endpar->GetDepth()) {
endpar = endpar->LastPhysicalPar()->Next();
}
}
SetUndo(Undo::DELETE,
old_cursor.par->previous,
endpar);
cursor = tmpcursor;
/* delete old row */
RemoveRow(old_cursor.row); /* delete old par */ if (params->paragraph == old_cursor.par) {
params->paragraph = params->paragraph->next;
} delete old_cursor.par;
/* Breakagain the next par. Needed because of *theparindentthatcanoccurordissappear. *Thenextrowcanchangeitsheight,ifthere
* is another layout before */ if (refresh_row) {
BreakAgain(refresh_row);
UpdateCounters(refresh_row->previous);
}
}
/* correct cursor y */
SetCursor(cursor.par, cursor.pos);
/* if (cursor.y > old_cursor.y)
cursor.y -= old_cursor.row->height; */
// if there's no before take the beginning of the document for redoing if (!before)
SetCursorIntern(FirstParagraph(), 0);
// replace the paragraphs with the undo informations
tmppar3 = undo->par;
undo->par = NULL; // otherwise the undo destructor would delete the paragraph
tmppar4 = tmppar3; if (tmppar4){ while (tmppar4->next)
tmppar4 = tmppar4->next;
} // get last undo par
// now remove the old text if there is any if (before != behind || (!behind && !before)){ if (before)
tmppar5 = before->next; else
tmppar5 = params->paragraph;
tmppar2 = tmppar3; while (tmppar5 && tmppar5 != behind){
tmppar = tmppar5;
tmppar5 = tmppar5->next; // a memory optimization for edit: Only layout information // is stored in the undo. So restore the text informations. if (undo->kind == Undo::EDIT){
tmppar2->text = tmppar->text;
tmppar->text = NULL;
tmppar2 = tmppar2->next;
} if ( currentrow && currentrow->par == tmppar )
currentrow = currentrow -> previous; delete tmppar;
}
}
// put the new stuff in the list if there is one if (tmppar3){ if (before)
before->next = tmppar3; else
params->paragraph = tmppar3;
tmppar3->previous = before;
} else { if (!before)
params->paragraph = behind;
} if (tmppar4) {
tmppar4->next = behind; if (behind)
behind->previous = tmppar4;
}
// Set the cursor for redoing if (before){
SetCursorIntern(before->FirstSelfrowPar(), 0); // check wether before points to a closed float and open it if necessary if (before && before->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE
&& before->next && before->next->footnoteflag != LyXParagraph::NO_FOOTNOTE){
tmppar4 =before; while (tmppar4->previous &&
tmppar4->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
tmppar4 = tmppar4->previous; while (tmppar4 && tmppar4->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
tmppar4->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
tmppar4 = tmppar4->next;
}
}
}
// open a cosed footnote at the end if necessary if (behind && behind->previous &&
behind->previous->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
behind->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){ while (behind && behind->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
behind->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
behind = behind->next;
}
}
// calculate the endpar for redoing the paragraphs. if (behind){ if (behind->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
endpar = behind->LastPhysicalPar()->Next(); else
endpar = behind->NextAfterFootnote()->LastPhysicalPar()->Next();
} else
endpar = behind;
Undo* LyXText::CreateUndo(Undo::undo_kind kind, LyXParagraph *before,
LyXParagraph *behind)
{ int before_number = -1; int behind_number = -1; if (before)
before_number = before->GetID(); if (behind)
behind_number = behind->GetID(); // Undo::EDIT and Undo::FINISH are // always finished. (no overlapping there) // overlapping only with insert and delete inside one paragraph: // Nobody wants all removed character // appear one by one when undoing. // EDIT is special since only layout information, not the // contents of a paragaph are stored. if (!undo_finished && kind != Undo::EDIT &&
kind != Undo::FINISH){ // check wether storing is needed if (params->undostack.Top() &&
params->undostack.Top()->kind == kind &&
params->undostack.Top()->number_of_before_par == before_number &&
params->undostack.Top()->number_of_behind_par == behind_number ){ // no undo needed return NULL;
}
} // create a new Undo
LyXParagraph* undopar;
LyXParagraph* tmppar;
LyXParagraph *tmppar2;
LyXParagraph* start = NULL;
LyXParagraph* end = NULL;
if (before)
start = before->next; else
start = FirstParagraph(); if (behind)
end = behind->previous; else {
end = FirstParagraph(); while (end->next)
end = end->next;
}
// a memory optimization: Just store the layout information when only edit if (kind == Undo::EDIT){ if (tmppar2->text) delete[] tmppar2->text;
tmppar2->text = NULL;
}
undopar = tmppar2;
while (tmppar != end && tmppar->next) {
tmppar = tmppar->next;
tmppar2->next = tmppar->Clone();
tmppar2->next->SetID(tmppar->GetID()); // a memory optimization: Just store the layout information when only edit if (kind == Undo::EDIT){ if (tmppar2->next->text) delete[] tmppar2->next->text;
tmppar2->next->text = NULL;
}
tmppar2->next->previous = tmppar2;
tmppar2=tmppar2->next;
}
tmppar2->next = NULL;
} else
undopar = NULL; // nothing to replace (undo of delete maybe)
int cursor_par = cursor.par->ParFromPos(cursor.pos)->GetID(); int cursor_pos = cursor.par->PositionInParFromPos(cursor.pos);
Undo* undo = new Undo(kind,
before_number, behind_number,
cursor_par, cursor_pos,
undopar);
do { /* move to the previous row */
cell_act = NumberOfCell(cursor->par, cursor->pos); if (cell < 0)
cell = cell_act; while (cursor->pos && !cursor->par->IsNewline(cursor->pos-1))
cursor->pos--; while (cursor->pos &&
!cursor->par->table->IsFirstCell(cell_act)){
cursor->pos--; while (cursor->pos && !cursor->par->IsNewline(cursor->pos-1))
cursor->pos--;
cell--;
cell_act--;
} /* now we have to pay attention if the actual table is the
main row of TableContRows and if yes to delete all of them */ if (!cell_org)
cell_org = cell; /* delete up to the next row */ while (cursor->pos < cursor->par->Last() &&
(cell_act == cell_org
|| !cursor->par->table->IsFirstCell(cell_act))){ while (cursor->pos < cursor->par->Last() && !cursor->par->IsNewline(cursor->pos))
cursor->par->Erase(cursor->pos);
cell++;
cell_act++; if (cursor->pos < cursor->par->Last())
cursor->par-> Erase(cursor->pos);
} if (cursor->pos && cursor->pos == cursor->par->Last()){
cursor->pos--;
cursor->par->Erase(cursor->pos); // no newline at the very end!
}
} while (!cursor->par->table->IsContRow(cell_org) &&
cursor->par->table->IsContRow(cell));
cursor->par->table->DeleteRow(cell_org); return;
}
bool LyXText::IsEmptyTableRow(LyXCursor *old_cursor)
{ if (!old_cursor->par->table) returnfalse; #ifdef I_DONT_KNOW_IF_I_SHOULD_DO_THIS int
pos = old_cursor->pos,
cell = NumberOfCell(old_cursor->par, pos);
// search first charater of this table row while (pos && !old_cursor->par->table->IsFirstCell(cell)) {
pos--; while (pos && !old_cursor->par->IsNewline(pos-1))
pos--;
cell--;
} if (!old_cursor->par->IsNewline(pos)) returnfalse;
cell++;
pos++; while ((pos < old_cursor->par->Last()) &&
!old_cursor->par->table->IsFirstCell(cell)) { if (!old_cursor->par->IsNewline(pos)) returnfalse;
pos++;
cell++;
} returntrue; #endif returnfalse;
}
bool LyXText::IsEmptyTableCell()
{ int pos = cursor.pos - 1;
void LyXText::toggleAppendix(){
LyXParagraph* par = cursor.par->FirstPhysicalPar(); bool start = !par->start_of_appendix;
/* ensure that we have only one start_of_appendix in this document */
LyXParagraph* tmp = FirstParagraph(); for (;tmp;tmp=tmp->next)
tmp->start_of_appendix = 0;
par->start_of_appendix = start;
/* we can set the refreshing parameters now */
status = LyXText::NEED_MORE_REFRESH;
refresh_y = 0;
refresh_row = 0; // not needed for full update
UpdateCounters(0);
SetCursor(cursor.par, cursor.pos);
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.48unsichere Verbindung
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.