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