products/Sources/formale Sprachen/JAVA/openjdk-20-36_src/test/jdk/sun/nio/cs/mapping image not shown  

Quellcode-Bibliothek

© Kompilation durch diese Firma

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

Datei:   Sprache: Unknown

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

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

[ Verzeichnis aufwärts0.146unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]