]> git.lyx.org Git - lyx.git/blobdiff - src/text.C
Added html export for LinuxDoc and DocBook. LinuxDoc import now available in file...
[lyx.git] / src / text.C
index 2bc2b48923f0533f9b78d0a9ac8035536f2e94bb..c81fae1f9b3af9e3315795c7f73349b769992667 100644 (file)
@@ -4,7 +4,7 @@
  *           LyX, The Document Processor
  *      
  *           Copyright 1995 Matthias Ettrich
- *           Copyright 1995-1999 The LyX Team.
+ *           Copyright 1995-2000 The LyX Team.
  *
  * ====================================================== */
 
 #include "LyXView.h"
 #include "lyxrow.h"
 #include "Painter.h"
+#include "tracer.h"
 
 using std::max;
 using std::min;
 
 static const int LYX_PAPER_MARGIN = 20;
 
-extern LyXRC * lyxrc;
 
 // ale070405
 extern int bibitemMaxWidth(Painter &, LyXFont const &);
 
 #define FIX_DOUBLE_SPACE 1
 
+static int iso885968x[] = {
+       0xbc,   // 0xa8 = fathatan
+       0xbd,   // 0xa9 = dammatan
+       0xbe,   // 0xaa = kasratan
+       0xdb,   // 0xab = fatha
+       0xdc,   // 0xac = damma
+       0xdd,   // 0xad = kasra
+       0xde,   // 0xae = shadda
+       0xdf,   // 0xaf = sukun
+
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xb0-0xbf
+
+       0,      // 0xc0 
+       0xc1,   // 0xc1 = hamza
+       0xc2,   // 0xc2 = ligature madda
+       0xc3,   // 0xc3 = ligature hamza on alef
+       0xc4,   // 0xc4 = ligature hamza on waw
+       0xc5,   // 0xc5 = ligature hamza under alef
+       0xc0,   // 0xc6 = ligature hamza on ya 
+       0xc7,   // 0xc7 = alef
+       0xeb,   // 0xc8 = baa 
+       0xc9,   // 0xc9 = taa marbuta
+       0xec,   // 0xca = taa
+       0xed,   // 0xcb = thaa
+       0xee,   // 0xcc = jeem
+       0xef,   // 0xcd = haa
+       0xf0,   // 0xce = khaa
+       0xcf,   // 0xcf = dal
+
+       0xd0,   // 0xd0 = thal
+       0xd1,   // 0xd1 = ra
+       0xd2,   // 0xd2 = zain
+       0xf1,   // 0xd3 = seen
+       0xf2,   // 0xd4 = sheen
+       0xf3,   // 0xd5 = sad
+       0xf4,   // 0xd6 = dad
+       0xd7,   // 0xd7 = tah
+       0xd8,   // 0xd8 = zah
+       0xf5,   // 0xd9 = ain
+       0xf6,   // 0xda = ghain
+       0,0,0,0,0, // 0xdb- 0xdf
+
+       0,      // 0xe0
+       0xf7,   // 0xe1 = fa
+       0xf8,   // 0xe2 = qaf
+       0xf9,   // 0xe3 = kaf
+       0xfa,   // 0xe4 = lam
+       0xfb,   // 0xe5 = meem
+       0xfc,   // 0xe6 = noon
+       0xfd,   // 0xe7 = ha
+       0xe8,   // 0xe8 = waw
+       0xe9,   // 0xe9 = alef maksura
+       0xfe    // 0xea = ya
+};
+
+bool is_arabic(unsigned char c)
+{
+       return 0xa8 <= c && c <= 0xea && iso885968x[c-0xa8];
+}
+
+unsigned char LyXText::TransformChar(unsigned char c, Letter_Form form) const
+{
+       if (is_arabic(c) && 
+           (form == FORM_INITIAL || form == FORM_MEDIAL) )
+               return iso885968x[c-0xa8];
+       else
+               return c;
+}
+
+unsigned char LyXText::TransformChar(unsigned char c, LyXParagraph * par,
+                       LyXParagraph::size_type pos) const
+{
+       if (!is_arabic(c))
+               return c;
+
+       bool not_first = (pos > 0 && is_arabic(par->GetChar(pos-1)));
+       if (pos < par->Last()-1 && is_arabic(par->GetChar(pos+1)))
+               if (not_first)
+                       return TransformChar(c,FORM_MEDIAL);
+               else
+                       return TransformChar(c,FORM_INITIAL);
+       else
+               if (not_first)
+                       return TransformChar(c,FORM_FINAL);
+               else
+                       return TransformChar(c,FORM_ISOLATED);
+}
+
+// This is the comments that some of the warnings below refers to.
+// There are some issues in this file and I don't think they are
+// really related to the FIX_DOUBLE_SPACE patch. I'd rather think that
+// this is a problem that has been here almost from day one and that a
+// larger userbase with differenct access patters triggers the bad
+// behaviour. (segfaults.) What I think happen is: In several places
+// we store the paragraph in the current cursor and then moves the
+// cursor. This movement of the cursor will delete paragraph at the
+// old position if it is now empty. This will make the temporary
+// pointer to the old cursor paragraph invalid and dangerous to use.
+// And is some cases this will trigger a segfault. I have marked some
+// of the cases where this happens with a warning, but I am sure there
+// are others in this file and in text2.C. There is also a note in
+// Delete() that you should read. In Delete I store the paragraph->id
+// instead of a pointer to the paragraph. I am pretty sure this faulty
+// use of temporary pointers to paragraphs that might have gotten
+// invalidated (through a cursor movement) before they are used, are
+// the cause of the strange crashes we get reported often.
+//
+// It is very tiresom to change this code, especially when it is as
+// hard to read as it is. Help to fix all the cases where this is done
+// would be greately appreciated.
+//
+// Lgb
+
 int LyXText::SingleWidth(LyXParagraph * par,
                         LyXParagraph::size_type pos) const
 {
@@ -59,6 +172,8 @@ int LyXText::SingleWidth(LyXParagraph * par,
 
        // The most common case is handled first (Asger)
        if (IsPrintable(c)) {
+               if (lyxrc.rtl_support && lyxrc.font_norm == "iso8859-6.8x")
+                       c = TransformChar(c, par, pos);
                return font.width(c);
 
        } else if (IsHfillChar(c)) {
@@ -132,7 +247,7 @@ LyXParagraph::size_type LyXText::RowLast(Row const * row) const
 void LyXText::ComputeBidiTables(Row * row) const
 {
 
-       if (!lyxrc->rtl_support) {
+       if (!lyxrc.rtl_support) {
                bidi_start = -1;
                return;
        }
@@ -206,10 +321,9 @@ void LyXText::ComputeBidiTablesFromTo(Row * row,
                } else {
                        if (level == 0 ||
                            (level == 1 && direction == LYX_DIR_RIGHT_TO_LEFT
-                            && row->par->getFont(lpos).direction() ==
-                            LyXFont::RTL_DIR
-                            && row->par->getFont(lpos).latex() ==
-                            LyXFont::ON ) ) {
+                            && row->par->getFont(lpos).isRightToLeft()
+                            && row->par->getFont(lpos).latex() == LyXFont::ON
+                            ) ) {
                                // The last check is needed when the
                                // char is a space
                                stack[level++] = lpos;
@@ -391,6 +505,9 @@ void LyXText::draw(Row const * row,
        // So IMHO we should go with the easier and clearer implementation.
        // And even if 1024 is a large number here it might overflow, string
        // will only overflow if the machine is out of memory...
+       bool do_transform = (lyxrc.rtl_support && lyxrc.font_norm == "iso8859-6.8x");
+       if (do_transform)
+               c = TransformChar(c, row->par, pos);
        static string textstring;
        textstring = c;
        ++vpos;
@@ -401,6 +518,8 @@ void LyXText::draw(Row const * row,
               (pos = vis2log(vpos)) >= 0
               && static_cast<unsigned char>(c = row->par->GetChar(pos)) > ' '
               && font2 == GetFont(row->par, pos)) {
+               if (do_transform)
+                       c = TransformChar(c, row->par, pos);
                textstring += c;
                ++vpos;
        }
@@ -601,7 +720,7 @@ int LyXText::LeftMargin(Row const * row) const
                }
        }
        
-       int align;
+       int align; // wrong type
        if (row->par->FirstPhysicalPar()->align == LYX_ALIGN_LAYOUT)
                align = layout.align;
        else
@@ -791,7 +910,6 @@ LyXText::NextBreakPoint(Row const * row, int width) const
        // position of the last possible breakpoint 
        // -1 isn't a suitable value, but a flag
        LyXParagraph::size_type last_separator = -1;
-       int left_margin = LabelEnd(row);
        width -= RightMargin(row);
        
        LyXParagraph::size_type main_body = BeginningOfMainBody(par);
@@ -857,6 +975,7 @@ LyXText::NextBreakPoint(Row const * row, int width) const
                                x += GetFont(par, -2).stringWidth(layout.labelsep);
                                if (par->IsLineSeparator(i - 1))
                                        x-= SingleWidth(par, i - 1);
+                               int left_margin = LabelEnd(row);
                                if (x < left_margin)
                                        x = left_margin;
                        }
@@ -910,9 +1029,7 @@ int LyXText::Fill(Row const * row, int paper_width) const
                           * this point. */ 
        }
        /* table stuff -- end*/ 
-       
-       int left_margin = LabelEnd(row);
-       
+               
        // if the row ends with newline, this newline will not be relevant
        //if (last >= 0 && row->par->IsNewline(last))
        //      --last;
@@ -944,6 +1061,7 @@ int LyXText::Fill(Row const * row, int paper_width) const
                                stringWidth(layout.labelsep);
                        if (row->par->IsLineSeparator(i - 1))
                                w -= SingleWidth(row->par, i - 1);
+                       int left_margin = LabelEnd(row);
                        if (w < left_margin)
                                w = left_margin;
                }
@@ -954,6 +1072,7 @@ int LyXText::Fill(Row const * row, int paper_width) const
                w += GetFont(row->par, -2).stringWidth(layout.labelsep);
                if (last >= 0 && row->par->IsLineSeparator(last))
                        w -= SingleWidth(row->par, last);
+               int left_margin = LabelEnd(row);
                if (w < left_margin)
                        w = left_margin;
        }
@@ -1006,11 +1125,6 @@ int LyXText::LabelFill(Row const * row) const
 int LyXText::NumberOfSeparators(Row const * row) const
 {
        int last = RowLast(row);
-       //int p = row->pos;
-       //int main_body = BeginningOfMainBody(row->par);
-       //if (p < main_body)
-       //      p = main_body;
-       // I think this is equivalent to the above. (Lgb)
        int p = max(row->pos, BeginningOfMainBody(row->par));
        int n = 0;
        for (; p < last; ++p) {
@@ -1035,10 +1149,6 @@ int LyXText::NumberOfHfills(Row const * row) const
                        ++first;
        }
 
-       //int main_body = BeginningOfMainBody(row->par);
-       //if (first < main_body)
-       //      first = main_body;
-       // I think this is equivalent to the above. (Lgb)
        first = max(first, BeginningOfMainBody(row->par));
        int n = 0;
        for (int p = first; p <= last; ++p) { // last, because the end is ignored!
@@ -1060,11 +1170,7 @@ int LyXText::NumberOfLabelHfills(Row const * row) const
                while(first < last && row->par->IsHfill(first))
                        ++first;
        }
-       //LyXParagraph::size_type main_body = 
-       //BeginningOfMainBody(row->par);
-       //if (last > main_body)
-       //last = main_body;
-       // I think this is eqvialent to the above. (Lgb)
+
        last = min(last, BeginningOfMainBody(row->par));
        int n = 0;
        for (LyXParagraph::size_type p = first;
@@ -1541,7 +1647,7 @@ void LyXText::BreakParagraph(char keep_layout)
    if (cursor.par->table) {
        int cell = NumberOfCell(cursor.par, cursor.pos);
        if (cursor.par->table->ShouldBeVeryLastCell(cell))
-           SetCursor(cursor.par, cursor.par->text.size());
+           SetCursor(cursor.par, cursor.par->size());
    }
    /* table stuff -- end */
    
@@ -1644,7 +1750,7 @@ void LyXText::OpenFootnote()
        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)->text.size());
+            cursor.pos + cursor.par->ParFromPos(cursor.pos)->size());
    
    /* the cursor must be exactly before the footnote */ 
    par = cursor.par->ParFromPos(cursor.pos);
@@ -1662,6 +1768,7 @@ void LyXText::OpenFootnote()
    /* set the dimensions of the cursor row */
    row->fill = Fill(row, paperwidth);
    SetHeightOfRow(row);
+#warning See comment on top of text.C
    tmppar = tmppar->Next();
    
    while (tmppar != endpar) {
@@ -1777,8 +1884,12 @@ void LyXText::TableFeatures(int feature) const
                
           /* insert the new cells */ 
           int number = cursor.par->table->NumberOfCellsInRow(cell_org);
-          for (int i = 0; i < number; ++i)
+         Language const * lang = cursor.par->getParLanguage();
+         LyXFont font(LyXFont::ALL_INHERIT,lang);
+          for (int i = 0; i < number; ++i) {
               cursor.par->InsertChar(pos, LyXParagraph::META_NEWLINE);
+             cursor.par->SetFont(pos, font);
+         }
                
           /* append the row into the table */
           cursor.par->table->AppendRow(cell_org);
@@ -1812,9 +1923,13 @@ void LyXText::TableFeatures(int feature) const
                
           /* insert the new cells */ 
           int number = cursor.par->table->NumberOfCellsInRow(cell_org);
-          for (int i = 0; i < number; ++i)
+         Language const * lang = cursor.par->getParLanguage();
+         LyXFont font(LyXFont::ALL_INHERIT,lang);
+          for (int i = 0; i < number; ++i) {
               cursor.par->InsertChar(pos, LyXParagraph::META_NEWLINE);
-               
+             cursor.par->SetFont(pos, font);
+         }
+
           /* append the row into the table */
           cursor.par->table->AppendContRow(cell_org);
           RedoParagraph();
@@ -1824,10 +1939,13 @@ void LyXText::TableFeatures(int feature) const
              LyXParagraph::size_type pos = 0;
           int cell_org = actCell;
           int cell = 0;
+         Language const * lang = cursor.par->getParLanguage();
+         LyXFont font(LyXFont::ALL_INHERIT,lang);
           do{
               if (pos && (cursor.par->IsNewline(pos-1))){
                   if (cursor.par->table->AppendCellAfterCell(cell_org, cell)) {
                       cursor.par->InsertChar(pos, LyXParagraph::META_NEWLINE);
+                     cursor.par->SetFont(pos, font);
                       if (pos <= cursor.pos)
                           cursor.pos++;
                       ++pos;
@@ -1838,8 +1956,11 @@ void LyXText::TableFeatures(int feature) const
           } 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(), LyXParagraph::META_NEWLINE);
+          if (cursor.par->table->AppendCellAfterCell(cell_org, cell)) {
+                 LyXParagraph::size_type last = cursor.par->Last();
+                 cursor.par->InsertChar(last, LyXParagraph::META_NEWLINE);
+                 cursor.par->SetFont(last, font);
+         }
                
           /* append the column into the table */ 
           cursor.par->table->AppendColumn(cell_org);
@@ -1979,7 +2100,7 @@ void LyXText::TableFeatures(int feature) const
           // dummy-paragraph !! 
           // not necessar anymore with UNDO :)
           for (LyXParagraph::size_type i = 
-                      cursor.par->text.size() - 1; i >= 0; --i)
+                      cursor.par->size() - 1; i >= 0; --i)
              cursor.par->Erase(i);
           RedoParagraph();
           return;
@@ -2258,6 +2379,7 @@ void LyXText::CheckParagraphInTable(LyXParagraph * par,
                /* redraw only the row */
                LyXCursor tmpcursor = cursor;
                SetCursorIntern(par, pos);
+#warning See comment on top of text.C
                refresh_y = y;
                refresh_x = cursor.x;
                refresh_row = row;
@@ -2390,19 +2512,12 @@ void LyXText::InsertChar(char c)
                cursor.par->ParFromPos(cursor.pos)->next);
 
        /* When the free-spacing option is set for the current layout,
-        * all spaces are converted to protected spaces. */
-#warning think about this
-#if 0
-       bool freeSpacingBo = 
+        * disable the double-space checking */
+
+       bool freeSpacing = 
                textclasslist.Style(parameters->textclass,
                               cursor.row->par->GetLayout()).free_spacing;
 
-       if (freeSpacingBo && IsLineSeparatorChar(c) 
-           && (!cursor.pos || cursor.par->IsLineSeparator(cursor.pos - 1))) {
-               c = LyXParagraph::META_PROTECTED_SEPARATOR;
-       }
-#endif
-       
        /* table stuff -- begin*/
        if (cursor.par->table) {
                InsertCharInTable(c);
@@ -2437,7 +2552,7 @@ void LyXText::InsertChar(char c)
 
        bool jumped_over_space = false;
    
-       if (IsLineSeparatorChar(c)) {
+       if (!freeSpacing && IsLineSeparatorChar(c)) {
 #ifndef FIX_DOUBLE_SPACE
                if (cursor.pos < lastpos
                    && cursor.par->IsLineSeparator(cursor.pos)) {
@@ -2764,6 +2879,7 @@ void LyXText::CursorRightOneWord() const
 {
        // treat floats, HFills and Insets as words
        LyXCursor tmpcursor = cursor;
+#warning See comment on top of text.C
 
        if (tmpcursor.pos == tmpcursor.par->Last()
            && tmpcursor.par->Next())
@@ -2958,18 +3074,29 @@ char * LyXText::SelectNextWord(float & value)
        /* Start the selection from here */
        sel_cursor = cursor;
 
-       string latex;
-   
+#ifdef HAVE_SSTREAM
+       ostringstream latex;
+#else
+       ostrstream latex;
+#endif
        /* and find the end of the word 
           (optional hyphens are part of a word) */
        while (cursor.pos < cursor.par->Last()
               && (cursor.par->IsLetter(cursor.pos)) 
-                  || (cursor.par->GetChar(cursor.pos) == LyXParagraph::META_INSET &&
-                      cursor.par->GetInset(cursor.pos) != 0 &&
-                      cursor.par->GetInset(cursor.pos)->Latex(latex, 0) == 0 &&
-                      latex == "\\-"))
+                  || (cursor.par->GetChar(cursor.pos) == LyXParagraph::META_INSET
+                      && cursor.par->GetInset(cursor.pos) != 0
+                      && cursor.par->GetInset(cursor.pos)->Latex(latex, 0, false) == 0
+#ifdef HAVE_SSTREAM
+                      && latex.str() == "\\-"
+#else
+               && string(latex.str(), 3) == "\\-" // this is not nice at all
+#endif
+                          ))
                cursor.pos++;
 
+#ifndef HAVE_SSTREAM
+       delete [] latex.str();
+#endif
        // Finally, we copy the word to a string and return it
        char * str = 0;
 
@@ -2995,17 +3122,29 @@ void LyXText::SelectSelectedWord()
        /* set the sel cursor */
        sel_cursor = cursor;
 
-       string latex;
+#ifdef HAVE_SSTREAM
+       ostringstream latex;
+#else
+       ostrstream latex;
+#endif
        
        /* now find the end of the word */
        while (cursor.pos < cursor.par->Last()
               && (cursor.par->IsLetter(cursor.pos)
-                  || (cursor.par->GetChar(cursor.pos) == LyXParagraph::META_INSET &&
-                      cursor.par->GetInset(cursor.pos) != 0 &&
-                      cursor.par->GetInset(cursor.pos)->Latex(latex, 0) == 0 &&
-                      latex == "\\-")))
+                  || (cursor.par->GetChar(cursor.pos) == LyXParagraph::META_INSET
+                      && cursor.par->GetInset(cursor.pos) != 0
+                      && cursor.par->GetInset(cursor.pos)->Latex(latex, 0, false) == 0
+#ifdef HAVE_SSTREAM
+                      && latex.str() == "\\-"
+#else
+                      && string(latex.str(), 3) == "\\-"
+#endif
+                          )))
                cursor.pos++;
        
+#ifndef HAVE_SSTREAM
+       delete [] latex.str();
+#endif
        SetCursor(cursor.par, cursor.pos);
        
        /* finally set the selection */ 
@@ -3020,6 +3159,7 @@ void LyXText::DeleteWordForward()
         
        if (!cursor.par->Last())
                CursorRight();
+#warning See comment on top of text.C
        else {
                /* -------> Skip initial non-word stuff. */
                while ( cursor.pos < cursor.par->Last() 
@@ -3046,6 +3186,7 @@ void LyXText::DeleteWordBackward()
        LyXCursor tmpcursor = cursor;
        if (!cursor.par->Last())
          CursorLeft();
+#warning See comment on top of text.C
        else{
          selection = true; // to avoid deletion 
          CursorLeftOneWord();
@@ -3063,6 +3204,7 @@ void LyXText::DeleteLineForward()
        LyXCursor tmpcursor = cursor;
        if (!cursor.par->Last())
                CursorRight();
+#warning See comment on top of text.C
        else {
                CursorEnd();
                sel_cursor = cursor;
@@ -3097,7 +3239,8 @@ void LyXText::ChangeWordCase(LyXText::TextCase action)
        LyXParagraph::size_type tmppos = 
                cursor.par->PositionInParFromPos(cursor.pos);
        while (tmppos < tmppar->size()) {
-               unsigned char c = tmppar->text[tmppos];
+               //unsigned char c = tmppar->text[tmppos];
+               unsigned char c = tmppar->GetChar(tmppos);
                if (IsKommaChar(c) || IsLineSeparatorChar(c))
                        break;
                if (c != LyXParagraph::META_INSET) {
@@ -3115,7 +3258,8 @@ void LyXText::ChangeWordCase(LyXText::TextCase action)
                        }
                }
                
-               tmppar->text[tmppos] = c;
+               //tmppar->text[tmppos] = c;
+               tmppar->SetChar(tmppos, c);
                ++tmppos;
        }
        CheckParagraph(tmppar, tmppos);
@@ -3135,6 +3279,7 @@ void LyXText::Delete()
        // just move to the right
        CursorRightIntern();
 
+#warning Look at the comment here.
        // This check is not very good...
        // The CursorRightIntern calls DeleteEmptyParagrapgMechanism
        // and that can very well delete the par or par->previous in
@@ -3163,13 +3308,10 @@ void LyXText::Delete()
 }
 
 
-void  LyXText::Backspace()
+void LyXText::Backspace()
 {
-       LyXParagraph * tmppar;
-       Row * tmprow, * row;
-       long y;
-       int tmpheight;
-
+       DebugTracer trc1("LyXText::Backspace");
+       
        /* table stuff -- begin */
        if (cursor.par->table) {
                BackspaceInTable();
@@ -3185,6 +3327,11 @@ void  LyXText::Backspace()
        LyXFont rawparfont = cursor.par->GetFontSettings(lastpos - 1);
 
        if (cursor.pos == 0) {
+               DebugTracer trc("LyXText::Backspace cursor.pos == 0");
+               
+               // The cursor is at the beginning of a paragraph, so the the backspace
+               // will collapse two paragraphs into one.
+               
                // we may paste some paragraphs
       
                // is it an empty paragraph?
@@ -3192,17 +3339,19 @@ void  LyXText::Backspace()
                if ((lastpos == 0
                     || (lastpos == 1 && cursor.par->IsSeparator(0)))
                    && !(cursor.par->Next() 
-                        && cursor.par->footnoteflag == 
-                        LyXParagraph::NO_FOOTNOTE
-                        && cursor.par->Next()->footnoteflag == 
-                        LyXParagraph::OPEN_FOOTNOTE)) {
+                        && cursor.par->footnoteflag == LyXParagraph::NO_FOOTNOTE
+                        && cursor.par->Next()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)) {
+                       // This is an empty paragraph and we delete it just by moving the curosr one step
+                       // left and let the DeleteEmptyParagraphMechanism handle the actual deleteion
+                       // of the paragraph.
                        
                        if (cursor.par->previous) {
-                               tmppar = cursor.par->previous->FirstPhysicalPar();
+                               LyXParagraph * tmppar = cursor.par->previous->FirstPhysicalPar();
                                if (cursor.par->GetLayout() == tmppar->GetLayout()
                                    && cursor.par->footnoteflag == tmppar->footnoteflag
                                    && cursor.par->GetAlign() == tmppar->GetAlign()) {
-                                       
+                                       // Inherit botom DTD from the paragraph below.
+                                       // (the one we are deleting)
                                        tmppar->line_bottom = cursor.par->line_bottom;
                                        tmppar->added_space_bottom = cursor.par->added_space_bottom;
                                        tmppar->pagebreak_bottom = cursor.par->pagebreak_bottom;
@@ -3211,7 +3360,7 @@ void  LyXText::Backspace()
                                CursorLeftIntern();
                     
                                // the layout things can change the height of a row !
-                               tmpheight = cursor.row->height;
+                               int tmpheight = cursor.row->height;
                                SetHeightOfRow(cursor.row);
                                if (cursor.row->height != tmpheight) {
                                        refresh_y = cursor.y - cursor.row->baseline;
@@ -3221,14 +3370,17 @@ void  LyXText::Backspace()
                                return;
                        }
                }
+               
                if (cursor.par->ParFromPos(cursor.pos)->previous){
                        SetUndo(Undo::DELETE,
                                cursor.par->ParFromPos(cursor.pos)->previous->previous,
                                cursor.par->ParFromPos(cursor.pos)->next);
                }
-               tmppar = cursor.par;
-               tmprow = cursor.row;
+               
+               LyXParagraph * tmppar = cursor.par;
+               Row * tmprow = cursor.row;
                CursorLeftIntern();
+#warning See comment on top of text.C
                /* Pasting is not allowed, if the paragraphs have different
                   layout. I think it is a real bug of all other
                   word processors to allow it. It confuses the user.
@@ -3241,18 +3393,22 @@ void  LyXText::Backspace()
                */
                if (cursor.par != tmppar
                    && (cursor.par->GetLayout() == tmppar->GetLayout()
-                       || !tmppar->GetLayout())
+                       || tmppar->GetLayout() == 0 /*standard*/)
                    && cursor.par->footnoteflag == tmppar->footnoteflag
                    /* table stuff -- begin*/
                    && !cursor.par->table /* no pasting of tables */ 
                    /* table stuff -- end*/
                    && cursor.par->GetAlign() == tmppar->GetAlign()) {
-                       
+
+                       RemoveParagraph(tmprow);
+                       RemoveRow(tmprow);
                        cursor.par->PasteParagraph();
                        
-                       if (!(cursor.pos &&
-                             cursor.par->IsSeparator(cursor.pos - 1)))
-                               cursor.par->InsertChar(cursor.pos, ' ');
+                       if (!cursor.pos || !cursor.par->IsSeparator(cursor.pos - 1))
+                               ; //cursor.par->InsertChar(cursor.pos, ' ');
+                       // strangely enough it seems that commenting out the line above removes
+                       // most or all of the segfaults. I will however also try to move the
+                       // two Remove... lines in front of the PasteParagraph too.
                        else
                                if (cursor.pos)
                                        cursor.pos--;
@@ -3262,16 +3418,22 @@ void  LyXText::Backspace()
                        refresh_y = cursor.y - cursor.row->baseline;
                        
                        // remove the lost paragraph
-                       RemoveParagraph(tmprow);
-                       RemoveRow(tmprow);  
+                       // This one is not safe, since the paragraph that the tmprow and the
+                       // following rows belong to has been deleted by the PasteParagraph
+                       // above. The question is... could this be moved in front of the
+                       // PasteParagraph?
+                       //RemoveParagraph(tmprow);
+                       //RemoveRow(tmprow);  
                        
-                       AppendParagraph(cursor.row);
+                       AppendParagraph(cursor.row); // This rebuilds the rows.
                        UpdateCounters(cursor.row);
                        
                        // the row may have changed, block, hfills etc.
                        SetCursor(cursor.par, cursor.pos);
                }
        } else {
+               DebugTracer trc("LyXText::Backspace normal backspace");
+               
                /* this is the code for a normal backspace, not pasting
                 * any paragraphs */ 
                SetUndo(Undo::DELETE, 
@@ -3292,8 +3454,8 @@ void  LyXText::Backspace()
                        }
                }
                
-               row = cursor.row;
-               y = cursor.y - row->baseline;
+               Row * row = cursor.row;
+               long y = cursor.y - row->baseline;
                LyXParagraph::size_type z;
                /* remember that a space at the end of a row doesnt count
                 * when calculating the fill */ 
@@ -3307,7 +3469,7 @@ void  LyXText::Backspace()
                if (cursor.pos && cursor.par->IsNewline(cursor.pos)) {
                        cursor.par->Erase(cursor.pos);
                        // refresh the positions
-                       tmprow = row;
+                       Row * tmprow = row;
                        while (tmprow->next && tmprow->next->par == row->par) {
                                tmprow = tmprow->next;
                                tmprow->pos--;
@@ -3328,7 +3490,7 @@ void  LyXText::Backspace()
                        cursor.par->Erase(cursor.pos);
                        
                        // refresh the positions
-                       tmprow = row;
+                       Row * tmprow = row;
                        while (tmprow->next && tmprow->next->par == row->par) {
                                tmprow = tmprow->next;
                                tmprow->pos--;
@@ -3377,7 +3539,7 @@ void  LyXText::Backspace()
                        if ( z >= row->pos) {
                                row->pos = z + 1;
                                
-                               tmprow = row->previous;
+                               Row * tmprow = row->previous;
                                
                                // maybe the current row is now empty
                                if (row->pos >= row->par->Last()) {
@@ -3456,7 +3618,8 @@ void  LyXText::Backspace()
                        SetCursor(cursor.par, cursor.pos, false);
                }
        }
-   
+       DebugTracer trc2("LyXText::Backspace wrap up");
+       
        // restore the current font
        // That is what a user expects!
        current_font = rawtmpfont; 
@@ -3676,10 +3839,33 @@ void LyXText::GetVisibleRow(int offset,
                        y_top += LYX_PAPER_MARGIN;
                
                if (row_ptr->par->pagebreak_top){ /* draw a top pagebreak  */
+#if 0
                        pain.line(0, offset + y_top + 2 * DefaultHeight(),
                                  paperwidth,
                                  offset + y_top + 2 * DefaultHeight(),
                                  LColor::pagebreak, Painter::line_onoffdash);
+#else
+                       LyXFont pb_font;
+                       pb_font.setColor(LColor::pagebreak).decSize();
+                       int w = 0, a = 0, d = 0;
+                       pain.line(0, offset + y_top + 2*DefaultHeight(),
+                                 paperwidth, 
+                                 offset + y_top + 2*DefaultHeight(),
+                                 LColor::pagebreak, 
+                                 Painter::line_onoffdash)
+                               .rectText(0,
+                                         0,
+                                         _("Page Break (top)"),
+                                         pb_font,
+                                         LColor::background,
+                                         LColor::background, false, w, a, d);
+                       pain.rectText((paperwidth - w)/2,
+                                     offset +y_top + 2*DefaultHeight() +d,
+                                     _("Page Break (top)"),
+                                     pb_font,
+                                     LColor::background,
+                                     LColor::background);
+#endif
                        y_top += 3 * DefaultHeight();
                }
                
@@ -3829,10 +4015,34 @@ void LyXText::GetVisibleRow(int offset,
                
                /* draw a bottom pagebreak */ 
                if (firstpar->pagebreak_bottom) {
+#if 0
                        pain.line(0, offset + y_bottom - 2 * DefaultHeight(),
                                  paperwidth,
                                  offset + y_bottom - 2 * DefaultHeight(),
                                  LColor::pagebreak, Painter::line_onoffdash);
+#else
+                       LyXFont pb_font;
+                       pb_font.setColor(LColor::pagebreak).decSize();
+                       int w = 0, a = 0, d = 0;
+                       pain.line(0,
+                                 offset + y_bottom - 2 * DefaultHeight(), 
+                                 paperwidth, 
+                                 offset + y_bottom - 2 * DefaultHeight(),
+                                 LColor::pagebreak,
+                                 Painter::line_onoffdash)
+                               .rectText(0,
+                                         0,
+                                         _("Page Break (bottom)"),
+                                         pb_font,
+                                         LColor::background,
+                                         LColor::background, false, w, a, d);
+                       pain.rectText((paperwidth - w)/2,
+                                     offset +y_top + 2*DefaultHeight() +d,
+                                     _("Page Break (bottom)"),
+                                     pb_font,
+                                     LColor::background,
+                                     LColor::background);
+#endif
                        y_bottom -= 3 * DefaultHeight();
                }
                
@@ -3866,6 +4076,40 @@ void LyXText::GetVisibleRow(int offset,
                                  Painter::line_thick);
                        y_bottom -= GetFont(par, par->Last() - 1).ascent('x');
                }
+
+               // draw an endlabel
+               int endlabel = row_ptr->par->GetEndLabel();
+               if (endlabel == END_LABEL_BOX ||
+                   endlabel == END_LABEL_FILLED_BOX) {
+                       LyXFont font = GetFont(row_ptr->par, RowLast(row_ptr));
+                       int size = int(0.75*font.maxAscent());
+                       int y = (offset + row_ptr->baseline) - size;
+                       int x = (direction == LYX_DIR_LEFT_TO_RIGHT)
+                               ? paperwidth - LYX_PAPER_MARGIN - size
+                               : LYX_PAPER_MARGIN;
+                       if (row_ptr->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
+                               if (direction == LYX_DIR_LEFT_TO_RIGHT)
+                                       x -= LYX_PAPER_MARGIN/2;
+                               else {
+                                       LyXFont font(LyXFont::ALL_SANE);
+                                       font.setSize(LyXFont::SIZE_SMALL);
+                                       x += font.textWidth("Mwide-figM", 10);
+                               }
+                       if (row_ptr->fill <= size)
+                               x += (size - row_ptr->fill + 1) * direction;
+                       if (endlabel == END_LABEL_BOX) {
+                               pain.line(x, y, x, y + size,
+                                         LColor::eolmarker);
+                               pain.line(x + size, y, x + size , y + size,
+                                         LColor::eolmarker);
+                               pain.line(x, y, x + size, y,
+                                         LColor::eolmarker);
+                               pain.line(x, y + size, x + size, y + size,
+                                         LColor::eolmarker);
+                       } else
+                               pain.fillRectangle(x, y, size, size,
+                                                  LColor::eolmarker);
+               }
        }
        
        /* draw the text in the pixmap */  
@@ -4149,7 +4393,7 @@ int LyXText::GetColumnNearX(Row * row, int & x) const
        LyXDirection direction = row->par->getParDirection();
        LyXParagraph::size_type vc = row->pos;
        LyXParagraph::size_type last = RowLast(row);
-       LyXParagraph::size_type c;
+       LyXParagraph::size_type c = 0;
 
        LyXLayout const & layout = textclasslist.Style(parameters->textclass,
                                                       row->par->GetLayout());
@@ -4232,10 +4476,15 @@ int LyXText::GetColumnNearX(Row * row, int & x) const
                        vc = row->pos+1;
                        tmpx += fill_separator+SingleWidth(row->par, vis2log(row->pos));
                }
-
        if (row->pos > last)  // Row is empty?
                c = row->pos;
-       else if (vc <= last) {
+       else if (vc > last ||
+                (row->par->table && vc > row->pos && row->par->IsNewline(vc)) ){
+               int pos = (vc > last+1) ? last : vc - 1; 
+               c = vis2log(pos);
+               if (row->par->getLetterDirection(c) == LYX_DIR_LEFT_TO_RIGHT)
+                       ++c;
+       } else {
                c = vis2log(vc);
                LyXDirection direction = row->par->getLetterDirection(c);
                if (vc > row->pos && row->par->IsLineSeparator(c)
@@ -4243,10 +4492,6 @@ int LyXText::GetColumnNearX(Row * row, int & x) const
                        c = vis2log(vc-1);
                if (direction == LYX_DIR_RIGHT_TO_LEFT)
                        ++c;
-       } else {
-               c = vis2log(last)+1;
-               if (row->par->getLetterDirection(c - 1) == LYX_DIR_RIGHT_TO_LEFT)
-                       --c;            
        }
 
        if (!row->par->table && row->pos <= last && c > last