Source Code (Use browser search to find items of interest.)
Class Index
klyx'LyXText (./klyx/src/lyxtext.h:28)
class LyXText {
public:
///
enum text_status {
///
UNCHANGED,
///
NEED_LITTLE_REFRESH,
///
NEED_MORE_REFRESH,
///
NEED_VERY_LITTLE_REFRESH
};
/// points to Buffer.params
BufferParams *parameters;
/// points to Buffer
Buffer *params;
///
int number_of_rows;
///
long height;
/// width of the paper
int paperwidth;
/// zoom used
unsigned int zoom;
/// the current font settings
LyXFont current_font;
/// the current font
LyXFont real_current_font;
/// Constructor
LyXText(int paperwidth, unsigned int _zoom, Buffer *);
/// Destructor
~LyXText();
///
LyXFont GetFont(LyXParagraph* par, int pos);
///
void SetCharFont(LyXParagraph *par, int pos, LyXFont font);
/// returns a pointer to the very first LyXParagraph
LyXParagraph *FirstParagraph();
/// what you expect when pressing <enter> at cursor position
void BreakParagraph(char keep_layout = 0);
/** set layout over selection and make a total rebreak of
those paragraphs
*/
void SetLayout(char layout);
/// used in setlayout
void MakeFontEntriesLayoutSpecific(LyXParagraph *par);
/** increment depth over selection and make a total rebreak of those
paragraphs
*/
void IncDepth();
/** decrement depth over selection and make a total rebreak of those
paragraphs */
void DecDepth();
/** Get the depth at current cursor position
*/
int GetDepth() { return cursor.par->GetDepth(); }
/** set font over selection and make a total rebreak of those
paragraphs.
*/
void SetFont(LyXFont font);
/** deletes and inserts again all paragaphs between the cursor
and the specified par .The Cursor is needed to set the refreshing
parameters.
This function is needed after SetLayout and SetFont etc.
*/
void RedoParagraphs(LyXCursor cursor, LyXParagraph *end_par);
///
void RedoParagraph();
///
void ToggleFree(LyXFont font);
/** recalculates the heights of all previous rows of the
specified paragraph. needed, if the last characters font
has changed.
*/
void RedoHeightOfParagraph(LyXCursor cursor);
/** forces the redrawing of a paragraph. Needed when manipulating a
right address box
*/
void RedoDrawingOfParagraph(LyXCursor cursor);
/** insert a character, moves all the following breaks in the
same Paragraph one to the right and make a little rebreak
*/
void InsertChar(char c);
///
void InsertInset(Inset *inset);
/// completes the insertion with a full rebreak
int FullRebreak();
/// may be important for the menu
char* GetLayout(int row);
///
LyXParagraph::footnote_flag GetFootnoteFlag(int row);
///
Row* need_break_row;
///
long refresh_y;
///
int refresh_height;
///
int refresh_width;
///
int refresh_x;
///
Row *refresh_row;
///
int refresh_pos;
/** wether the screen needs a refresh,
starting with refresh_y
*/
text_status status;
/** returns a pointer to the row near the specified y-coordinate
(relative to the whole text). y is set to the real beginning
of this row
*/
Row* GetRowNearY(long &y);
/** returns the column near the specified x-coordinate of the row
x is set to the real beginning of this column
*/
int GetColumnNearX(Row *row, int& x);
/** returns a pointer to a specified row. y is set to the beginning
of the row
*/
Row* GetRow(LyXParagraph *par, int pos, long &y);
/** returns the height of a default row, needed for scrollbar
*/
int DefaultHeight();
/** The cursor.
Later this variable has to be removed. There should be now internal
cursor in a text (and thus not in a buffer). By keeping this it is
(I think) impossible to have several views with the same buffer, but
the cursor placed at different places.
*/
LyXCursor cursor;
/* the selection cursor */
///
bool selection;
///
bool mark_set;
///
LyXCursor sel_cursor;
///
LyXCursor sel_start_cursor;
///
LyXCursor sel_end_cursor;
/// needed for the toggling
LyXCursor last_sel_cursor;
///
LyXCursor toggle_cursor;
///
LyXCursor toggle_end_cursor;
/// need the selection cursor:
void SetSelection();
///
void ClearSelection();
/// just selects the word the cursor is in
void SelectWord();
/** 'selects" the next word, where the cursor is not in
and returns this word as string. THe cursor will be moved
to the beginning of this word.
With SelectSelectedWord can this be highlighted really
*/
char* SelectNextWord(float &value);
///
void SelectSelectedWord();
///
void ExchangeCursorAndSelection(); // Rocher 981127
///
void SetCursor(LyXParagraph *par, int pos);
///
void SetCursorIntern(LyXParagraph *par, int pos);
///
void SetCursorFromCoordinates(int x, long y, bool delete_empty = true);
///
void CursorUp();
///
void CursorDown();
///
void CursorLeft();
///
void CursorRight();
///
void CursorLeftOneWord();
///
void CursorRightOneWord();
///
void CursorUpParagraph();
///
void CursorDownParagraph();
///
void CursorHome();
///
void CursorEnd();
///
void CursorTab();
///
void CursorTop();
///
void CursorBottom();
///
void Delete();
///
void Backspace();
///
void DeleteWordForward();
///
void DeleteWordBackward();
///
void DeleteLineForward();
///
int SelectWordWhenUnderCursor();
///
void UpcaseWord();
///
void LowcaseWord();
///
void CapitalizeWord();
/** returns a printed row in a pixmap. The y value is needed to
decide, wether it is selected text or not. This is a strange
solution but faster.
*/
void GetVisibleRow(LyXScreen &scr, int offset,
Row *row_ptr, long y);
/* footnotes: */
///
void ToggleFootnote();
///
void OpenStuff();
///
void OpenFootnotes();
///
void OpenFootnote();
///
void CloseFootnotes();
///
void CloseFootnote();
/** turn the selection into a new environment. If there is no
selection, create an empty environment
*/
void InsertFootnoteEnvironment(LyXParagraph::footnote_kind kind);
///
void MeltFootnoteEnvironment();
///
void CutSelection(bool = true);
///
void CopySelection();
///
void PasteSelection();
///
void copyEnvironmentType();
///
void pasteEnvironmentType();
///
void InsertFootnote();
///
void InsertMarginpar();
///
void InsertFigure();
///
void InsertTabular();
/** the DTP switches for paragraphs. LyX will store the top settings
always in the first physical paragraph, the bottom settings in the
last. When a paragraph is broken, the top settings rest, the bottom
settings are given to the new one. So I can make shure, they do not
duplicate themself (and you cannnot make dirty things with them! )
*/
void SetParagraph(bool line_top, bool line_bottom,
bool pagebreak_top, bool pagebreak_bottom,
VSpace space_top, VSpace space_bottom,
Spacing spacing,
LYX_ALIGNMENT align,
LString labelwidthstring,
bool noindent);
void SetParagraphExtraOpt(int type,
const char *width,
const char *widthp,
int alignment, bool hfill,
bool start_minipage);
/* these things are for search and replace */
/** returns true if the specified string is at the specified
position
*/
bool IsStringInText(LyXParagraph *par, int pos, char const* string);
/** sets the selection over the number of characters of string,
no check!!
*/
void SetSelectionOverString(char const* string);
/** simple replacing. The font of the first selected character
is used
*/
void ReplaceSelectionWithString(char const* string);
/// needed to insert the selection
void InsertStringA(const char* string);
/// needed to insert the selection
void InsertStringB(const char* string);
/// useful before setting the cursor in goto-functions
void EnsureParagraphIsOpen(LyXParagraph* par);
/// usefull when texing from within LyX
bool GotoNextError();
/// just another feature :)
bool GotoNextNote();
/** needed to switch between different classes this works
for a list of paragraphs beginning with the specified par
return value is the number of wrong conversions
*/
int SwitchLayoutsBetweenClasses(char class1, char class2, LyXParagraph *par);
/* for the greater insets */
/// returns 0 if inset wasn't found
int UpdateInset(Inset* inset);
///
void CheckParagraph(LyXParagraph* par, int pos);
/* table stuff -- begin*/
/** all table features of the text-class are put together in
this function. Possible values of feature are defined in table.h
*/
void TableFeatures(int feature,LString val);
///
void TableFeatures(int feature);
///
int NumberOfCell(LyXParagraph *par, int pos);
/** pos points at the beginning of the next cell (if there is one)
*/
int WidthOfCell(LyXParagraph *par, int &pos);
///
void InsertCharInTable(char c);
///
void BackspaceInTable();
///
void CheckParagraphInTable(LyXParagraph* par, int pos);
///
char HitInTable(Row* row, int x);
///
bool MouseHitInTable(int x, long y);
/* table stuff -- end*/
///
LyXParagraph* GetParFromID(int id);
// undo functions
/// returns false if no undo possible
bool TextUndo();
/// returns false if no redo possible
bool TextRedo();
/// used by TextUndo/TextRedo
bool TextHandleUndo(Undo* undo);
/// makes sure the next operation will be stored
void FinishUndo();
/// this is dangerous and for internal use only
void FreezeUndo();
/// this is dangerous and for internal use only
void UnFreezeUndo();
/// the flag used by FinishUndo();
bool undo_finished;
/// a flag
bool undo_frozen;
///
void SetUndo(Undo::undo_kind kind, LyXParagraph *before, LyXParagraph *end);
///
void SetRedo(Undo::undo_kind kind, LyXParagraph *before, LyXParagraph *end);
///
Undo *CreateUndo(Undo::undo_kind kind, LyXParagraph *before, LyXParagraph *end);
/// for external use in lyx_cb.C
void SetCursorParUndo();
///
void CursorLeftIntern();
///
void CursorRightIntern();
///
void RemoveTableRow(LyXCursor *cursor);
///
bool IsEmptyTableRow(LyXCursor *cursor);
///
bool IsEmptyTableCell();
/// For KLyX table of contents editor
void StructureUp(LyXParagraph* par);
void StructureDown(LyXParagraph* par);
void toggleAppendix();
private:
///
Row* firstrow;
///
Row* lastrow;
/** Copybuffer for copy environment type
Asger has learned that this should be a buffer-property instead
Lgb has learned that 'char' is a lousy type for non-characters
*/
char copylayouttype;
/// the currentrow is needed to access rows faster*/
Row* currentrow; /* pointer to the current row */
/* The insetstore is needed to handle changes of the display state
of insets correctly in the CheckParagraph-method.
*/
Inset* insetstore;
bool insetstore_display;
/// position in the text
long currentrow_y;
/** inserts a new row behind the specified row, increments
* the touched counters */
void InsertRow(Row *row, LyXParagraph *par, int pos );
/** removes the row and reset the touched counters */
void RemoveRow(Row *row);
/** remove all following rows of the paragraph of the specified row. */
void RemoveParagraph(Row *row);
/** insert the specified paragraph behind the specified row */
void InsertParagraph(LyXParagraph *par, Row *row);
/** appends the implizit specified paragraph behind the specified row,
* start at the implizit given position */
void AppendParagraph(Row *row);
///
void BreakAgain(Row *row);
///
void BreakAgainOneRow(Row *row);
///
void SetHeightOfRow(Row *row_ptr); /* calculate and set the height
* of the row */
/** this calculates the specified parameters. needed when setting
* the cursor and when creating a visible row */
void PrepareToPrint(Row *row, float &x, float &fill_separator,
float &fill_hfill, float &fill_label_hfill);
///
void DeleteEmptyParagraphMechanism(LyXCursor old_cursor);
/** Updates all counters starting BEHIND the row. Changed paragraphs
* with a dynamic left margin will be rebroken. */
void UpdateCounters(Row *row);
///
void SetCounter(LyXParagraph *par);
/*
* some low level functions
*/
///
int SingleWidth(LyXParagraph *par, int pos);
///
int SingleWidth(LyXParagraph *par, int pos, char c);
///
void Draw(Row *row, int &pos, LyXScreen &scr, int offset, float &x);
/// get the next breakpoint in a given paragraph
int NextBreakPoint(Row* row, int width);
/// returns the minimum space a row needs on the screen in pixel
int Fill(Row *row, int paperwidth);
/** returns the minimum space a manual label needs on the
screen in pixel */
int LabelFill(Row *row);
///
int BeginningOfMainBody(LyXParagraph *par);
/** Returns the left beginning of the text.
This information cannot be taken from the layouts-objekt, because
in LaTeX the beginning of the text fits in some cases
(for example sections) exactly the label-width.
*/
int LeftMargin(Row *row);
///
int RightMargin(Row *row);
///
int LabelEnd (Row *row);
/** returns the number of separators in the specified row.
The separator on the very last column doesnt count
*/
int NumberOfSeparators(Row *row);
/** returns the number of hfills in the specified row. The
LyX-Hfill is a LaTeX \hfill so that the hfills at the
beginning and at the end were ignored. This is {\em MUCH}
more usefull than not to ignore!
*/
int NumberOfHfills(Row *row);
/// like NumberOfHfills, but only those in the manual label!
int NumberOfLabelHfills(Row *row);
/** returns true, if a expansion is needed. Rules are given by
LaTeX
*/
bool HfillExpansion(Row *row_ptr, int pos);
/** returns the paragraph position of the last character in the
specified row
*/
int RowLast(Row *row);
};
klyx'LyXText::SingleWidth() (./klyx/src/text.C:46)
int LyXText::SingleWidth(LyXParagraph *par, int pos)
{
char c = par->GetChar(pos);
return SingleWidth(par, pos, c);
}
klyx'LyXText::SingleWidth() (./klyx/src/text.C:53)
int LyXText::SingleWidth(LyXParagraph *par, int pos, char c)
{
LyXFont font = GetFont(par, pos);
// The most common case is handled first (Asger)
if (IsPrintable(c)) {
return font.width(c);
} else if (IsHfillChar(c)) {
return 3; /* because of the representation
* as vertical lines */
} else if (c == QChar( (int)LYX_META_FOOTNOTE ) ||
c == QChar( (int)LYX_META_MARGIN ) ||
c == QChar( (int)LYX_META_FIG ) ||
c == QChar( (int)LYX_META_TAB ) ||
c == QChar( (int)LYX_META_WIDE_FIG ) ||
c == QChar( (int)LYX_META_WIDE_TAB ) ||
c == QChar( (int)LYX_META_ALGORITHM) )
{
LString fs;
bool cfab = lyxrc->close_floats_as_buttons; // Rocher 990601
switch (c) {
case LYX_META_MARGIN:
fs = "margin";
break;
case LYX_META_FIG:
fs = cfab ? "figure" : "fig"; // Rocher 990601
break;
case LYX_META_TAB:
fs = cfab ? "table" : "tab"; // Rocher 990601
break;
case LYX_META_ALGORITHM:
fs = cfab ? "algorithm" : "alg"; // Rocher 990601
break;
case LYX_META_WIDE_FIG:
fs = "wide-fig";
break;
case LYX_META_WIDE_TAB:
fs = "wide-tab";
break;
case LYX_META_FOOTNOTE:
fs = cfab ? "footnote" : "foot"; // Rocher 990601
break;
}
font.decSize();
if (cfab) // Rocher 990601
return font.stringWidth(fs) + 10;
else {
font.decSize();
return font.stringWidth(fs);
}
}
else if (c == QChar( (int)LYX_META_INSET )) {
Inset *tmpinset=par->GetInset(pos);
if (tmpinset)
return par->GetInset(pos)->Width(font);
else
return 0;
} else if (IsSeparatorChar(c))
c = ' ';
else if (IsNewlineChar(c))
c = 'n';
return font.width(c);
}
/* returns the paragraph position of the last character in the
* specified row */
klyx'LyXText::RowLast() (./klyx/src/text.C:124)
int LyXText::RowLast(Row *row)
{
if (row->next == NULL)
return row->par->Last()-1;
else if (row->next->par != row->par)
return row->par->Last()-1;
else
return row->next->pos - 1;
}
klyx'LyXText::Draw() (./klyx/src/text.C:135)
void LyXText::Draw(Row *row, int &pos, LyXScreen &scr, int offset, float &x)
{
char c = row->par->GetChar(pos);
if (IsNewlineChar(c)) {
pos++;
// Draw end-of-line marker
/**** (Old stuff) Rocher 990604
LyXFont font = GetFont(row->par, pos);
int asc = font.maxAscent();
int wid = font.width('n');
int y = (offset + row->baseline);
XPoint p[3];
p[0].x = int(x + wid*0.375); p[0].y = int(y - 0.875*asc*0.75);
p[1].x = int(x); p[1].y = int(y - 0.500*asc*0.75);
p[2].x = int(x + wid*0.375); p[2].y = int(y - 0.125*asc*0.75);
scr.drawLines(GetColorGC(LyXFont::RED),p, 3);
p[0].x = int(x); p[0].y = int(y - 0.500*asc*0.75);
p[1].x = int(x + wid); p[1].y = int(y - 0.500*asc*0.75);
p[2].x = int(x + wid); p[2].y = int(y - asc*0.75);
scr.drawLines(GetColorGC(LyXFont::RED),p, 3);
*****/
/***** Now the NewLineChar appears as '¶' Rocher 990604 ****/
LyXFont font = GetFont(row->par, pos);
font.setFamily(LyXFont::SANS_FAMILY);
font.setSeries(LyXFont::MEDIUM_SERIES);
font.setShape(LyXFont::UP_SHAPE);
font.setUnderbar(LyXFont::OFF);
font.setColor(LyXFont::RED);
LString fs = "¶";
scr.drawString(font, fs, offset + row->baseline, x+1);
/***** END *****/
return;
}
LyXFont font = GetFont(row->par, pos);
LyXFont font2 = font;
if (c == QChar( (int)LYX_META_FOOTNOTE) ||
c == QChar( (int)LYX_META_MARGIN) ||
c == QChar( (int)LYX_META_FIG) ||
c == QChar( (int)LYX_META_TAB) ||
c == QChar( (int)LYX_META_WIDE_FIG) ||
c == QChar( (int)LYX_META_WIDE_TAB) ||
c == QChar( (int)LYX_META_ALGORITHM)) {
LString fs;
bool cfab = lyxrc->close_floats_as_buttons; // Rocher 990601
switch (c) {
case LYX_META_MARGIN:
fs = "margin";
/* draw a sign at the left margin! */
if (!cfab) // Rocher 990601
scr.drawText(font, "!", 1, offset + row->baseline,
(LYX_PAPER_MARGIN - font.width('!'))/2);
break;
case LYX_META_FIG:
fs = cfab ? "figure" : "fig"; // Rocher 990601
break;
case LYX_META_TAB:
fs = cfab ? "table": "tab"; // Rocher 990601
break;
case LYX_META_ALGORITHM:
fs = cfab ? "algorithm" : "alg"; // Rocher 990601
break;
case LYX_META_WIDE_FIG:
fs = "wide-fig";
break;
case LYX_META_WIDE_TAB:
fs = "wide-tab";
break;
case LYX_META_FOOTNOTE:
fs = cfab ? "footnote" : "foot"; // Rocher 990601
break;
}
if (cfab) { // Rocher 990601
// This is the same as InsetCommand::Draw
font.decSize();
font.setColor(LyXFont::RED);
gc_type back = gc_lighted;
if (mono_video)
back = gc_clear;
x += 3;
scr.fillRectangle(back, int(x),
offset + row->baseline - font.maxAscent() - 2,
font.stringWidth(fs) + 4,
font.maxAscent() + font.maxDescent() + 4);
scr.drawFrame(int(x),
offset + row->baseline - font.maxAscent() - 2,
font.stringWidth(fs) + 4,
font.maxAscent() + font.maxDescent() + 4);
scr.drawString(font, fs, offset + row->baseline,
int(x+2));
x += font.stringWidth(fs) + 7;
}
else {
font.decSize();
font.decSize();
/* calculate the position of the footnotemark */
int y = (row->baseline - font2.maxAscent()
+ font.maxAscent());
font.setColor(LyXFont::INSET);
/* draw it and set new x position */
x += scr.drawString(font, fs, offset + y, int(x));
}
pos++;
return;
} else if (c == QChar( (int)LYX_META_INSET)) {
Inset *tmpinset = row->par->GetInset(pos);
if (tmpinset)
tmpinset->Draw(font, scr, offset + row->baseline, x);
pos++;
return;
}
/* usual characters, no insets */
// Collect character that we can draw in one command
// This is dirty, but fast. Notice that it will never be too small.
// For the record, I'll note that Microsoft Word has a limit
// of 768 here. We have none :-) (Asger)
static char textstring[1024];
int last = RowLast(row);
// Prevent crash in the extremely unlikely event
// that our array is too small
if (last > pos+1020) last = pos + 1020;
textstring[0] = c;
pos++;
int i = 1;
while (pos <= last &&
(unsigned char) (c = row->par->GetChar(pos)) > ' ' &&
font2 == GetFont(row->par, pos)) {
textstring[i++] = c;
pos++;
}
textstring[i] = 0;
float tmpx = x;
// If monochrome and LaTeX mode, provide reverse background
if (mono_video && font.latex() == LyXFont::ON) {
int a=font.maxAscent(), d=font.maxDescent();
scr.fillRectangle(gc_copy, int(tmpx), offset + row->baseline-a,
font.textWidth(textstring, i), a+d);
}
/* Draw text and set the new x position */
x += scr.drawText(font, textstring, i, offset + row->baseline,
int(x));
/* what about underbars? */
if (font.underbar() == LyXFont::ON && font.latex() != LyXFont::ON) {
scr.drawLine(gc_copy, offset + row->baseline + 2,
int(tmpx), int(x - tmpx));
}
// If we want ulem.sty support, drawing
// routines should go here. (Asger)
// Why shouldn't LyXFont::drawText handle it internally?
}
/* Returns the left beginning of the text.
* This information cannot be taken from the layouts-objekt, because in
* LaTeX the beginning of the text fits in some cases (for example sections)
* exactly the label-width. */
klyx'LyXText::LeftMargin() (./klyx/src/text.C:311)
int LyXText::LeftMargin(Row* row)
{
int x;
LyXLayout *layout;
LyXFont labelfont;
LyXParagraph *newpar;
Row dummyrow;
layout = lyxstyle.Style(parameters->textclass, row->par->GetLayout());
LString parindent = layout->parindent;
/* table stuff -- begin*/
if (row->par->table)
parindent.clean();
/* table stuff -- end*/
x = LYX_PAPER_MARGIN;
x += lyxstyle.TextClass(parameters->textclass)->
defaultfont.signedStringWidth(lyxstyle.TextClass(parameters->textclass)->leftmargin);
if (row->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
LyXFont font(LyXFont::ALL_SANE);
font.setSize(LyXFont::SIZE_SMALL);
x += font.textWidth("Mwide-figM", 10) + LYX_PAPER_MARGIN/2;
}
/* this is the way, LyX handles the LaTeX-Environments.
* I have had this idea very late, so it seems to be a
* later added hack and this is true */
if (!row->par->GetDepth()) {
if (!row->par->GetLayout()) {
/* find the previous same level paragraph */
if (row->par->FirstPhysicalPar()->Previous()) {
newpar = row->par->DepthHook(row->par->GetDepth());
if (newpar && lyxstyle.Style(parameters->textclass, newpar->GetLayout())->nextnoindent)
parindent.clean();
}
}
}
else {
/* find the next level paragraph */
newpar = row->par->DepthHook(row->par->GetDepth()-1);
/* make a corresponding row. Needed to call LeftMargin() */
/* check wether it is a sufficent paragraph */
if (newpar && newpar->footnoteflag == row->par->footnoteflag
&& lyxstyle.Style(parameters->textclass,
newpar->GetLayout())->isEnvironment()) {
dummyrow.par = newpar;
dummyrow.pos = newpar->Last();
x = LeftMargin(&dummyrow);
}
else {
/* this is no longer an error, because this function is used
* to clear impossible depths after changing a layout. Since there
* is always a redo, LeftMargin() is always called */
/* printf("LYX_ERROR (text, LeftMargin()) impossible depth \n");*/
row->par->FirstPhysicalPar()->depth = 0;
}
if (newpar && !row->par->GetLayout()) {
if (newpar->FirstPhysicalPar()->noindent)
parindent.clean();
else
parindent = lyxstyle.Style(parameters->textclass,
newpar->GetLayout())->parindent;
}
}
labelfont = GetFont(row->par, -2);
switch (layout->margintype) {
case MARGIN_DYNAMIC:
if (!layout->leftmargin.empty()) {
x += lyxstyle.TextClass(parameters->textclass)->defaultfont.signedStringWidth(layout->leftmargin);
}
if (!row->par->GetLabelString().empty()) {
x += labelfont.signedStringWidth(layout->labelindent);
x += labelfont.stringWidth(row->par->GetLabelString());
x += labelfont.stringWidth(layout->labelsep);
}
break;
case MARGIN_MANUAL:
x += labelfont.signedStringWidth(layout->labelindent);
if (row->pos >= BeginningOfMainBody(row->par)) {
if (!row->par->GetLabelWidthString().empty()) {
x += labelfont.stringWidth(row->par->GetLabelWidthString());
x += labelfont.stringWidth(layout->labelsep);
}
}
break;
case MARGIN_STATIC:
x += ( lyxstyle.TextClass(parameters->textclass)->defaultfont.signedStringWidth(layout->leftmargin) * 4
/ (row->par->GetDepth() + 4));
break;
case MARGIN_FIRST_DYNAMIC:
if (layout->labeltype == LABEL_MANUAL) {
if (row->pos >= BeginningOfMainBody(row->par)) {
x += labelfont.signedStringWidth(layout->leftmargin);
} else {
x += labelfont.signedStringWidth(layout->labelindent);
}
} else {
if (row->pos
// Special case to fix problems with theorems (JMarc)
|| (layout->labeltype == LABEL_STATIC
&& layout->latextype == LATEX_ENVIRONMENT
&& ! row->par->IsFirstInSequence())) {
x += labelfont.signedStringWidth(layout->leftmargin);
} else if (layout->labeltype != LABEL_TOP_ENVIRONMENT
&& layout->labeltype != LABEL_BIBLIO
&& layout->labeltype != LABEL_CENTERED_TOP_ENVIRONMENT) {
x += labelfont.signedStringWidth(layout->labelindent);
x += labelfont.stringWidth(layout->labelsep);
x += labelfont.stringWidth(row->par->GetLabelString());
}
}
break;
case MARGIN_RIGHT_ADDRESS_BOX:
{
/* ok, a terrible hack. The left margin depends on the widest row
* in this paragraph. Do not care about footnotes, they are *NOT*
* allowed in the LaTeX realisation of this layout. */
/* find the first row of this paragraph */
Row *tmprow = row;
while (tmprow->previous && tmprow->previous->par == row->par)
tmprow = tmprow->previous;
int minfill = tmprow->fill;
while (tmprow-> next && tmprow->next->par == row->par) {
tmprow = tmprow->next;
if (tmprow->fill < minfill)
minfill = tmprow->fill;
}
x += lyxstyle.TextClass(parameters->textclass)->defaultfont.signedStringWidth(layout->leftmargin);
x += minfill;
}
break;
}
if (row->par->pextra_type == PEXTRA_INDENT) {
if (!row->par->pextra_widthp.empty()) {
x += paperwidth * atoi(row->par->pextra_widthp.c_str()) / 100;
} else if (!row->par->pextra_width.empty()) {
int xx = VSpace(row->par->pextra_width).inPixels();
if (xx > paperwidth)
xx = paperwidth * 80 / 100;
x += xx;
} else { // should not happen
LyXFont font(LyXFont::ALL_SANE);
x += font.stringWidth("XXXXXX");
}
}
int align;
if (row->par->FirstPhysicalPar()->align == LYX_ALIGN_LAYOUT)
align = layout->align;
else
align = row->par->FirstPhysicalPar()->align;
/* set the correct parindent */
if (row->pos == 0) {
if ((layout->labeltype == LABEL_NO_LABEL
|| layout->labeltype == LABEL_TOP_ENVIRONMENT
|| layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT
|| (layout->labeltype == LABEL_STATIC
&& layout->latextype == LATEX_ENVIRONMENT
&& ! row->par->IsFirstInSequence()))
&& row->par == row->par->FirstPhysicalPar()
&& align == LYX_ALIGN_BLOCK
&& !row->par->noindent
&& (row->par->layout ||
parameters->paragraph_separation == LYX_PARSEP_INDENT))
x += lyxstyle.TextClass(parameters->textclass)->defaultfont.stringWidth(parindent);
else
if (layout->labeltype==LABEL_BIBLIO) { // ale970405 Right width for bibitems
x += bibitemMaxWidth(lyxstyle.TextClass(parameters->textclass)->defaultfont);
}
}
return x;
}
klyx'LyXText::RightMargin() (./klyx/src/text.C:502)
int LyXText::RightMargin(Row *row)
{
int x;
LyXLayout* layout;
LyXParagraph *newpar;
Row dummyrow;
layout = lyxstyle.Style(parameters->textclass, row->par->GetLayout());
x = LYX_PAPER_MARGIN;
x += lyxstyle.TextClass(parameters->textclass)->
defaultfont.signedStringWidth(lyxstyle.TextClass(parameters->textclass)->rightmargin);
if (row->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
x += LYX_PAPER_MARGIN/2;
}
/* this is the way, LyX handles the LaTeX-Environments.
* I have had this idea very late, so it seems to be a
* later added hack and this is true */
if (row->par->GetDepth()) {
/* find the next level paragraph */
newpar = row->par;
do {
newpar = newpar->FirstPhysicalPar()->Previous();
if (newpar)
newpar = newpar->FirstPhysicalPar();
} while (newpar && newpar->GetDepth() >= row->par->GetDepth()
&& newpar->footnoteflag == row->par->footnoteflag);
/* make a corresponding row. Needed to call LeftMargin() */
/* check wether it is a sufficent paragraph */
if (newpar && newpar->footnoteflag == row->par->footnoteflag
&& lyxstyle.Style(parameters->textclass,
newpar->GetLayout())->isEnvironment()) {
dummyrow.par = newpar;
dummyrow.pos = 0;
x = RightMargin(&dummyrow);
}
else {
/* this is no longer an error, because this function is used
* to clear impossible depths after changing a layout. Since there
* is always a redo, LeftMargin() is always called */
/* printf("LYX_ERROR (text, LeftMargin()) impossible depth \n");*/
row->par->FirstPhysicalPar()->depth = 0;
}
}
//fprintf(stderr,"rightmargin: %s\n", layout->rightmargin.c_str());
//fflush(stderr);
x += (lyxstyle.TextClass(parameters->textclass)->defaultfont.signedStringWidth(layout->rightmargin) * 4
/ (row->par->GetDepth() + 4));
return x;
}
klyx'LyXText::LabelEnd() (./klyx/src/text.C:563)
int LyXText::LabelEnd (Row *row)
{
if (lyxstyle.Style(parameters->textclass, row->par->GetLayout())->margintype == MARGIN_MANUAL) {
Row tmprow;
tmprow = *row;
tmprow.pos = row->par->Last();
return LeftMargin(&tmprow); /* just the beginning
* of the main body */
}
else
return 0; /* LabelEnd is only needed, if the
* layout fills a flushleft
* label. */
}
/* table stuff -- begin*/
klyx'LyXText::NumberOfCell() (./klyx/src/text.C:580)
int LyXText::NumberOfCell(LyXParagraph *par, int pos)
{
int cell = 0;
int tmp_pos = 0;
while (tmp_pos < pos) {
if (par->IsNewline(tmp_pos))
cell++;
tmp_pos++;
}
return cell;
}
klyx'LyXText::WidthOfCell() (./klyx/src/text.C:593)
int LyXText::WidthOfCell(LyXParagraph *par, int &pos)
{
int w = 0;
while (pos < par->Last() && !par->IsNewline(pos)) {
w += SingleWidth(par, pos);
pos++;
}
if (par->IsNewline(pos))
pos++;
return w;
}
klyx'LyXText::HitInTable() (./klyx/src/text.C:606)
char LyXText::HitInTable(Row* row, int x)
{
float tmpx;
float fill_separator, fill_hfill, fill_label_hfill;
if (!row->par->table)
return 0;
PrepareToPrint(row, tmpx, fill_separator, fill_hfill, fill_label_hfill);
return (x > tmpx && x < tmpx + row->par->table->WidthOfTable());
}
klyx'LyXText::MouseHitInTable() (./klyx/src/text.C:617)
bool LyXText::MouseHitInTable(int x, long y)
{
Row *row = GetRowNearY(y);
return HitInTable(row, x);
}
/* table stuff -- end*/
/* get the next breakpoint in a given paragraph */
klyx'LyXText::NextBreakPoint() (./klyx/src/text.C:628)
int LyXText::NextBreakPoint(Row* row, int width)
{
int x = 0;
int last_separator = -1; /* position of the last possible breakpoint
* -1 isn't a suitable value, but a flag */
int i = 0;
int left_margin;
LyXParagraph *par = row->par;
int pos = row->pos;
/* table stuff -- begin*/
if (par->table) {
while (pos<par->last
&& (!par->IsNewline(pos)
|| !par->table->IsFirstCell(NumberOfCell(par, pos+1)))) {
if (par->GetChar(pos) == QChar( (int)LYX_META_INSET) &&
par->GetInset(pos) && par->GetInset(pos)->Display()){
par->GetInset(pos)->SetDisplay(false);
}
pos++;
}
return pos;
}
/* table stuff -- end*/
left_margin = LabelEnd(row);
width -= RightMargin(row);
int main_body = BeginningOfMainBody(par);
LyXLayout* layout = lyxstyle.Style(parameters->textclass, par->GetLayout());
i = pos;
char c;
if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) {
/* special code for right address boxes, only newlines count */
while (i < par->Last()) {
if (par->IsNewline(i)) {
last_separator = i;
i = par->Last() - 1;/* this means break */
x = width;
}
else if (par->GetChar(i) == QChar( (int)LYX_META_INSET) &&
par->GetInset(i) && par->GetInset(i)->Display()){
par->GetInset(i)->SetDisplay(false);
}
i++;
}
}
else {
// Last position is an invariant
int const last = par->Last();
/* this is the usual handling */
x = LeftMargin(row);
while (x < width && i < last) {
c = par->GetChar(i);
if (IsNewlineChar(c)) {
last_separator = i;
x = width; /* this means break */
}
else if (c == QChar( (int)LYX_META_INSET) &&
par->GetInset(i) && par->GetInset(i)->Display()){
/* check wether a Display() inset is valid here .
if not, change it to non-display*/
if (layout->isCommand()
|| (layout->labeltype == LABEL_MANUAL
&& i < BeginningOfMainBody(par))){
/* display istn't allowd */
par->GetInset(i)->SetDisplay(false);
x += SingleWidth(par, i, c);
}
else {
/* inset is display. So break the line here */
if (i==pos){
if (pos < last-1){
last_separator = i;
if (IsLineSeparatorChar(par->GetChar(i+1)))
last_separator++;
}else
last_separator = last; // to avoid extra rows
}
else
last_separator = i - 1;
x = width; /* this means break */
}
}
else {
if (IsLineSeparatorChar(c))
last_separator = i;
x += SingleWidth(par, i, c);
}
i++;
if (i == main_body) {
x += GetFont(par, -2).stringWidth(layout->labelsep);
if (par->IsLineSeparator(i - 1))
x-= SingleWidth(par, i - 1);
if (x < left_margin)
x = left_margin;
}
}
/* end of paragraph is always a suitable separator */
if (i == last && x < width)
last_separator = i;
}
/* well, if last_separator is still 0, the line isn't breakable.
* don't care and cut simply at the end */
if (last_separator < 0) {
last_separator = i;
}
/* manual labels cannot be broken in LaTeX, do not care */
if (main_body && last_separator < main_body)
last_separator = main_body - 1;
return last_separator;
}
/* returns the minimum space a row needs on the screen in pixel */
klyx'LyXText::Fill() (./klyx/src/text.C:749)
int LyXText::Fill(Row *row, int paperwidth)
{
int w,i, last, fill, left_margin;
/* get the pure distance */
last = RowLast(row);
/* table stuff -- begin*/
if (row->par->table) {
/* for tables FILL does calculate the widthes of each cell in
* the row */
int pos = row->pos;
int cell = NumberOfCell(row->par, pos);
w = 0;
do {
row->par->table->SetWidthOfCell(cell, WidthOfCell(row->par, pos));
cell++;
} while (pos <= last && !row->par->table->IsFirstCell(cell));
/* don't forget the very last table cell without characters */
if (cell == row->par->table->GetNumberOfCells()-1)
row->par->table->SetWidthOfCell(cell, WidthOfCell(row->par, pos));
return 0; /* width of table cannot be returned since
* we cannot guarantee its correct value at
* this point. */
}
/* table stuff -- end*/
left_margin = LabelEnd(row);
/* if the row ends with newline, this newline will not be relevant */
if (last >= 0 && row->par->IsNewline(last))
last--;
/* if the row ends with a space, this space will not be relevant */
if (last >= 0 && row->par->IsLineSeparator(last))
last--;
/* special handling of the right address boxes */
if (lyxstyle.Style(parameters->textclass, row->par->GetLayout())->margintype == MARGIN_RIGHT_ADDRESS_BOX) {
int tmpfill = row->fill;
row->fill = 0; /* the minfill in MarginLeft() */
w = LeftMargin(row);
row->fill = tmpfill;
/* the old way, impossible when using environments: */
/* w = LyXStringWidth(lyxstyle.Style(parameters->textclass, row->par->GetLayout())->font, */
/* lyxstyle.Style(parameters->textclass, row->par->GetLayout())->leftmargin); */
}
else
w = LeftMargin(row);
int main_body = BeginningOfMainBody(row->par);
LyXLayout *layout = lyxstyle.Style(parameters->textclass,
row->par->GetLayout());
i = row->pos;
while (i<= last) {
w += SingleWidth(row->par, i);
i++;
if (i == main_body) {
w += GetFont(row->par, -2).stringWidth(layout->labelsep);
if (row->par->IsLineSeparator(i - 1))
w-= SingleWidth(row->par, i - 1);
if (w < left_margin)
w = left_margin;
}
}
fill = paperwidth - w - RightMargin(row);
return fill;
}
/* returns the minimum space a manual label needs on the screen in pixel */
klyx'LyXText::LabelFill() (./klyx/src/text.C:822)
int LyXText::LabelFill(Row *row)
{
int w,i, last;
int fill=0;
last = BeginningOfMainBody(row->par) - 1;
/* -1 because a label ends either with a space that is in the label,
* or with the beginning of a footnote that is outside the label. */
// I don't understand this code in depth, but sometimes "last" is less than
// 0 and this causes a crash. This fix seems to work correctly, but I
// bet the real error is elsewhere. The bug is triggered when you have an
// open footnote in a paragraph environment with a manual label. (Asger)
if (last<0) last = 0;
if (row->par->IsLineSeparator(last)) /* a sepearator at this end
* does not count */
last--;
w = 0;
i = row->pos;
while (i<= last) {
w += SingleWidth(row->par, i);
i++;
}
if (!row->par->labelwidthstring.empty()) {
fill = GetFont(row->par, -2).stringWidth(row->par->labelwidthstring) - w;
}
if (fill < 0)
fill = 0;
return fill;
}
/* returns the number of separators in the specified row. The separator
* on the very last column doesnt count */
klyx'LyXText::NumberOfSeparators() (./klyx/src/text.C:861)
int LyXText::NumberOfSeparators(Row *row)
{
int n,p,last;
last = RowLast(row);
n = 0;
p = row->pos;
int main_body = BeginningOfMainBody(row->par);
if (p < main_body)
p = main_body;
for (; p < last; p++) {
if (row->par->IsSeparator(p)) {
n++;
}
}
return n;
}
/* returns the number of hfills in the specified row. The LyX-Hfill is
* a LaTeX \hfill so that the hfills at the beginning and at the end were
* ignored. This is *MUCH* more usefull than not to ignore! */
klyx'LyXText::NumberOfHfills() (./klyx/src/text.C:883)
int LyXText::NumberOfHfills(Row *row)
{
int n,p,last, first;
last = RowLast(row);
first = row->pos;
if (first) { /* hfill *DO* count at the beginning
* of paragraphs! */
while(first <= last && row->par->IsHfill(first))
first++;
}
n = 0;
int main_body = BeginningOfMainBody(row->par);
if (first < main_body)
first = main_body;
for (p = first; p <= last; p++) { /* last, because the end is ignored! */
if (row->par->IsHfill(p)) {
n++;
}
}
return n;
}
/* like NumberOfHfills, but only those in the manual label! */
klyx'LyXText::NumberOfLabelHfills() (./klyx/src/text.C:909)
int LyXText::NumberOfLabelHfills(Row *row)
{
int n,p,last, first;
last = RowLast(row);
first = row->pos;
if (first) { /* hfill *DO* count at the beginning
* of paragraphs! */
while(first < last && row->par->IsHfill(first))
first++;
}
n = 0;
int main_body = BeginningOfMainBody(row->par);
if (last > main_body)
last = main_body;
for (p = first; p < last; p++) { /* last, because the end is ignored! */
if (row->par->IsHfill(p)) {
n++;
}
}
return n;
}
/* returns true, if a expansion is needed.
* Rules are given by LaTeX */
klyx'LyXText::HfillExpansion() (./klyx/src/text.C:938)
bool LyXText::HfillExpansion(Row *row_ptr, int pos)
{
/* by the way, is it a hfill? */
if (!row_ptr->par->IsHfill(pos))
return false;
/* at the end of a row it does not count */
// if (pos >= RowLast(row_ptr))
// return false;
/* at the beginning of a row it does not count, if it is not
* the first row of a paragaph */
if (!row_ptr->pos)
return true;
/* in some labels it does not count */
if ( lyxstyle.Style(parameters->textclass, row_ptr->par->GetLayout())->margintype != MARGIN_MANUAL &&
pos < BeginningOfMainBody(row_ptr->par))
return false;
/* if there is anything between the first char of the row and
* the sepcified position that is not a newline and not a hfill,
* the hfill will count, otherwise not */
int i = row_ptr->pos;
while (i < pos && (row_ptr->par->IsNewline(i)
|| row_ptr->par->IsHfill(i)))
i++;
return (i != pos);
}
klyx'LyXText::SetHeightOfRow() (./klyx/src/text.C:971)
void LyXText::SetHeightOfRow(Row *row_ptr)
{
/* get the maximum ascent and the maximum descent */
int asc, maxasc, desc, maxdesc, pos_end, pos, labeladdon;
float layoutasc = 0;
float layoutdesc = 0;
float tmptop = 0;
LyXParagraph *par, *firstpar;
LyXFont tmpfont;
Inset *tmpinset;
/* this must not happen before the currentrow for clear reasons.
so the trick is just to set the current row onto this row */
long unused_y;
GetRow(row_ptr->par, row_ptr->pos, unused_y);
/* ok , let us initialize the maxasc and maxdesc value.
* This depends in LaTeX of the font of the last character
* in the paragraph. The hack below is necessary because
* of the possibility of open footnotes */
/* Correction: only the fontsize count. The other properties
are taken from the layoutfont. Nicer on the screen :) */
par = row_ptr->par->LastPhysicalPar();
firstpar = row_ptr->par->FirstPhysicalPar();
LyXLayout *layout = lyxstyle.Style(parameters->textclass, firstpar->GetLayout());
LyXFont font = GetFont(par, par->Last()-1);
LyXFont::FONT_SIZE size = font.size();
font = GetFont(par, -1);
font.setSize(size);
LyXFont labelfont = GetFont(par, -2);
maxasc = int(font.maxAscent() *
layout->spacing.getValue() *
firstpar->spacing.getValue(parameters->spacing.getValue()));
maxdesc = int(font.maxDescent() *
layout->spacing.getValue() *
firstpar->spacing.getValue(parameters->spacing.getValue()));
pos_end = RowLast(row_ptr);
labeladdon = 0;
// Check if any insets are larger
for (pos = row_ptr->pos; pos <= pos_end; pos++) {
if (row_ptr->par->GetChar(pos) == QChar( (int)LYX_META_INSET)) {
tmpfont = GetFont(row_ptr->par, pos);
tmpinset = row_ptr->par->GetInset(pos);
if (tmpinset) {
asc = tmpinset->Ascent(tmpfont);
desc = tmpinset->Descent(tmpfont);
if (asc > maxasc)
maxasc = asc;
if (desc > maxdesc)
maxdesc = desc;
}
}
// --- Rocher 990601 ---
if (lyxrc->close_floats_as_buttons) {
char c = row_ptr->par->GetChar(pos);
if (c == QChar( (int)LYX_META_FOOTNOTE) ||
c == QChar( (int)LYX_META_MARGIN) ||
c == QChar( (int)LYX_META_FIG) ||
c == QChar( (int)LYX_META_TAB) ||
c == QChar( (int)LYX_META_WIDE_FIG) ||
c == QChar( (int)LYX_META_WIDE_TAB) ||
c == QChar( (int)LYX_META_ALGORITHM)) {
tmpfont = GetFont(row_ptr->par, pos);
tmpfont.decSize();
asc = tmpfont.maxAscent() + 4;
desc = tmpfont.maxDescent() + 4;
if (asc > maxasc)
maxasc = asc;
if (desc > maxdesc)
maxdesc = desc;
}
}
// --- Rocher 990601 ---
}
// Check if any custom fonts are larger (Asger)
// This is not completely correct, but we can live with the small,
// cosmetic error for now.
LyXFont::FONT_SIZE maxsize = row_ptr->par->HighestFontInRange(row_ptr->pos, pos_end);
if (maxsize > font.size()) {
font.setSize(maxsize);
asc = font.maxAscent();
desc = font.maxDescent();
if (asc > maxasc)
maxasc = asc;
if (desc > maxdesc)
maxdesc = desc;
}
/* table stuff -- begin*/
if (row_ptr->par->table){
// stretch the rows a bit
maxasc += 1;
maxdesc +=1;
}
/* table stuff -- end*/
// This is nicer with box insets:
maxasc++;
maxdesc++;
row_ptr->ascent_of_text = maxasc;
/* is it a top line? */
if (row_ptr->pos == 0
&& row_ptr->par == firstpar) {
/* do some corrections if the previous paragraph has a larger spacing */
if (firstpar->Previous()
&& firstpar->Previous()->spacing.getValue(parameters->spacing.getValue())
> firstpar->spacing.getValue(parameters->spacing.getValue()))
maxasc += int(font.maxAscent() *
(firstpar->Previous()->spacing.getValue(parameters->spacing.getValue())
- firstpar->spacing.getValue(parameters->spacing.getValue())));
/* some parksips VERY EASY IMPLEMENTATION */
if (parameters->paragraph_separation == LYX_PARSEP_SKIP) {
if (layout->isParagraph()
&& firstpar->GetDepth() == 0
&& firstpar->Previous())
maxasc += parameters->getDefSkip().inPixels();
else if (firstpar->Previous()
&& lyxstyle.Style(parameters->textclass,
firstpar->Previous()->GetLayout())->isParagraph()
&& firstpar->Previous()->GetDepth() == 0)
// is it right to use defskip here too? (AS)
maxasc += parameters->getDefSkip().inPixels();
}
/* the paper margins */
if (!row_ptr->par->previous)
maxasc += LYX_PAPER_MARGIN;
/* add the vertical spaces, that the user added */
if (firstpar->added_space_top.kind() != VSpace::NONE)
maxasc += int(firstpar->added_space_top.inPixels());
/* do not forget the DTP-lines!
* there height depends on the font of the nearest character */
if (firstpar->line_top)
maxasc += 2 * GetFont(firstpar, 0).ascent('x');
/* and now the pagebreaks */
if (firstpar->pagebreak_top)
maxasc += 3 * DefaultHeight();
/* this is special code for the chapter, since the label of this
* layout is printed in an extra row */
if (layout->labeltype == LABEL_COUNTER_CHAPTER
&& parameters->secnumdepth>=0) {
labeladdon = int(labelfont.maxDescent() *
layout->spacing.getValue() *
firstpar->spacing.getValue(parameters->spacing.getValue()))
+ int(labelfont.maxAscent() *
layout->spacing.getValue() *
firstpar->spacing.getValue(parameters->spacing.getValue()));
}
/* sepcial code for the top label */
if ((layout->labeltype == LABEL_TOP_ENVIRONMENT
|| layout->labeltype == LABEL_BIBLIO
|| layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT)
&& row_ptr->par->IsFirstInSequence()) {
labeladdon = int(
(labelfont.maxAscent() *
layout->spacing.getValue() *
firstpar->spacing.getValue(parameters->spacing.getValue()))
+(labelfont.maxDescent() *
layout->spacing.getValue() *
firstpar->spacing.getValue(parameters->spacing.getValue()))
+ layout->topsep * DefaultHeight()
+ layout->labelbottomsep * DefaultHeight());
}
/* and now the layout spaces, for example before and after a section,
* or between the items of a itemize or enumerate environment */
if (!firstpar->pagebreak_top) {
LyXParagraph *prev = row_ptr->par->Previous();
if (prev)
prev = row_ptr->par->DepthHook(row_ptr->par->GetDepth());
if (prev && prev->GetLayout() == firstpar->GetLayout()
&& prev->GetDepth() == firstpar->GetDepth()
&& prev->GetLabelWidthString() == firstpar->GetLabelWidthString())
{
layoutasc = (layout->itemsep * DefaultHeight());
}
else if (row_ptr->previous) {
tmptop = layout->topsep;
if (row_ptr->previous->par->GetDepth() >= row_ptr->par->GetDepth())
tmptop-=lyxstyle.Style(parameters->textclass, row_ptr->previous->par->GetLayout())->bottomsep;
if (tmptop > 0)
layoutasc = (tmptop * DefaultHeight());
}
else if (row_ptr->par->line_top){
tmptop = layout->topsep;
if (tmptop > 0)
layoutasc = (tmptop * DefaultHeight());
}
prev = row_ptr->par->DepthHook(row_ptr->par->GetDepth()-1);
if (prev) {
maxasc += int(lyxstyle.Style(parameters->textclass,
prev->GetLayout())->parsep * DefaultHeight());
}
else {
if (firstpar->Previous()
&& firstpar->Previous()->GetDepth() == 0
&& firstpar->Previous()->GetLayout() != firstpar->GetLayout()) {
/* avoid parsep */
}
else if (firstpar->Previous()){
maxasc += int(layout->parsep * DefaultHeight());
}
}
}
}
/* is it a bottom line? */
if (row_ptr->par->ParFromPos(RowLast(row_ptr) + 1) == par
&& (!row_ptr->next || row_ptr->next->par != row_ptr->par)) {
/* the paper margins */
if (!par->next)
maxdesc += LYX_PAPER_MARGIN;
/* add the vertical spaces, that the user added */
if (firstpar->added_space_bottom.kind() != VSpace::NONE)
maxdesc += int(firstpar->added_space_bottom.inPixels());
/* do not forget the DTP-lines!
* there height depends on the font of the nearest character */
if (firstpar->line_bottom)
maxdesc += 2 * (GetFont(par, par->Last()-1).ascent('x'));
/* and now the pagebreaks */
if (firstpar->pagebreak_bottom)
maxdesc += 3 * DefaultHeight();
/* and now the layout spaces, for example before and after a section,
* or between the items of a itemize or enumerate environment */
if (!firstpar->pagebreak_bottom && row_ptr->par->Next()) {
LyXParagraph *nextpar = row_ptr->par->Next();
LyXParagraph *comparepar = row_ptr->par;
float usual = 0;
float unusual = 0;
if (comparepar->GetDepth() > nextpar->GetDepth()) {
usual = (lyxstyle.Style(parameters->textclass, comparepar->GetLayout())->bottomsep * DefaultHeight());
comparepar = comparepar->DepthHook(nextpar->GetDepth());
if (comparepar->GetLayout()!=nextpar->GetLayout()
|| nextpar->GetLabelWidthString() !=
comparepar->GetLabelWidthString())
unusual = (lyxstyle.Style(parameters->textclass, comparepar->GetLayout())->bottomsep * DefaultHeight());
if (unusual > usual)
layoutdesc = unusual;
else
layoutdesc = usual;
}
else if (comparepar->GetDepth() == nextpar->GetDepth()) {
if (comparepar->GetLayout()!= nextpar->GetLayout()
|| nextpar->GetLabelWidthString() !=
comparepar->GetLabelWidthString())
layoutdesc = int(lyxstyle.Style(parameters->textclass, comparepar->GetLayout())->bottomsep * DefaultHeight());
}
}
}
/* incalculate the layout spaces */
maxasc += int(layoutasc * 2 / (2 + firstpar->GetDepth()));
maxdesc += int(layoutdesc * 2 / (2 + firstpar->GetDepth()));
/* table stuff -- begin*/
if (row_ptr->par->table){
maxasc += row_ptr->par->table->
AdditionalHeight(NumberOfCell(row_ptr->par, row_ptr->pos));
}
/* table stuff -- end*/
/* calculate the new height of the text */
height -= row_ptr->height;
row_ptr->height=maxasc+maxdesc+labeladdon;
row_ptr->baseline=maxasc+labeladdon;
height += row_ptr->height;
}
/* Appends the implicit specified paragraph behind the specified row,
* start at the implicit given position */
klyx'LyXText::AppendParagraph() (./klyx/src/text.C:1279)
void LyXText::AppendParagraph(Row *row)
{
int z;
Row *tmprow;
bool not_ready = true;
// Get the width of the row
z = row->pos;
// The last character position of a paragraph is an invariant so we can
// safely get it here. (Asger)
int lastposition = row->par->Last();
do {
// Get the next breakpoint
z = NextBreakPoint(row, paperwidth);
tmprow = row;
// Insert the new row
if (z < lastposition) {
z++;
InsertRow(row, row->par, z);
row = row->next;
row->height = 0;
} else
not_ready = false;
// Set the dimensions of the row
tmprow->fill = Fill(tmprow, paperwidth);
SetHeightOfRow(tmprow);
} while (not_ready);
}
klyx'LyXText::BreakAgain() (./klyx/src/text.C:1316)
void LyXText::BreakAgain(Row *row)
{
int z;
char not_ready;
z = row->pos;
Row *tmprow, *tmprow2;
not_ready = 1;
do {
/* get the next breakpoint */
z = NextBreakPoint(row, paperwidth);
tmprow = row;
if (z < row->par->Last() ) {
if (!row->next || (row->next && row->next->par != row->par)) {
/* insert a new row */
z++;
InsertRow(row, row->par, z);
row = row->next;
row->height = 0;
}
else {
row=row->next;
z++;
if (row->pos == z)
not_ready = 0; /* the rest will not change */
else {
row->pos = z;
}
}
}
else {
/* if there are some rows too much, delete them */
/* only if you broke the whole paragraph! */
tmprow2 = row;
while (tmprow2->next && tmprow2->next->par == row->par) {
tmprow2 = tmprow2->next;
}
while (tmprow2 != row) {
tmprow2 = tmprow2->previous;
RemoveRow(tmprow2->next);
}
not_ready = 0;
}
/* set the dimensions of the row */
tmprow->fill = Fill(tmprow, paperwidth);
SetHeightOfRow(tmprow);
} while (not_ready);
}
/* this is just a little changed version of break again */
klyx'LyXText::BreakAgainOneRow() (./klyx/src/text.C:1371)
void LyXText::BreakAgainOneRow(Row *row)
{
int z;
char not_ready;
z = row->pos;
Row *tmprow, *tmprow2;
not_ready = 1;
/* get the next breakpoint */
z = NextBreakPoint(row, paperwidth);
tmprow = row;
if (z < row->par->Last() ) {
if (!row->next || (row->next && row->next->par != row->par)) {
/* insert a new row */
z++;
InsertRow(row, row->par, z);
row = row->next;
row->height = 0;
}
else {
row=row->next;
z++;
if (row->pos == z)
not_ready = 0; /* the rest will not change */
else {
row->pos = z;
}
}
}
else {
/* if there are some rows too much, delete them */
/* only if you broke the whole paragraph! */
tmprow2 = row;
while (tmprow2->next && tmprow2->next->par == row->par) {
tmprow2 = tmprow2->next;
}
while (tmprow2 != row) {
tmprow2 = tmprow2->previous;
RemoveRow(tmprow2->next);
}
not_ready = 0;
}
/* set the dimensions of the row */
tmprow->fill = Fill(tmprow, paperwidth);
SetHeightOfRow(tmprow);
}
klyx'LyXText::BreakParagraph() (./klyx/src/text.C:1423)
void LyXText::BreakParagraph(char keep_layout)
{
LyXLayout *layout = lyxstyle.Style(parameters->textclass,
cursor.par->GetLayout());
/* table stuff -- begin*/
if (cursor.par->table) {
// breaking of tables is only allowed at the beginning or the end */
if (cursor.pos && cursor.pos < cursor.par->last &&
!cursor.par->table->ShouldBeVeryLastCell(NumberOfCell(cursor.par, cursor.pos)))
return; /* no breaking of tables allowed */
}
/* table stuff -- end*/
/* this is only allowed, if the current paragraph is not empty or caption*/
if ((cursor.par->Last() <= 0 && !cursor.par->IsDummy())
&&
layout->labeltype!=LABEL_SENSITIVE)
return;
SetUndo(Undo::INSERT,
cursor.par->ParFromPos(cursor.pos)->previous,
cursor.par->ParFromPos(cursor.pos)->next);
/* table stuff -- begin*/
if (cursor.par->table) {
int cell = NumberOfCell(cursor.par, cursor.pos);
if (cursor.par->table->ShouldBeVeryLastCell(cell))
SetCursor(cursor.par,cursor.par->last);
}
/* table stuff -- end*/
/* please break alway behind a space */
if (cursor.pos < cursor.par->Last()
&& cursor.par->IsLineSeparator(cursor.pos))
cursor.pos++;
/* break the paragraph */
if (keep_layout)
keep_layout = 2;
else
keep_layout = layout->isEnvironment();
cursor.par->BreakParagraph(cursor.pos, keep_layout);
/* table stuff -- begin*/
if (cursor.par->table){
// the table should stay with the contents
if (!cursor.pos){
cursor.par->Next()->table = cursor.par->table;
cursor.par->table = NULL;
}
}
/* table stuff -- end*/
/* well this is the caption hack since one caption is really enough */
if (layout->labeltype == LABEL_SENSITIVE){
if (!cursor.pos)
cursor.par->SetLayout(0); /* set the new paragraph to standard-layout */
else
cursor.par->Next()->SetLayout(0); /* set the new paragraph to standard-layout */
}
/* if the cursor is at the beginning of a row without prior newline,
* move one row up!
* This touches only the screen-update. Otherwise we would may have
* an empty row on the screen */
if (cursor.pos && !cursor.row->par->IsNewline(cursor.row->pos -1) &&
cursor.row->pos == cursor.pos) {
CursorLeft();
}
status = LyXText::NEED_MORE_REFRESH;
refresh_row = cursor.row;
refresh_y = cursor.y - cursor.row->baseline;
/* Do not forget the special right address boxes */
if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) {
while (refresh_row->previous &&
refresh_row->previous->par == refresh_row->par) {
refresh_row = refresh_row->previous;
refresh_y -= refresh_row->height;
}
}
RemoveParagraph(cursor.row);
/* set the dimensions of the cursor row */
cursor.row->fill = Fill(cursor.row, paperwidth);
SetHeightOfRow(cursor.row);
while (!cursor.par->Next()->table && cursor.par->Next()->Last()
&& cursor.par->Next()->IsNewline(0))
cursor.par->Next()->Erase(0);
InsertParagraph(cursor.par->Next(), cursor.row);
UpdateCounters(cursor.row->previous);
/* this check is necessary. Otherwise the new empty paragraph will
* be deleted automatically. And it is more friendly for the user! */
if (cursor.pos)
SetCursor(cursor.par->Next(), 0);
else
SetCursor(cursor.par, 0);
if (cursor.row->next)
BreakAgain(cursor.row->next);
need_break_row = NULL;
}
klyx'LyXText::OpenFootnote() (./klyx/src/text.C:1535)
void LyXText::OpenFootnote()
{
LyXParagraph *par, *endpar,*tmppar;
Row *row;
par = cursor.par->ParFromPos(cursor.pos);
/* if there is no footnote in this paragraph, just return. */
if (!par->next
|| par->next->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
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);
/* the cursor must be exactly before the footnote */
par = cursor.par->ParFromPos(cursor.pos);
status = LyXText::NEED_MORE_REFRESH;
refresh_row = cursor.row;
refresh_y = cursor.y - cursor.row->baseline;
tmppar = cursor.par;
endpar = cursor.par->Next();
row = cursor.row;
tmppar->OpenFootnote(cursor.pos);
RemoveParagraph(row);
/* set the dimensions of the cursor row */
row->fill = Fill(row, paperwidth);
SetHeightOfRow(row);
tmppar = tmppar->Next();
while (tmppar != endpar) {
if (tmppar) {
InsertParagraph(tmppar, row);
while (row->next && row->next->par == tmppar)
row = row->next;
tmppar = tmppar->Next();
}
}
SetCursor(par->next, 0);
sel_cursor = cursor;
}
/* table stuff -- begin*/
klyx'LyXText::TableFeatures() (./klyx/src/text.C:1587)
void LyXText::TableFeatures(int feature, LString val)
{
int
actCell;
if (!cursor.par->table)
return; /* this should never happen */
actCell = NumberOfCell(cursor.par, cursor.pos);
SetUndo(Undo::FINISH,
cursor.par->ParFromPos(cursor.pos)->previous,
cursor.par->ParFromPos(cursor.pos)->next);
switch (feature){
case LyXTable::SET_PWIDTH:
cursor.par->table->SetPWidth(actCell,val);
break;
case LyXTable::SET_SPECIAL_COLUMN:
case LyXTable::SET_SPECIAL_MULTI:
cursor.par->table->SetAlignSpecial(actCell,val,feature);
break;
default:
break;
}
RedoParagraph();
}
klyx'LyXText::TableFeatures() (./klyx/src/text.C:1615)
void LyXText::TableFeatures(int feature)
{
int
setLines = 0,
setAlign = LYX_ALIGN_LEFT,
lineSet,
actCell;
bool
what;
if (!cursor.par->table)
return; /* this should never happen */
actCell = NumberOfCell(cursor.par, cursor.pos);
SetUndo(Undo::FINISH,
cursor.par->ParFromPos(cursor.pos)->previous,
cursor.par->ParFromPos(cursor.pos)->next);
switch (feature){
case LyXTable::ALIGN_LEFT:
setAlign=LYX_ALIGN_LEFT;
break;
case LyXTable::ALIGN_RIGHT:
setAlign=LYX_ALIGN_RIGHT;
break;
case LyXTable::ALIGN_CENTER:
setAlign=LYX_ALIGN_CENTER;
break;
default:
break;
}
switch (feature){
case LyXTable::APPEND_ROW: {
int pos = cursor.pos;
/* move to the next row */
int cell_org = actCell;
int cell = cell_org;
// if there is a ContRow following this row I have to add
// the row after the ContRow's
if ((pos < cursor.par->Last()) &&
cursor.par->table->RowHasContRow(cell_org)) {
while((pos < cursor.par->Last()) &&
!cursor.par->table->IsContRow(cell)) {
while (pos < cursor.par->Last() &&
!cursor.par->IsNewline(pos))
pos++;
if (pos < cursor.par->Last())
pos++;
cell++;
}
while((pos < cursor.par->Last()) &&
cursor.par->table->IsContRow(cell)) {
while (pos < cursor.par->Last() &&
!cursor.par->IsNewline(pos))
pos++;
if (pos < cursor.par->Last())
pos++;
cell++;
}
cell_org = --cell;
if (pos < cursor.par->Last())
pos--;
}
while (pos < cursor.par->Last() &&
(cell == cell_org || !cursor.par->table->IsFirstCell(cell))){
while (pos < cursor.par->Last() && !cursor.par->IsNewline(pos))
pos++;
if (pos < cursor.par->Last())
pos++;
cell++;
}
/* insert the new cells */
int number = cursor.par->table->NumberOfCellsInRow(cell_org);
int i;
for (i=0; i<number; i++)
cursor.par->InsertChar(pos, LYX_META_NEWLINE);
/* append the row into the table */
cursor.par->table->AppendRow(cell_org);
RedoParagraph();
return;
}
case LyXTable::APPEND_CONT_ROW: {
int pos = cursor.pos;
/* move to the next row */
int cell_org = actCell;
int cell = cell_org;
// if there is already a controw but not for this cell
// the AppendContRow sets only the right values but does
// not actually add a row
if (cursor.par->table->RowHasContRow(cell_org) &&
(cursor.par->table->CellHasContRow(cell_org)<0)) {
cursor.par->table->AppendContRow(cell_org);
RedoParagraph();
return;
}
while (pos < cursor.par->Last() &&
(cell == cell_org
|| !cursor.par->table->IsFirstCell(cell))){
while (pos < cursor.par->Last() && !cursor.par->IsNewline(pos))
pos++;
if (pos < cursor.par->Last())
pos++;
cell++;
}
/* insert the new cells */
int number = cursor.par->table->NumberOfCellsInRow(cell_org);
int i;
for (i=0; i<number; i++)
cursor.par->InsertChar(pos, LYX_META_NEWLINE);
/* append the row into the table */
cursor.par->table->AppendContRow(cell_org);
RedoParagraph();
return;
}
case LyXTable::APPEND_COLUMN: {
int pos = 0;
int cell_org = actCell;
int cell = 0;
do{
if (pos && (cursor.par->IsNewline(pos-1))){
if (cursor.par->table->AppendCellAfterCell(cell_org, cell)){
cursor.par->InsertChar(pos, LYX_META_NEWLINE);
if (pos<=cursor.pos)
cursor.pos++;
pos++;
}
cell++;
}
pos++;
} while (pos<= cursor.par->Last());
/* remember that the very last cell doesn't end with a newline.
This saves one byte memory per table ;-) */
if (cursor.par->table->AppendCellAfterCell(cell_org, cell))
cursor.par->InsertChar(cursor.par->Last(), LYX_META_NEWLINE);
/* append the column into the table */
cursor.par->table->AppendColumn(cell_org);
RedoParagraph();
return;
}
case LyXTable::DELETE_ROW:
RemoveTableRow(&cursor);
RedoParagraph();
return;
case LyXTable::DELETE_COLUMN: {
int pos = 0;
int cell_org = actCell;
int cell = 0;
do{
if (!pos || (cursor.par->IsNewline(pos-1))){
if (cursor.par->table->DeleteCellIfColumnIsDeleted(cell, cell_org)){
// delete one cell
while (pos < cursor.par->Last() && !cursor.par->IsNewline(pos))
cursor.par->Erase(pos);
if (pos < cursor.par->Last())
cursor.par->Erase(pos);
else
cursor.par->Erase(pos - 1); // the missing newline at the end of a table
pos--; // because of pos++ below
}
cell++;
}
pos++;
} while (pos<= cursor.par->Last());
/* delete the column from the table */
cursor.par->table->DeleteColumn(cell_org);
/* set the cursor to the beginning of the table, where else? */
cursor.pos = 0;
RedoParagraph();
return;
}
case LyXTable::TOGGLE_LINE_TOP:
lineSet = !cursor.par->table->TopLine(actCell);
if (!selection){
cursor.par->table->SetTopLine(actCell,lineSet);
} else {
int i,n=-1,m=-2;
for (i=sel_start_cursor.pos; i<=sel_end_cursor.pos; i++){
if ((n=NumberOfCell(sel_start_cursor.par,i)) != m) {
cursor.par->table->SetTopLine(n,lineSet);
m = n;
}
}
}
RedoParagraph();
return;
case LyXTable::TOGGLE_LINE_BOTTOM:
lineSet = !cursor.par->table->BottomLine(actCell);
if (!selection){
cursor.par->table->SetBottomLine(actCell,lineSet);
} else {
int i,n=-1,m=-2;
for (i=sel_start_cursor.pos; i<=sel_end_cursor.pos; i++){
if ((n=NumberOfCell(sel_start_cursor.par,i)) != m) {
cursor.par->table->SetBottomLine(n,lineSet);
m = n;
}
}
}
RedoParagraph();
return;
case LyXTable::TOGGLE_LINE_LEFT:
lineSet = !cursor.par->table->LeftLine(actCell);
if (!selection){
cursor.par->table->SetLeftLine(actCell,lineSet);
} else {
int i,n=-1,m=-2;
for (i=sel_start_cursor.pos; i<=sel_end_cursor.pos; i++){
if ((n=NumberOfCell(sel_start_cursor.par,i)) != m) {
cursor.par->table->SetLeftLine(n,lineSet);
m = n;
}
}
}
RedoParagraph();
return;
case LyXTable::TOGGLE_LINE_RIGHT:
lineSet = !cursor.par->table->RightLine(actCell);
if (!selection){
cursor.par->table->SetRightLine(actCell,lineSet);
} else {
int i,n=-1,m=-2;
for (i=sel_start_cursor.pos; i<=sel_end_cursor.pos; i++){
if ((n=NumberOfCell(sel_start_cursor.par,i)) != m) {
cursor.par->table->SetRightLine(n,lineSet);
m = n;
}
}
}
RedoParagraph();
return;
case LyXTable::ALIGN_LEFT:
case LyXTable::ALIGN_RIGHT:
case LyXTable::ALIGN_CENTER:
if (!selection){
cursor.par->table->SetAlignment(actCell,setAlign);
} else {
int i,n=-1,m=-2;
for (i=sel_start_cursor.pos; i<=sel_end_cursor.pos; i++){
if ((n=NumberOfCell(sel_start_cursor.par,i)) != m) {
cursor.par->table->SetAlignment(n,setAlign);
m = n;
}
}
}
RedoParagraph();
return;
case LyXTable::DELETE_TABLE:
SetCursorIntern(cursor.par, 0);
delete cursor.par->table;
cursor.par->table = NULL;
// temporary: Should put table in simple_cut_buffer (with before and after
// dummy-paragraph !!
// not necessar anymore with UNDO :)
int i;
for (i = cursor.par->last-1; i>=0; i--)
cursor.par->Erase(i);
RedoParagraph();
return;
case LyXTable::MULTICOLUMN: {
int number = 0;
// check wether we are completly in a multicol
int multicol = cursor.par->table->IsMultiColumn(actCell);
if (multicol && selection && sel_start_cursor.row == sel_end_cursor.row){
multicol = NumberOfCell(sel_start_cursor.par, sel_start_cursor.pos)
== NumberOfCell(sel_end_cursor.par, sel_end_cursor.pos);
}
if (multicol){
int newlines = cursor.par->table->UnsetMultiColumn(actCell);
int pos = cursor.pos;
while (pos<cursor.par->Last() && !cursor.par->IsNewline(pos))
pos++;
for (;newlines;newlines--)
cursor.par->InsertChar(pos, LYX_META_NEWLINE);
RedoParagraph();
return;
}
else {
// selection must be in one row (or no selection)
if (!selection){
cursor.par->table->SetMultiColumn(NumberOfCell(cursor.par,
cursor.pos),
1);
RedoParagraph();
return;
}
else {
if (sel_start_cursor.row == sel_end_cursor.row){
int i;
number = 1;
for (i=sel_start_cursor.pos; i<sel_end_cursor.pos; i++){
if (sel_start_cursor.par->IsNewline(i)){
sel_start_cursor.par->Erase(i);
// check for double-blanks
if ((i && !sel_start_cursor.par->IsLineSeparator(i-1))
&&
(i<sel_start_cursor.par->Last()
&& !sel_start_cursor.par->IsLineSeparator(i)))
sel_start_cursor.par->InsertChar(i, ' ');
else {
sel_end_cursor.pos--;
i--;
}
number++;
}
}
cursor.par->table->
SetMultiColumn(NumberOfCell(sel_start_cursor.par,
sel_start_cursor.pos),
number);
cursor.pos = sel_start_cursor.pos;
RedoParagraph();
return;
}
else {
WriteAlert(i18n("Impossible Operation!"),
i18n("Multicolumns can only be horizontally."),
i18n("Sorry."));
}
}
}
break;
}
case LyXTable::SET_ALL_LINES:
setLines = 1;
case LyXTable::UNSET_ALL_LINES:
if (!selection){
cursor.par->table->SetAllLines(NumberOfCell(cursor.par,
cursor.pos),
setLines);
} else {
int i,n=-1,m=-2;
for (i=sel_start_cursor.pos; i<=sel_end_cursor.pos; i++){
if ((n=NumberOfCell(sel_start_cursor.par,i)) != m) {
cursor.par->table->SetAllLines(n,setLines);
m = n;
}
}
}
RedoParagraph();
return;
case LyXTable::SET_NORMALTABLE:
cursor.par->table->SetRotateTable(false);
cursor.par->table->SetLongTable(false);
return;
case LyXTable::SET_LONGTABLE:
cursor.par->table->SetRotateTable(false);
cursor.par->table->SetLongTable(true);
return;
case LyXTable::UNSET_LONGTABLE:
cursor.par->table->SetLongTable(false);
return;
case LyXTable::SET_ROTATE_TABLE:
cursor.par->table->SetLongTable(false);
cursor.par->table->SetRotateTable(true);
return;
case LyXTable::UNSET_ROTATE_TABLE:
cursor.par->table->SetRotateTable(false);
return;
case LyXTable::SET_ROTATE_CELL:
if (!selection){
cursor.par->table->SetRotateCell(actCell,true);
} else {
int i,n=-1,m=-2;
for (i=sel_start_cursor.pos; i<=sel_end_cursor.pos; i++){
if ((n=NumberOfCell(sel_start_cursor.par,i)) != m) {
cursor.par->table->SetRotateCell(n,true);
m = n;
}
}
}
return;
case LyXTable::UNSET_ROTATE_CELL:
if (!selection){
cursor.par->table->SetRotateCell(actCell,false);
} else {
int i,n=-1,m=-2;
for (i=sel_start_cursor.pos; i<=sel_end_cursor.pos; i++){
if ((n=NumberOfCell(sel_start_cursor.par,i)) != m) {
cursor.par->table->SetRotateCell(n,false);
m = n;
}
}
}
return;
case LyXTable::SET_LINEBREAKS:
what = !cursor.par->table->Linebreaks(cursor.par->table->FirstVirtualCell(actCell));
if (!selection){
cursor.par->table->SetLinebreaks(actCell,what);
} else {
int i,n=-1,m=-2;
for (i=sel_start_cursor.pos; i<=sel_end_cursor.pos; i++){
if ((n=NumberOfCell(sel_start_cursor.par,i)) != m) {
cursor.par->table->SetLinebreaks(n,what);
m = n;
}
}
}
return;
case LyXTable::SET_LTFIRSTHEAD:
cursor.par->table->SetLTHead(actCell,true);
return;
case LyXTable::SET_LTHEAD:
cursor.par->table->SetLTHead(actCell,false);
return;
case LyXTable::SET_LTFOOT:
cursor.par->table->SetLTFoot(actCell,false);
return;
case LyXTable::SET_LTLASTFOOT:
cursor.par->table->SetLTFoot(actCell,true);
return;
case LyXTable::SET_LTNEWPAGE:
cursor.par->table->SetLTNewPage(actCell,true);
return;
case LyXTable::SET_LTNORMAL:
cursor.par->table->LTClear(actCell);
return;
}
}
klyx'LyXText::InsertCharInTable() (./klyx/src/text.C:2053)
void LyXText::InsertCharInTable(char c)
{
Row *row;
Row *tmprow;
long y;
bool jumped_over_space;
/* first check, if there will be two blanks together or a blank at
* the beginning of a paragraph.
* I decided to handle blanks like normal characters, the main
* difference are the special checks when calculating the row.fill
* (blank does not count at the end of a row) and the check here */
LyXFont realtmpfont = real_current_font;
LyXFont rawtmpfont = current_font; /* store the current font.
* This is because of the use
* of cursor movements. The moving
* cursor would refresh the
* current font */
// Get the font that is used to calculate the baselineskip
int const lastpos = cursor.par->Last();
LyXFont rawparfont = cursor.par->GetFontSettings(lastpos - 1);
jumped_over_space = false;
if (IsLineSeparatorChar(c)) {
/* avoid double blanks but insert the new blank because
* of a possible font change */
if (cursor.pos < lastpos &&
cursor.par->IsLineSeparator(cursor.pos))
{
cursor.par->Erase(cursor.pos);
jumped_over_space = true;
}
else if ((cursor.pos > 0 &&
cursor.par->IsLineSeparator(cursor.pos - 1))
|| (cursor.pos > 0 && cursor.par->IsNewline(cursor.pos - 1))
|| (cursor.pos == 0 &&
!(cursor.par->Previous()
&& cursor.par->Previous()->footnoteflag
== LyXParagraph::OPEN_FOOTNOTE)))
return;
}
else if (IsNewlineChar(c)) {
if (!IsEmptyTableCell()) {
TableFeatures(LyXTable::APPEND_CONT_ROW);
CursorDown();
}
/* the newline character is the separator of the cells */
// cursor.par->InsertChar(cursor.pos, c);
// SetCharFont(cursor.par, cursor.pos, rawtmpfont);
// RedoParagraphs(cursor, cursor.par->Next());
// SetCursor(cursor.par, cursor.pos+1);
return;
}
row = cursor.row;
y = cursor.y - row->baseline;
if (c != QChar( (int)LYX_META_INSET)) /* in this case LyXText::InsertInset
* already inserted the character */
cursor.par->InsertChar(cursor.pos, c);
SetCharFont(cursor.par, cursor.pos, rawtmpfont);
if (!jumped_over_space) {
/* refresh the positions */
tmprow = row;
while (tmprow->next && tmprow->next->par == row->par) {
tmprow = tmprow->next;
tmprow->pos++;
}
}
cursor.pos++;
CheckParagraphInTable(cursor.par, cursor.pos);
current_font = rawtmpfont;
real_current_font = realtmpfont;
/* check, whether the last character's font has changed. */
if (cursor.pos && cursor.pos == cursor.par->Last()
&& rawparfont != rawtmpfont)
RedoHeightOfParagraph(cursor);
}
klyx'LyXText::CheckParagraphInTable() (./klyx/src/text.C:2140)
void LyXText::CheckParagraphInTable(LyXParagraph* par, int pos)
{
Row *row;
long y;
if (par->GetChar(pos) == QChar( (int)LYX_META_INSET) &&
par->GetInset(pos) && par->GetInset(pos)->Display()){
par->GetInset(pos)->SetDisplay(false);
}
row = GetRow(par, pos, y);
int tmpheight = row->height;
SetHeightOfRow(row);
int tmp_pos = pos;
/* update the table information */
while (tmp_pos && !par->IsNewline(tmp_pos - 1))
tmp_pos--;
if (par->table->SetWidthOfCell(NumberOfCell(par, pos),
WidthOfCell(par, tmp_pos))) {
LyXCursor tmpcursor = cursor;
SetCursorIntern(par, pos);
/* make a complete redraw */
RedoDrawingOfParagraph(cursor);
cursor = tmpcursor;
}
else {
/* redraw only the row */
LyXCursor tmpcursor = cursor;
SetCursorIntern(par, pos);
refresh_y = y;
refresh_x = cursor.x;
refresh_row = row;
refresh_pos = cursor.pos;
cursor = tmpcursor;
if (tmpheight == row->height)
status = LyXText::NEED_VERY_LITTLE_REFRESH;
else
status = LyXText::NEED_MORE_REFRESH;
}
SetCursorIntern(cursor.par, cursor.pos);
}
klyx'LyXText::BackspaceInTable() (./klyx/src/text.C:2186)
void LyXText::BackspaceInTable()
{
Row *tmprow, *row;
long y;
LyXFont rawtmpfont = current_font;
LyXFont realtmpfont = real_current_font;
// Get the font that is used to calculate the baselineskip
int const lastpos = cursor.par->Last();
LyXFont rawparfont = cursor.par->GetFontSettings(lastpos - 1);
if (cursor.pos == 0) {
/* no pasting of table paragraphs */
CursorLeft();
}
else {
/* this is the code for a normal backspace, not pasting
* any paragraphs */
SetUndo(Undo::DELETE,
cursor.par->ParFromPos(cursor.pos)->previous,
cursor.par->ParFromPos(cursor.pos)->next);
CursorLeftIntern();
/* some insets are undeletable here */
if (cursor.par->GetChar(cursor.pos)==QChar( (int)LYX_META_INSET)) {
if (!cursor.par->GetInset(cursor.pos)->Deletable())
return;
}
row = cursor.row;
y = cursor.y - row->baseline;
/* some special code when deleting a newline. */
if (cursor.par->IsNewline(cursor.pos)) {
/* nothing :-) */
return;
}
else {
cursor.par->Erase(cursor.pos);
/* refresh the positions */
tmprow = row;
while (tmprow->next && tmprow->next->par == row->par) {
tmprow = tmprow->next;
tmprow->pos--;
}
/* delete superfluous blanks */
if (cursor.pos < cursor.par->Last() - 1 &&
(cursor.par->IsLineSeparator(cursor.pos))) {
if (cursor.pos == BeginningOfMainBody(cursor.par)
|| !cursor.pos
|| cursor.par->IsLineSeparator(cursor.pos - 1)) {
cursor.par->Erase(cursor.pos);
/* refresh the positions */
tmprow = row;
while (tmprow->next &&
tmprow->next->par == row->par) {
tmprow = tmprow->next;
tmprow->pos--;
}
if (cursor.pos) /* move one character left */
cursor.pos--;
}
}
}
CheckParagraphInTable(cursor.par, cursor.pos);
/* check, wether the last characters font has changed. */
if (cursor.pos && cursor.pos == cursor.par->Last()
&& rawparfont != rawtmpfont)
RedoHeightOfParagraph(cursor);
/* restore the current font
* That is what a user expects! */
current_font = rawtmpfont;
real_current_font = realtmpfont;
}
SetCursorIntern(cursor.par, cursor.pos);
}
/* table stuff -- end*/
/* just a macro to make some thing easier. */
klyx'LyXText::RedoParagraph() (./klyx/src/text.C:2276)
void LyXText::RedoParagraph()
{
LyXCursor tmpcursor = cursor;
ClearSelection();
RedoParagraphs(cursor, cursor.par->Next());;
SetCursorIntern(tmpcursor.par, tmpcursor.pos);
}
/* insert a character, moves all the following breaks in the
* same Paragraph one to the right and make a rebreak */
klyx'LyXText::InsertChar() (./klyx/src/text.C:2287)
void LyXText::InsertChar(char c)
{
Row *row;
Row *tmprow;
int z;
long y;
bool jumped_over_space;
LyXFont realtmpfont;
LyXFont rawtmpfont;
int lastpos;
LyXFont rawparfont;
SetUndo(Undo::INSERT,
cursor.par->ParFromPos(cursor.pos)->previous,
cursor.par->ParFromPos(cursor.pos)->next);
/* When the free-spacing option is set for the current layout,
* all spaces are converted to protected spaces. */
bool freeSpacingBo =
lyxstyle.Style(parameters->textclass,
cursor.row->par->GetLayout())->free_spacing;
//
// Is this wanted? There cannot be a line break between protected
// separators. Therefore I suggest the way implemented below
// (Matthias)
//
// if ( freeSpacingBo && IsLineSeparatorChar(c) )
// c = LYX_META_PROTECTED_SEPARATOR;
if (freeSpacingBo && IsLineSeparatorChar(c)
&& (!cursor.pos || cursor.par->IsLineSeparator(cursor.pos-1)))
c = LYX_META_PROTECTED_SEPARATOR;
/* table stuff -- begin*/
if (cursor.par->table) {
InsertCharInTable(c);
goto out;
}
/* table stuff -- end*/
/* first check, if there will be two blanks together or a blank at
* the beginning of a paragraph.
* I decided to handle blanks like normal characters, the main
* difference are the special checks when calculating the row.fill
* (blank does not count at the end of a row) and the check here */
realtmpfont = real_current_font;
rawtmpfont = current_font; /* store the current font.
* This is because of the use
* of cursor movements. The moving
* cursor would refresh the
* current font */
// Get the font that is used to calculate the baselineskip
lastpos = cursor.par->Last();
rawparfont = cursor.par->GetFontSettings(lastpos - 1);
jumped_over_space = false;
if (IsLineSeparatorChar(c)) {
if (cursor.pos < lastpos
&& cursor.par->IsLineSeparator(cursor.pos)) {
/* some special code here (klyx). If the users auto
deleted a region by typing something it might
happen, that there are two blanks, one before the
cursor and one behind. Usually this is not a
problem, because auto deletion only happens, if
something is inserted. A problem occurs, if the
inserted character is a blank as well. Therefore
this workaround: */
if (cursor.pos > 0 && cursor.par->IsLineSeparator(cursor.pos-1)){
Backspace();
}
/* the user inserted a space before a space. So we
* will just make a CursorRight. BUT: The font of this
* space should be set to current font. That is why
* we need to rebreak perhaps. If there is a protected
* blank at the end of a row we have to force
* a rebreak.*/
if (cursor.pos == RowLast(cursor.row)
&& !IsLineSeparatorChar(c))
cursor.row->fill = -1; /* force rebreak */
cursor.par->Erase(cursor.pos);
jumped_over_space = true;
} else if ((cursor.pos > 0
&& cursor.par->IsLineSeparator(cursor.pos - 1))
|| (cursor.pos > 0
&& cursor.par->IsNewline(cursor.pos - 1))
|| (cursor.pos == 0
&& !(cursor.par->Previous()
&& cursor.par->Previous()->footnoteflag
== LyXParagraph::OPEN_FOOTNOTE)))
goto out;
} else if (IsNewlineChar(c)) {
if (cursor.par->FirstPhysicalPar() == cursor.par
&& cursor.pos <= BeginningOfMainBody(cursor.par))
goto out;
/* no newline at first position
* of a paragraph or behind labels.
* TeX does not allow that. */
if (cursor.pos < cursor.par->Last() &&
cursor.par->IsLineSeparator(cursor.pos))
CursorRightIntern(); // newline always after a blank!
cursor.row->fill = -1; // to force a new break
}
/* the display inset stuff */
if (cursor.row->par->GetChar(cursor.row->pos) == QChar( (int)LYX_META_INSET)
&& cursor.row->par->GetInset(cursor.row->pos)
&& cursor.row->par->GetInset(cursor.row->pos)->Display())
cursor.row->fill = -1; // to force a new break
/* get the cursor row fist */
/* this is a dumb solution, i will try to hold the cursor.row
in future */
/* row = GetRow(cursor.par, cursor.pos, y);*/
/* ok, heres a better way: */
row = cursor.row;
y = cursor.y - row->baseline;
if (c != QChar( (int)LYX_META_INSET)) /* in this case LyXText::InsertInset
* already insertet the character */
cursor.par->InsertChar(cursor.pos, c);
SetCharFont(cursor.par, cursor.pos, rawtmpfont);
if (!jumped_over_space) {
/* refresh the positions */
tmprow = row;
while (tmprow->next && tmprow->next->par == row->par) {
tmprow = tmprow->next;
tmprow->pos++;
}
}
/* Is there a break one row above */
if ((cursor.par->IsLineSeparator(cursor.pos)
|| cursor.par->IsNewline(cursor.pos)
|| cursor.row->fill == -1)
&& row->previous && row->previous->par == row->par) {
z = NextBreakPoint(row->previous, paperwidth);
if ( z >= row->pos) {
row->pos = z + 1;
/* set the dimensions of the row above */
row->previous->fill = Fill(row->previous, paperwidth);
SetHeightOfRow(row->previous);
y -= row->previous->height;
refresh_y = y;
refresh_row = row->previous;
status = LyXText::NEED_MORE_REFRESH;
BreakAgainOneRow(row);
SetCursor(cursor.par, cursor.pos + 1);
/* cursor MUST be in row now */
if (row->next && row->next->par == row->par)
need_break_row = row->next;
else
need_break_row = NULL;
current_font = rawtmpfont;
real_current_font = realtmpfont;
// check, wether the last characters font has changed.
if (cursor.pos && cursor.pos == cursor.par->Last()
&& rawparfont != rawtmpfont)
RedoHeightOfParagraph(cursor);
goto out;
}
}
/* recalculate the fill of the row */
if (row->fill >= 0) /* needed because a newline
* will set fill to -1. Otherwise
* we would not get a rebreak! */
row->fill = Fill(row, paperwidth);
if (row->fill < 0 ) {
refresh_y = y;
refresh_row = row;
refresh_x = cursor.x;
refresh_pos = cursor.pos;
status = LyXText::NEED_MORE_REFRESH;
BreakAgainOneRow(row);
/* will the cursor be in another row now? */
if (RowLast(row) <= cursor.pos + 1 && row->next) {
if (row->next && row->next->par == row->par)
/* this should
* always be true */
row = row->next;
BreakAgainOneRow(row);
}
SetCursor(cursor.par, cursor.pos + 1);
if (row->next && row->next->par == row->par)
need_break_row = row->next;
else
need_break_row = NULL;
current_font = rawtmpfont;
real_current_font = realtmpfont;
} else {
refresh_y = y;
refresh_x = cursor.x;
refresh_row = row;
refresh_pos = cursor.pos;
int tmpheight = row->height;
SetHeightOfRow(row);
if (tmpheight == row->height)
status = LyXText::NEED_VERY_LITTLE_REFRESH;
else
status = LyXText::NEED_MORE_REFRESH;
SetCursor(cursor.par, cursor.pos + 1);
current_font = rawtmpfont;
real_current_font = realtmpfont;
}
/* check, wether the last characters font has changed. */
if (cursor.pos && cursor.pos == cursor.par->Last()
&& rawparfont != rawtmpfont) {
RedoHeightOfParagraph(cursor);
} else {
/* now the special right address boxes */
if (lyxstyle.Style(parameters->textclass,
cursor.par->GetLayout())->margintype
== MARGIN_RIGHT_ADDRESS_BOX) {
RedoDrawingOfParagraph(cursor);
}
}
out:
// Here we could call FinishUndo for every 20 characters inserted.
// This is from my experience how emacs does it. (Lgb)
// lifted to 64 (Matthias)
static unsigned short counter = 0;
if (counter < 64) {
++counter;
} else {
FinishUndo();
counter = 0;
}
return;
}
klyx'LyXText::PrepareToPrint() (./klyx/src/text.C:2539)
void LyXText::PrepareToPrint(Row *row, float &x, float &fill_separator,
float &fill_hfill, float &fill_label_hfill)
{
float w, nh, nlh, ns;
w = row->fill;
fill_hfill = 0;
fill_label_hfill = 0;
fill_separator = 0;
fill_label_hfill = 0;
x = LeftMargin(row);
/* is there a manual margin with a manual label */
if (lyxstyle.Style(parameters->textclass,
row->par->GetLayout())->margintype == MARGIN_MANUAL
&& lyxstyle.Style(parameters->textclass,
row->par->GetLayout())->labeltype == LABEL_MANUAL) {
nlh = NumberOfLabelHfills(row) + 1; /* one more since labels
* are left aligned*/
if (nlh && !row->par->GetLabelWidthString().empty()) {
fill_label_hfill = LabelFill(row) / nlh;
}
}
/* are there any hfills in the row? */
nh = NumberOfHfills(row);
/* table stuff -- begin*/
if (row->par->table) {
w = paperwidth - row->par->table->WidthOfTable()
- x - RightMargin(row);
nh = 0; /* ignore hfills in tables */
}
/* table stuff -- end*/
if (nh)
fill_hfill = w /nh;
else {
/* is it block, flushleft or flushright?
* set x how you need it */
int align;
if (row->par->FirstPhysicalPar()->align == LYX_ALIGN_LAYOUT)
align = lyxstyle.Style(parameters->textclass, row->par->GetLayout())->align;
else
align = row->par->FirstPhysicalPar()->align;
/* center displayed insets */
if (row->par->GetChar(row->pos) == QChar( (int)LYX_META_INSET)
&& row->par->GetInset(row->pos)
&& row->par->GetInset(row->pos)->Display())
align = LYX_ALIGN_CENTER;
switch (align) {
case LYX_ALIGN_BLOCK:
ns = NumberOfSeparators(row);
if (ns && row->next && row->next->par == row->par &&
!(row->next->par->IsNewline(row->next->pos-1))
&& !(row->next->par->GetChar(row->next->pos) == QChar( (int)LYX_META_INSET)
&& row->next->par->GetInset(row->next->pos)
&& row->next->par->GetInset(row->next->pos)->Display())
)
fill_separator = w / ns;
break;
case LYX_ALIGN_RIGHT:
x += w;
break;
case LYX_ALIGN_CENTER:
x += w / 2;
break;
}
}
}
/* important for the screen */
/* the cursor set functions have a special mechanism. When they
* realize, that you left an empty paragraph, they will delete it.
* They also delet the corresponding row */
klyx'LyXText::CursorRightOneWord() (./klyx/src/text.C:2623)
void LyXText::CursorRightOneWord()
{
// Now this function moves the cursor to the beginning of
// the current (or next) word, as in (X)Emacs an another
// emacs-like editors.
// treat floats, HFills and Insets as words
LyXCursor tmpcursor = cursor;
if (tmpcursor.pos == tmpcursor.par->Last()
&& tmpcursor.par->Next())
{
tmpcursor.par = tmpcursor.par->Next();
tmpcursor.pos = 0;
} else {
while (tmpcursor.pos < tmpcursor.par->Last()
&& (tmpcursor.par->IsSeparator(tmpcursor.pos)
|| tmpcursor.par->IsKomma(tmpcursor.pos)
|| tmpcursor.par->IsHfill(tmpcursor.pos)
|| tmpcursor.par->IsFloat(tmpcursor.pos)
|| tmpcursor.par->IsInset(tmpcursor.pos)))
{
tmpcursor.pos++;
if (tmpcursor.par->IsInset(tmpcursor.pos-1)
|| tmpcursor.par->IsFloat(tmpcursor.pos-1)
|| tmpcursor.par->IsHfill(tmpcursor.pos-1))
break;
}
if (tmpcursor.pos == cursor.pos
|| !(tmpcursor.par->IsInset(tmpcursor.pos-1)
|| tmpcursor.par->IsFloat(tmpcursor.pos-1)
|| tmpcursor.par->IsHfill(tmpcursor.pos-1)))
while (tmpcursor.pos < tmpcursor.par->Last()
&& !tmpcursor.par->IsSeparator(tmpcursor.pos)
&& !tmpcursor.par->IsKomma(tmpcursor.pos)
&& !tmpcursor.par->IsHfill(tmpcursor.pos)
&& !tmpcursor.par->IsFloat(tmpcursor.pos)
&& !tmpcursor.par->IsInset(tmpcursor.pos))
tmpcursor.pos++;
}
SetCursor(tmpcursor.par, tmpcursor.pos);
}
klyx'LyXText::CursorTab() (./klyx/src/text.C:2666)
void LyXText::CursorTab()
{
if (cursor.par->table) {
int cell = NumberOfCell(cursor.par, cursor.pos);
while(cursor.par->table->IsContRow(cell)) {
CursorUp();
cell = NumberOfCell(cursor.par, cursor.pos);
}
if (cursor.par->table->ShouldBeVeryLastCell(cell))
TableFeatures(LyXTable::APPEND_ROW);
}
LyXCursor tmpcursor = cursor;
while (tmpcursor.pos < tmpcursor.par->Last()
&& !tmpcursor.par->IsNewline(tmpcursor.pos))
tmpcursor.pos++;
if (tmpcursor.pos == tmpcursor.par->Last()){
if (tmpcursor.par->Next()) {
tmpcursor.par = tmpcursor.par->Next();
tmpcursor.pos = 0;
}
}
else
tmpcursor.pos++;
SetCursor(tmpcursor.par, tmpcursor.pos);
if (cursor.par->table) {
int cell = NumberOfCell(cursor.par, cursor.pos);
while (cursor.par->table->IsContRow(cell) &&
!cursor.par->table->ShouldBeVeryLastCell(cell)) {
tmpcursor = cursor;
while (tmpcursor.pos < tmpcursor.par->Last()
&& !tmpcursor.par->IsNewline(tmpcursor.pos))
tmpcursor.pos++;
if (tmpcursor.pos == tmpcursor.par->Last()){
if (tmpcursor.par->Next()) {
tmpcursor.par = tmpcursor.par->Next();
tmpcursor.pos = 0;
}
}
else
tmpcursor.pos++;
SetCursor(tmpcursor.par, tmpcursor.pos);
cell = NumberOfCell(cursor.par, cursor.pos);
}
}
}
/* -------> Skip initial whitespace at end of word and move cursor to *start*
of prior word, not to end of next prior word. */
klyx'LyXText::CursorLeftOneWord() (./klyx/src/text.C:2718)
void LyXText::CursorLeftOneWord()
{
// treat HFills, floats and Insets as words
LyXCursor tmpcursor = cursor;
while (tmpcursor.pos
&& (tmpcursor.par->IsSeparator(tmpcursor.pos - 1)
|| tmpcursor.par->IsKomma(tmpcursor.pos - 1))
&& !(tmpcursor.par->IsHfill(tmpcursor.pos - 1)
|| tmpcursor.par->IsFloat(tmpcursor.pos - 1)
|| tmpcursor.par->IsInset(tmpcursor.pos - 1)))
tmpcursor.pos--;
if (tmpcursor.pos
&& (tmpcursor.par->IsInset(tmpcursor.pos - 1)
|| tmpcursor.par->IsFloat(tmpcursor.pos - 1)
|| tmpcursor.par->IsHfill(tmpcursor.pos - 1))) {
tmpcursor.pos--;
} else if (!tmpcursor.pos) {
if (tmpcursor.par->Previous()){
tmpcursor.par = tmpcursor.par->Previous();
tmpcursor.pos = tmpcursor.par->Last();
}
} else {
while (tmpcursor.pos > 0
&& !tmpcursor.par->IsSeparator(tmpcursor.pos-1)
&& !tmpcursor.par->IsKomma(tmpcursor.pos-1)
&& !tmpcursor.par->IsHfill(tmpcursor.pos-1)
&& !tmpcursor.par->IsFloat(tmpcursor.pos-1)
&& !tmpcursor.par->IsInset(tmpcursor.pos-1))
tmpcursor.pos--;
}
SetCursor(tmpcursor.par, tmpcursor.pos);
}
/* -------> Select current word. This depeds on behaviour of CursorLeftOneWord(), so it is
patched as well. */
klyx'LyXText::SelectWord() (./klyx/src/text.C:2755)
void LyXText::SelectWord()
{
/* Move cursor to the beginning, when not already there. */
if ( cursor.pos
&& !cursor.par->IsSeparator(cursor.pos-1)
&& !cursor.par->IsKomma(cursor.pos-1) )
CursorLeftOneWord();
/* set the sel cursor */
sel_cursor = cursor;
while ( cursor.pos < cursor.par->Last()
&& !cursor.par->IsSeparator(cursor.pos)
&& !cursor.par->IsKomma(cursor.pos) )
cursor.pos++;
SetCursor( cursor.par, cursor.pos );
/* finally set the selection */
SetSelection();
}
klyx'LyXText::ExchangeCursorAndSelection() (./klyx/src/text.C:2776)
void LyXText::ExchangeCursorAndSelection() { // Rocher 981127
if (!selection)
return;
LyXCursor tmpcursor = sel_cursor;
sel_cursor = cursor;
SetCursor( tmpcursor.par, tmpcursor.pos );
SetSelection();
}
/* -------> Select the word currently under the cursor when:
1: no selection is currently set,
2: the cursor is not at the borders of the word. */
klyx'LyXText::SelectWordWhenUnderCursor() (./klyx/src/text.C:2789)
int LyXText::SelectWordWhenUnderCursor()
{
if ( selection ) return 0;
if ( cursor.pos < cursor.par->Last()
&& !cursor.par->IsSeparator(cursor.pos)
&& !cursor.par->IsKomma(cursor.pos)
&& cursor.pos
&& !cursor.par->IsSeparator(cursor.pos -1)
&& !cursor.par->IsKomma(cursor.pos -1) ) {
SelectWord();
return 1;
}
return 0;
}
// This function is only used by the spellchecker for NextWord().
// It doesn't handle LYX_ACCENTs and probably never will.
klyx'LyXText::SelectNextWord() (./klyx/src/text.C:2807)
char* LyXText::SelectNextWord(float &value)
{
LyXParagraph* tmppar = cursor.par;
// If this is not the very first word, skip rest of
// current word because we are probably in the middle
// of a word if there is text here.
if (cursor.pos || cursor.par->previous) {
while (cursor.pos < cursor.par->Last()
&& cursor.par->IsLetter(cursor.pos))
cursor.pos++;
}
// Now, skip until we have real text (will jump paragraphs)
while ((cursor.par->Last() > cursor.pos
&& !cursor.par->IsLetter(cursor.pos))
|| (cursor.par->Last() == cursor.pos
&& cursor.par->Next())){
if (cursor.pos == cursor.par->Last()) {
cursor.par = cursor.par->Next();
cursor.pos = 0;
}
else
cursor.pos++;
}
// Update the value if we changed paragraphs
if (cursor.par != tmppar){
SetCursor(cursor.par, cursor.pos);
value = float(cursor.y)/float(height);
}
/* Start the selection from here */
sel_cursor = cursor;
/* and find the end of the word */
while (cursor.pos < cursor.par->Last()
&& cursor.par->IsLetter(cursor.pos))
cursor.pos++;
// Finally, we copy the word to a string and return it
char* string = NULL;
if (sel_cursor.pos < cursor.pos) {
string = new char [cursor.pos - sel_cursor.pos + 2];
int i,j;
for (i=sel_cursor.pos, j=0; i<cursor.pos; i++)
string[j++] = cursor.par->GetChar(i);
string[j] = '\0';
}
return string;
}
// This one is also only for the spellchecker
klyx'LyXText::SelectSelectedWord() (./klyx/src/text.C:2862)
void LyXText::SelectSelectedWord()
{
/* move cursor to the beginning */
SetCursor(sel_cursor.par, sel_cursor.pos);
/* set the sel cursor */
sel_cursor = cursor;
/* now find the end of the word */
while (cursor.pos < cursor.par->Last()
&& cursor.par->IsLetter(cursor.pos))
cursor.pos++;
SetCursor(cursor.par, cursor.pos);
/* finally set the selection */
SetSelection();
}
/* -------> Delete from cursor up to the end of the current or next word. */
klyx'LyXText::DeleteWordForward() (./klyx/src/text.C:2883)
void LyXText::DeleteWordForward()
{
LyXCursor tmpcursor = cursor;
if (!cursor.par->Last())
CursorRight();
else {
/* -------> Skip initial non-word stuff. */
while ( cursor.pos < cursor.par->Last()
&& (cursor.par->IsSeparator(cursor.pos)
|| cursor.par->IsKomma(cursor.pos)) )
cursor.pos++;
SetCursorIntern(cursor.par, cursor.pos);
selection = True; // to avoid deletion
CursorRightOneWord();
// not sure about that.....
while (cursor.par->IsSeparator(cursor.pos-1) ||
cursor.par->IsKomma(cursor.pos-1))
cursor.pos--;
sel_cursor = cursor;
cursor = tmpcursor;
SetSelection();
/* -----> Great, CutSelection() gets rid of multiple spaces. */
CutSelection();
}
}
/* -------> Delete from cursor to start of current or prior word. */
klyx'LyXText::DeleteWordBackward() (./klyx/src/text.C:2916)
void LyXText::DeleteWordBackward()
{
LyXCursor tmpcursor = cursor;
if (!cursor.par->Last())
CursorLeft();
else{
selection = True; // to avoid deletion
CursorLeftOneWord();
sel_cursor = cursor;
cursor = tmpcursor;
SetSelection();
CutSelection();
}
}
/* -------> Kill to end of line. */
klyx'LyXText::DeleteLineForward() (./klyx/src/text.C:2933)
void LyXText::DeleteLineForward()
{
LyXCursor tmpcursor = cursor;
if (!cursor.par->Last())
CursorRight();
else {
CursorEnd();
sel_cursor = cursor;
cursor = tmpcursor;
SetSelection();
if (selection == false) {
DeleteWordForward();
} else {
CutSelection();
}
}
}
/* -------> Upcase characters from cursor to end of word. */
klyx'LyXText::UpcaseWord() (./klyx/src/text.C:2953)
void LyXText::UpcaseWord()
{
SetUndo(Undo::FINISH,
cursor.par->ParFromPos(cursor.pos)->previous,
cursor.par->ParFromPos(cursor.pos)->next);
while (cursor.pos < cursor.par->Last()
&& !cursor.par->IsSeparator(cursor.pos)
&& !cursor.par->IsKomma(cursor.pos) ) {
if (cursor.par->GetChar(cursor.pos) != QChar( (int)LYX_META_INSET))
cursor.par->text[cursor.pos] =
toupper((unsigned char) cursor.par->text[cursor.pos]);
CursorRight();
}
CheckParagraph(cursor.par, cursor.pos);
// CursorRightOneWord();
}
/* -------> Lowcase characters from cursor to end of word. */
klyx'LyXText::LowcaseWord() (./klyx/src/text.C:2973)
void LyXText::LowcaseWord()
{
SetUndo(Undo::FINISH,
cursor.par->ParFromPos(cursor.pos)->previous,
cursor.par->ParFromPos(cursor.pos)->next);
while ( cursor.pos < cursor.par->Last()
&& !cursor.par->IsSeparator(cursor.pos)
&& !cursor.par->IsKomma(cursor.pos) ) {
if (cursor.par->GetChar(cursor.pos) != QChar( (int)LYX_META_INSET))
cursor.par->text[cursor.pos] =
tolower((unsigned char) cursor.par->text[cursor.pos]);
CursorRight();
}
CheckParagraph(cursor.par, cursor.pos);
// CursorRightOneWord();
}
/* -------> Capitalize characters from cursor to end of word. */
klyx'LyXText::CapitalizeWord() (./klyx/src/text.C:2993)
void LyXText::CapitalizeWord()
{
SetUndo(Undo::FINISH,
cursor.par->ParFromPos(cursor.pos)->previous,
cursor.par->ParFromPos(cursor.pos)->next);
bool firstBo = true;
while ( cursor.pos < cursor.par->Last()
&& !cursor.par->IsSeparator(cursor.pos)
&& !cursor.par->IsKomma(cursor.pos) ) {
if ( firstBo ){
if (cursor.par->GetChar(cursor.pos) != QChar( (int)LYX_META_INSET))
cursor.par->text[cursor.pos]
= toupper((unsigned char) cursor.par->text[cursor.pos]);
}
else{
if (cursor.par->GetChar(cursor.pos) != QChar( (int)LYX_META_INSET))
cursor.par->text[cursor.pos]
= tolower((unsigned char) cursor.par->text[cursor.pos]);
}
firstBo = false;
CursorRight();
}
CheckParagraph(cursor.par, cursor.pos);
// CursorRightOneWord();
}
klyx'LyXText::Delete() (./klyx/src/text.C:3021)
void LyXText::Delete()
{
LyXCursor old_cursor = cursor;
LyXCursor tmpcursor;
/* this is a very easy implementation*/
/* just move to the right */
CursorRightIntern();
if (cursor.par->previous == old_cursor.par->previous
&& cursor.par != old_cursor.par)
return; // delete-emty-paragraph-mechanism has done it
/* if you had success make a backspace */
if (old_cursor.par != cursor.par || old_cursor.pos != cursor.pos) {
tmpcursor = cursor;
cursor = old_cursor; // to make sure undo gets the right cursor position
SetUndo(Undo::DELETE,
cursor.par->ParFromPos(cursor.pos)->previous,
cursor.par->ParFromPos(cursor.pos)->next);
cursor = tmpcursor;
Backspace();
}
}
klyx'LyXText::Backspace() (./klyx/src/text.C:3047)
void LyXText::Backspace()
{
LyXParagraph *tmppar;
Row *tmprow, *row;
long y;
int tmpheight;
/* table stuff -- begin*/
if (cursor.par->table) {
BackspaceInTable();
return;
}
/* table stuff -- end*/
LyXFont rawtmpfont = current_font;
LyXFont realtmpfont = real_current_font;
// Get the font that is used to calculate the baselineskip
int const lastpos = cursor.par->Last();
LyXFont rawparfont = cursor.par->GetFontSettings(lastpos - 1);
if (cursor.pos == 0) {
/* we may paste some paragraphs */
/* is it an empty paragraph? */
if ((lastpos == 0
|| (lastpos == 1 && cursor.par->IsSeparator(0)))
&& !(cursor.par->Next()
&& cursor.par->footnoteflag ==
LyXParagraph::NO_FOOTNOTE
&& cursor.par->Next()->footnoteflag ==
LyXParagraph::OPEN_FOOTNOTE)) {
if (cursor.par->previous) {
tmppar = cursor.par->previous->FirstPhysicalPar();
if (cursor.par->GetLayout() == tmppar->GetLayout()
&& cursor.par->footnoteflag == tmppar->footnoteflag
&& cursor.par->GetAlign() == tmppar->GetAlign()) {
tmppar->line_bottom = cursor.par->line_bottom;
tmppar->added_space_bottom = cursor.par->added_space_bottom;
tmppar->pagebreak_bottom = cursor.par->pagebreak_bottom;
}
CursorLeftIntern();
/* the layout things can change the height of a row ! */
tmpheight = cursor.row->height;
SetHeightOfRow(cursor.row);
if (cursor.row->height != tmpheight) {
refresh_y = cursor.y - cursor.row->baseline;
refresh_row = cursor.row;
status = LyXText::NEED_MORE_REFRESH;
}
return;
}
}
if (cursor.par->ParFromPos(cursor.pos)->previous){
SetUndo(Undo::DELETE,
cursor.par->ParFromPos(cursor.pos)->previous->previous,
cursor.par->ParFromPos(cursor.pos)->next);
}
tmppar = cursor.par;
tmprow = cursor.row;
CursorLeftIntern();
/* Pasting is not allowed, if the paragraphs have different layout.
* I think it is a real bug of all other word processors to allow
* it. It confuses the user. Even so with a footnote paragraph and
* a non-footnote paragraph. I will not allow pasting in this case,
* because the user would be confused if the footnote behaves
* different wether it is open or closed.
*
* Correction: Pasting is always allowed with standard-layout */
if (cursor.par != tmppar
&& (cursor.par->GetLayout() == tmppar->GetLayout()
|| !tmppar->GetLayout())
&& cursor.par->footnoteflag == tmppar->footnoteflag
/* table stuff -- begin*/
&& !cursor.par->table /* no pasting of tables */
/* table stuff -- end*/
&& cursor.par->GetAlign() == tmppar->GetAlign()) {
cursor.par->PasteParagraph();
if (!(cursor.pos &&
cursor.par->IsSeparator(cursor.pos - 1)))
cursor.par->InsertChar(cursor.pos, ' ');
else
if (cursor.pos)
cursor.pos--;
status = LyXText::NEED_MORE_REFRESH;
refresh_row = cursor.row;
refresh_y = cursor.y - cursor.row->baseline;
/* remove the lost paragraph */
RemoveParagraph(tmprow);
RemoveRow(tmprow);
/* break the paragraph again */
/* BreakAgain(cursor.row); */
AppendParagraph(cursor.row);
UpdateCounters(cursor.row);
/* the row may have changed, block, hfills etc. */
SetCursor(cursor.par, cursor.pos);
}
} else {
/* this is the code for a normal backspace, not pasting
* any paragraphs */
SetUndo(Undo::DELETE,
cursor.par->ParFromPos(cursor.pos)->previous,
cursor.par->ParFromPos(cursor.pos)->next);
CursorLeftIntern();
/* some insets are undeletable here */
if (cursor.par->GetChar(cursor.pos)==QChar( (int)LYX_META_INSET)) {
if (!cursor.par->GetInset(cursor.pos)->Deletable())
return;
/* force complete redo when erasing display insets */
/* this is a cruel mathod but save..... Matthias */
if (cursor.par->GetInset(cursor.pos)->Display()){
cursor.par->Erase(cursor.pos);
RedoParagraph();
return;
}
}
row = cursor.row;
y = cursor.y - row->baseline;
int z;
/* remember that a space at the end of a row doesnt count
* when calculating the fill */
if (cursor.pos < RowLast(row) ||
!cursor.par->IsLineSeparator(cursor.pos)) {
row->fill += SingleWidth(cursor.par, cursor.pos);
}
/* some special code when deleting a newline. This is similar
* to the behavior when pasting paragraphs */
if (cursor.pos && cursor.par->IsNewline(cursor.pos)) {
cursor.par->Erase(cursor.pos);
/* refresh the positions */
tmprow = row;
while (tmprow->next && tmprow->next->par == row->par) {
tmprow = tmprow->next;
tmprow->pos--;
}
if (cursor.par->IsLineSeparator(cursor.pos - 1))
cursor.pos--;
if (cursor.pos < cursor.par->Last() && !cursor.par->IsSeparator(cursor.pos)) {
cursor.par->InsertChar(cursor.pos, ' ');
/* refresh the positions */
tmprow = row;
while (tmprow->next && tmprow->next->par == row->par) {
tmprow = tmprow->next;
tmprow->pos++;
}
}
} else {
cursor.par->Erase(cursor.pos);
/* refresh the positions */
tmprow = row;
while (tmprow->next && tmprow->next->par == row->par) {
tmprow = tmprow->next;
tmprow->pos--;
}
/* delete superfluous blanks */
if (cursor.pos < cursor.par->Last() - 1 &&
(cursor.par->IsLineSeparator(cursor.pos))) {
if (cursor.pos == BeginningOfMainBody(cursor.par)
|| !cursor.pos
|| cursor.par->IsLineSeparator(cursor.pos - 1)) {
cursor.par->Erase(cursor.pos);
/* refresh the positions */
tmprow = row;
while (tmprow->next &&
tmprow->next->par == row->par) {
tmprow = tmprow->next;
tmprow->pos--;
}
if (cursor.pos) /* move one character left */
cursor.pos--;
}
}
/* delete newlines at the beginning of paragraphs */
while (cursor.par->Last() &&
cursor.par->IsNewline(cursor.pos) &&
cursor.pos == BeginningOfMainBody(cursor.par)
) {
cursor.par->Erase(cursor.pos);
/* refresh the positions */
tmprow = row;
while (tmprow->next &&
tmprow->next->par == row->par) {
tmprow = tmprow->next;
tmprow->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) {
row->pos = z + 1;
tmprow = row->previous;
/* maybe the current row is now empty */
if (row->pos >= row->par->Last()) {
/* remove it */
RemoveRow(row);
need_break_row = NULL;
}
else {
BreakAgainOneRow(row);
if (row->next && row->next->par == row->par)
need_break_row = row->next;
else
need_break_row = NULL;
}
/* set the dimensions of the row above */
y -= tmprow->height;
tmprow->fill = Fill(tmprow, paperwidth);
SetHeightOfRow(tmprow);
refresh_y = y;
refresh_row = tmprow;
status = LyXText::NEED_MORE_REFRESH;
SetCursor(cursor.par, cursor.pos);
current_font = rawtmpfont;
real_current_font = realtmpfont;
/* check, whether the last character's font has changed. */
rawtmpfont = cursor.par->GetFontSettings(cursor.par->Last() - 1);
if (rawparfont != rawtmpfont)
RedoHeightOfParagraph(cursor);
return;
}
}
/* break the cursor row again */
z = NextBreakPoint(row, paperwidth);
if ( z != RowLast(row) ||
(row->next && row->next->par == row->par &&
RowLast(row) == row->par->Last() - 1)){
/* it can happen that a paragraph loses one row
* without a real breakup. This is when a word
* is to long to be broken. Well, I don t care this
* hack ;-) */
if (row->next && row->next->par == row->par &&
RowLast(row) == row->par->Last() - 1)
RemoveRow(row->next);
refresh_y = y;
refresh_row = row;
status = LyXText::NEED_MORE_REFRESH;
BreakAgainOneRow(row);
SetCursor(cursor.par, cursor.pos);
/* cursor MUST be in row now */
if (row->next && row->next->par == row->par)
need_break_row = row->next;
else
need_break_row = NULL;
} else {
/* set the dimensions of the row */
row->fill = Fill(row, paperwidth);
int tmpheight = row->height;
SetHeightOfRow(row);
if (tmpheight == row->height)
status = LyXText::NEED_VERY_LITTLE_REFRESH;
else
status = LyXText::NEED_MORE_REFRESH;
refresh_y = y;
refresh_row = row;
SetCursor(cursor.par, cursor.pos);
}
}
/* restore the current font
* That is what a user expects! */
current_font = rawtmpfont;
real_current_font = realtmpfont;
/* check, wether the last characters font has changed. */
rawtmpfont = cursor.par->GetFontSettings(cursor.par->Last() - 1);
if (rawparfont != rawtmpfont) {
RedoHeightOfParagraph(cursor);
} else {
/* now the special right address boxes */
if (lyxstyle.Style(parameters->textclass,
cursor.par->GetLayout())->margintype == MARGIN_RIGHT_ADDRESS_BOX) {
RedoDrawingOfParagraph(cursor);
}
}
}
klyx'LyXText::GetVisibleRow() (./klyx/src/text.C:3360)
void LyXText::GetVisibleRow(LyXScreen &scr, int offset,
Row *row_ptr, long y)
{
/* returns a printed row */
int pos, pos_end;
float x, tmpx;
int y_top, y_bottom;
float fill_separator, fill_hfill, fill_label_hfill;
LyXParagraph *par, *firstpar;
int left_margin;
LyXFont font;
int maxdesc;
if (row_ptr->height <= 0) {
fprintf(stderr, "LYX_ERROR: row.height: %d \n",
row_ptr->height);
return;
}
left_margin = LabelEnd(row_ptr);
PrepareToPrint(row_ptr, x, fill_separator,
fill_hfill, fill_label_hfill);
int main_body = BeginningOfMainBody(row_ptr->par);
// check for NOT FAST SELECTION
if (!fast_selection && !mono_video && selection) {
/* selection code */
if (sel_start_cursor.row == row_ptr &&
sel_end_cursor.row == row_ptr) {
scr.fillRectangle(gc_clear,
0, offset,
sel_start_cursor.x,
row_ptr->height);
scr.fillRectangle(gc_selection,
sel_start_cursor.x,
offset,
sel_end_cursor.x - sel_start_cursor.x,
row_ptr->height);
scr.fillRectangle(gc_clear,
sel_end_cursor.x, offset,
paperwidth - sel_end_cursor.x,
row_ptr->height);
}
else if (sel_start_cursor.row == row_ptr) {
scr.fillRectangle(gc_clear,
0, offset,
sel_start_cursor.x,
row_ptr->height);
scr.fillRectangle(gc_selection,
sel_start_cursor.x,
offset,
paperwidth - sel_start_cursor.x,
row_ptr->height);
} else if (sel_end_cursor.row == row_ptr) {
scr.fillRectangle(gc_selection,
0, offset,
sel_end_cursor.x,
row_ptr->height);
scr.fillRectangle(gc_clear,
sel_end_cursor.x, offset,
paperwidth - sel_end_cursor.x,
row_ptr->height);
} else if (y > sel_start_cursor.y && y < sel_end_cursor.y) {
scr.fillRectangle(gc_selection,
0, offset,
paperwidth, row_ptr->height);
} else {
/* initialize the pixmap */
scr.fillRectangle(gc_clear,
0, offset, paperwidth, row_ptr->height);
}
} // end of NOT FAST SELECTION code
else {
/* initialize the pixmap */
scr.fillRectangle(gc_clear,
0, offset, paperwidth, row_ptr->height);
}
/***** This was twice ?:-/ Rocher 990604 *****/
if (row_ptr->par->appendix){
scr.drawVerticalLine(gc_math, 1, offset, offset+row_ptr->height);
scr.drawVerticalLine(gc_math, paperwidth-2 , offset, offset+row_ptr->height);
}
/***** END *****/
if (row_ptr->par->pextra_type == PEXTRA_MINIPAGE) {
/* draw a marker at the left margin! */
LyXFont font = GetFont(row_ptr->par, 0);
int asc = font.maxAscent();
int x = (LYX_PAPER_MARGIN - font.width('|')) / 2;
int y1 = (offset + row_ptr->baseline);
int y2 = (offset + row_ptr->baseline) - asc;
scr.drawVerticalLine(gc_minipage, x, y1, y2);
}
if (row_ptr->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
LyXFont font(LyXFont::ALL_SANE);
font.setSize(LyXFont::SIZE_FOOTNOTE);
font.setColor(LyXFont::RED);
int box_x = LYX_PAPER_MARGIN;
bool cfab = lyxrc->close_floats_as_buttons; // Rocher 990601
if (cfab)
box_x += font.textWidth(" algorithm ", 10);
else
box_x += font.textWidth(" wide-tab ", 10);
if (row_ptr->previous &&
row_ptr->previous->par->footnoteflag != LyXParagraph::OPEN_FOOTNOTE){
LString fs;
switch (row_ptr->par->footnotekind) {
case LyXParagraph::MARGIN:
fs = " margin";
break;
case LyXParagraph::FIG:
fs = cfab ? " figure" : " fig"; // Rocher 990601
break;
case LyXParagraph::TAB:
fs = cfab ? " table" : " tab"; // Rocher 990601
break;
case LyXParagraph::WIDE_FIG:
fs = " wide-fig";
break;
case LyXParagraph::WIDE_TAB:
fs = " wide-tab";
break;
case LyXParagraph::ALGORITHM:
fs = cfab ? " algorithm" : " alg"; // Rocher 990601
break;
case LyXParagraph::FOOTNOTE:
fs = cfab ? " footnote" : " foot"; // Rocher 990601
break;
}
// Determine background color.
gc_type back = gc_lighted;
if (mono_video) {
back = gc_clear;
}
scr.fillRectangle(back,LYX_PAPER_MARGIN, offset+1,
box_x - LYX_PAPER_MARGIN,
int(font.maxAscent())+
int(font.maxDescent()));
scr.drawFrame(LYX_PAPER_MARGIN+2, offset+2,
box_x - LYX_PAPER_MARGIN -3,
int(font.maxAscent())+
int(font.maxDescent())-2);
scr.drawLine(gc_foot,
offset,
LYX_PAPER_MARGIN,
paperwidth - 2*LYX_PAPER_MARGIN);
scr.drawString(font, fs,
offset + int(font.maxAscent())+1,
LYX_PAPER_MARGIN);
scr.drawVerticalLine(gc_foot,
LYX_PAPER_MARGIN,
offset,
offset
+ int(font.maxAscent())+
int(font.maxDescent()));
scr.drawLine(gc_foot,
offset
+ int(font.maxAscent())
+ int(font.maxDescent()) + 1,
LYX_PAPER_MARGIN, box_x - LYX_PAPER_MARGIN);
}
/* draw the open floats in a red box */
scr.drawVerticalLine(gc_foot,
box_x,
offset, offset + row_ptr->height);
scr.drawVerticalLine(gc_foot,
paperwidth - LYX_PAPER_MARGIN,
offset,
offset + row_ptr->height);
} else {
if (row_ptr->previous &&
row_ptr->previous->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
LyXFont font(LyXFont::ALL_SANE);
font.setSize(LyXFont::SIZE_FOOTNOTE);
int box_x = LYX_PAPER_MARGIN;
if (lyxrc->close_floats_as_buttons) // Rocher 990601
box_x += font.textWidth(" algorithm ", 10);
else
box_x += font.textWidth(" wide-tab ", 10);
scr.drawLine(gc_foot,
offset,
box_x,
paperwidth - LYX_PAPER_MARGIN - box_x);
}
}
LyXLayout* layout = lyxstyle.Style(parameters->textclass,
row_ptr->par->GetLayout());
firstpar = row_ptr->par->FirstPhysicalPar();
y_top = 0;
y_bottom = row_ptr->height;
/* is it a first row? */
if (row_ptr->pos == 0
&& row_ptr->par == firstpar) {
/* start of appendix? */
if (row_ptr->par->start_of_appendix){
scr.drawLine(gc_math,
offset,
1, paperwidth-3); // Rocher 990604
}
/* think about the margins */
if (!row_ptr->previous)
y_top += LYX_PAPER_MARGIN;
if (row_ptr->par->pagebreak_top){ /* draw a top pagebreak */
scr.drawOnOffLine(offset + y_top + 2 * DefaultHeight(),
0, paperwidth);
y_top += 3 * DefaultHeight();
}
if (row_ptr->par->added_space_top.kind() == VSpace::VFILL) {
/* draw a vfill top */
scr.drawLine(gc_fill,
offset + 2 + y_top,
0, LYX_PAPER_MARGIN);
scr.drawLine(gc_fill,
offset + y_top + 3 * DefaultHeight(),
0, LYX_PAPER_MARGIN);
scr.drawVerticalOnOffLine(LYX_PAPER_MARGIN / 2,
offset + 2 + y_top,
offset + y_top + 3 *
DefaultHeight());
y_top += 3 * DefaultHeight();
}
/* think about user added space */
y_top += int(row_ptr->par->added_space_top.inPixels());
/* think about the parskip */
/* some parskips VERY EASY IMPLEMENTATION */
if (parameters->paragraph_separation == LYX_PARSEP_SKIP) {
if (layout->latextype == LATEX_PARAGRAPH
&& firstpar->GetDepth() == 0
&& firstpar->Previous())
y_top += parameters->getDefSkip().inPixels();
else if (firstpar->Previous()
&& lyxstyle.Style(parameters->textclass,
firstpar->Previous()->GetLayout())->latextype == LATEX_PARAGRAPH
&& firstpar->Previous()->GetDepth() == 0)
// is it right to use defskip here, too? (AS)
y_top += parameters->getDefSkip().inPixels();
}
if (row_ptr->par->line_top) { /* draw a top line */
y_top += GetFont(row_ptr->par, 0).ascent('x');
scr.drawThickLine(offset + y_top,
0, paperwidth);
y_top += GetFont(row_ptr->par, 0).ascent('x');
}
/* should we print a label? */
if (layout->labeltype >= LABEL_STATIC
&& (layout->labeltype != LABEL_STATIC
|| layout->latextype != LATEX_ENVIRONMENT
|| row_ptr->par->IsFirstInSequence())) {
font = GetFont(row_ptr->par, -2);
if (!row_ptr->par->GetLabelString().empty()) {
tmpx = x;
LString tmpstring = row_ptr->par->GetLabelString();
if (layout->labeltype == LABEL_COUNTER_CHAPTER) {
if (parameters->secnumdepth >=0){
/* this is special code for the chapter layout. This is printed in
* an extra row and has a pagebreak at the top. */
maxdesc = int(font.maxDescent() * layout->spacing.getValue() * firstpar->spacing.getValue(parameters->spacing.getValue()))
+ int(layout->parsep) * DefaultHeight();
scr.drawString(font, tmpstring,
offset + row_ptr->baseline
- row_ptr->ascent_of_text - maxdesc,
int(x));
}
} else {
x -= font.stringWidth( layout->labelsep);
x -= font.stringWidth( tmpstring);
/* draw it! */
scr.drawString(font, tmpstring,
offset + row_ptr->baseline, int(x));
}
x = tmpx;
}
/* the labels at the top of an environment. More or less for bibliography */
} else if (layout->labeltype == LABEL_TOP_ENVIRONMENT ||
layout->labeltype == LABEL_BIBLIO ||
layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT) {
if (row_ptr->par->IsFirstInSequence()) {
font = GetFont(row_ptr->par, -2);
if (!row_ptr->par->GetLabelS