products/Sources/formale Sprachen/C/Lyx/src image not shown  

Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: axpy.prf   Sprache: C

Original von: Lyx©

/* This file is part of
* ======================================================

*           LyX, The Document Processor
*   
*     Copyright (C) 1995 Matthias Ettrich
*           Copyright (C) 1995-1998 The LyX Team.
*
*======================================================*/


#include <config.h>
#include <stdlib.h>
#include <ctype.h>

#ifdef __GNUG__
#pragma implementation "table.h"
#endif

#include "layout.h"
#include "lyxparagraph.h"
#include "lyxtext.h"
#include "textutils.h"
#include "lyx_gui_misc.h"
#include "lyxdraw.h"
#include "gettext.h"
#include "bufferparams.h"
#include "buffer.h"
#include "lyxscreen.h"

//  $Id: text.C,v 1.9 1998/10/16 16:59:02 larsbj Exp $

#if !defined(lint) && !defined(WITH_WARNINGS)
static char vcid[] = "$Id: text.C,v 1.9 1998/10/16 16:59:02 larsbj Exp $";
#endif /* lint */


static const int LYX_PAPER_MARGIN = 20;

extern int mono_video;
extern int reverse_video;
extern int fast_selection;
extern BufferView *current_view;
extern int UnlockInset(UpdatableInset* inset);

// ale070405
extern int bibitemMaxWidth(const class LyXFont &);


int LyXText::SingleWidth(LyXParagraph *par, int pos)
{
 char c = par->GetChar(pos);
 return SingleWidth(par, pos, c);
}


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 == LYX_META_FOOTNOTE ||
     c == LYX_META_MARGIN ||
     c == LYX_META_FIG ||
     c == LYX_META_TAB ||
     c == LYX_META_WIDE_FIG ||
     c == LYX_META_WIDE_TAB ||
     c == LYX_META_ALGORITHM) 
 {
  LString fs;
  switch (c) {
  case LYX_META_MARGIN:
   fs = "margin";
   break;
  case LYX_META_FIG:
   fs = "fig";
   break;
  case LYX_META_TAB:
   fs = "tab";
   break;
  case LYX_META_ALGORITHM:
   fs = "alg";
   break;
  case LYX_META_WIDE_FIG:
   fs = "wide-fig";
   break;
  case LYX_META_WIDE_TAB:
   fs = "wide-tab";
   break;
  case LYX_META_FOOTNOTE:
   fs = "foot";
   break;
  }
  font.decSize();
  font.decSize();
  return font.stringWidth(fs);
 } 
   
 else if (c == 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 */

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;
}


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

  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(::getGC(gc_new_line),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(::getGC(gc_new_line),p, 3);
  return;
 }

 LyXFont font = GetFont(row->par, pos);
 LyXFont font2 = font;

 if (c == LYX_META_FOOTNOTE ||
     c == LYX_META_MARGIN ||
     c == LYX_META_FIG ||
     c == LYX_META_TAB ||
     c == LYX_META_WIDE_FIG ||
     c == LYX_META_WIDE_TAB ||
     c == LYX_META_ALGORITHM) {
  LString fs;
  switch (c) {
  case LYX_META_MARGIN:
   fs = "margin";
   /* draw a sign at the left margin! */ 
   scr.drawText(font, "!", 1, offset + row->baseline,
         (LYX_PAPER_MARGIN - font.width('!'))/2);
   break;
  case LYX_META_FIG:
   fs = "fig";
   break;
  case LYX_META_TAB:
   fs = "tab";
   break;
  case LYX_META_ALGORITHM:
   fs = "alg";
   break;
  case LYX_META_WIDE_FIG:
   fs = "wide-fig";
   break;
  case LYX_META_WIDE_TAB:
   fs = "wide-tab";
   break;
  case LYX_META_FOOTNOTE:
   fs = "foot";
   break;
  }
  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 == 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. */

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;
}
    
   
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;
   
}


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*/ 
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;
}


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;
}


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());
}


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 */
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) == 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) == 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 == 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 */
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 */ 
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 */

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!  */

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! */ 
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 */

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);
}


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() *
     parameters->spacing.getValue());
   maxdesc = int(font.maxDescent() *
      layout->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) == 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;
  }
      }
   }

   // 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) {
      
      /* 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() *
      parameters->spacing.getValue())
        + int(labelfont.maxAscent() *
          layout->spacing.getValue() *
          parameters->spacing.getValue());
      }
      
      /* special 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()
   && !row_ptr->par->GetLabelString().empty()) {
  labeladdon = int(
   (labelfont.maxAscent() *
    layout->spacing.getValue() *
    parameters->spacing.getValue())
   +(labelfont.maxDescent() *
     layout->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 */

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);
}


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 */ 
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);
}


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;
}


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*/

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();
}


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:
          if (current_view->currentBuffer()->the_locking_inset)
              UnlockInset(current_view->currentBuffer()->the_locking_inset);
          RemoveTableRow(&cursor);
          RedoParagraph();
          return;
 
      case LyXTable::DELETE_COLUMN: {
          int pos = 0;
          int cell_org = actCell;
          int cell = 0;
          if (current_view->currentBuffer()->the_locking_inset)
              UnlockInset(current_view->currentBuffer()->the_locking_inset);
          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(_("Impossible Operation!"), 
                                 _("Multicolumns can only be horizontally."), 
                                 _("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_LONGTABLE:
          cursor.par->table->SetLongTable(true);
          return;
      case LyXTable::UNSET_LONGTABLE:
          cursor.par->table->SetLongTable(false);
          return;
      case LyXTable::SET_ROTATE_TABLE:
          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:
          what = !cursor.par->table->LTNewPage(actCell);
          cursor.par->table->SetLTNewPage(actCell,what);
          return;
    }
}
 

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 != 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);
}


void LyXText::CheckParagraphInTable(LyXParagraph* par, int pos)
{
 Row *row;
 long y;
 
 if (par->GetChar(pos) == 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);
}


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)==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 
--> --------------------

--> maximum size reached

--> --------------------

¤ Dauer der Verarbeitung: 0.49 Sekunden  (vorverarbeitet)  ¤





Download des
Quellennavigators
Download des
sprechenden Kalenders

in der Quellcodebibliothek suchen




Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.


Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.


Bot Zugriff