X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftext.C;h=c81fae1f9b3af9e3315795c7f73349b769992667;hb=91a2ea274e9c27f571a3cd4798d2e8ecc1b982a7;hp=5fcfce853936a4abe43da91395004112c92c5003;hpb=4ed68c1bc2007d6505cc2d82c66494f63d9de107;p=lyx.git diff --git a/src/text.C b/src/text.C index 5fcfce8539..c81fae1f9b 100644 --- a/src/text.C +++ b/src/text.C @@ -1,12 +1,12 @@ /* This file is part of -* ====================================================== -* -* LyX, The Document Processor -* -* Copyright (C) 1995 Matthias Ettrich -* Copyright (C) 1995-1998 The LyX Team. -* -* ====================================================== */ + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2000 The LyX Team. + * + * ====================================================== */ #include #include @@ -20,29 +20,145 @@ #include "lyxparagraph.h" #include "lyxtext.h" #include "support/textutils.h" +#include "insets/insetbib.h" #include "lyx_gui_misc.h" -#include "lyxdraw.h" #include "gettext.h" #include "bufferparams.h" #include "buffer.h" -#include "lyxscreen.h" #include "minibuffer.h" #include "debug.h" +#include "lyxrc.h" #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 int mono_video; -extern int reverse_video; -extern int fast_selection; -extern BufferView * current_view; -extern int UnlockInset(UpdatableInset * inset); // ale070405 -extern int bibitemMaxWidth(LyXFont const &); +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) + LyXParagraph::size_type pos) const { char c = par->GetChar(pos); return SingleWidth(par, pos, c); @@ -50,26 +166,26 @@ int LyXText::SingleWidth(LyXParagraph * par, int LyXText::SingleWidth(LyXParagraph * par, - LyXParagraph::size_type pos, char c) + LyXParagraph::size_type pos, char c) const { LyXFont font = GetFont(par, pos); // 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)) { return 3; /* Because of the representation * as vertical lines */ - } else if (c == LyXParagraph::META_FOOTNOTE || c == LyXParagraph::META_MARGIN || c == LyXParagraph::META_FIG || c == LyXParagraph::META_TAB || c == LyXParagraph::META_WIDE_FIG || c == LyXParagraph::META_WIDE_TAB || - c == LyXParagraph::META_ALGORITHM) - { + c == LyXParagraph::META_ALGORITHM) { string fs; switch (c) { case LyXParagraph::META_MARGIN: @@ -97,12 +213,11 @@ int LyXText::SingleWidth(LyXParagraph * par, font.decSize(); font.decSize(); return font.stringWidth(fs); - } - - else if (c == LyXParagraph::META_INSET) { - Inset *tmpinset= par->GetInset(pos); + } else if (c == LyXParagraph::META_INSET) { + Inset * tmpinset= par->GetInset(pos); if (tmpinset) - return par->GetInset(pos)->Width(font); + return par->GetInset(pos)->width(owner_->painter(), + font); else return 0; @@ -115,40 +230,196 @@ int LyXText::SingleWidth(LyXParagraph * par, // Returns the paragraph position of the last character in the specified row -LyXParagraph::size_type LyXText::RowLast(Row * row) +LyXParagraph::size_type LyXText::RowLast(Row const * row) const { if (row->next == 0) - return row->par->Last()-1; + return row->par->Last() - 1; else if (row->next->par != row->par) - return row->par->Last()-1; + return row->par->Last() - 1; else return row->next->pos - 1; } -void LyXText::Draw(Row * row, LyXParagraph::size_type & pos, - LyXScreen & scr, int offset, float & x) + + + +void LyXText::ComputeBidiTables(Row * row) const +{ + + if (!lyxrc.rtl_support) { + bidi_start = -1; + return; + } + LyXParagraph::size_type last = RowLast(row); + bidi_start = row->pos; + + if (bidi_start > last) { + bidi_start = -1; + return; + } + + if (last + 2 - bidi_start > + static_cast(log2vis_list.size())) { + LyXParagraph::size_type new_size = + (last + 2 - bidi_start < 500) ? + 500 : 2 * (last + 2 - bidi_start); + log2vis_list.resize(new_size); + vis2log_list.resize(new_size); + } + + vis2log_list[last + 1 - bidi_start] = -1; + log2vis_list[last + 1 - bidi_start] = -1; + + LyXParagraph::size_type main_body = BeginningOfMainBody(row->par); + if (main_body > 0 && row->pos < main_body - 1 && main_body - 1 <= last + && row->par->IsLineSeparator(main_body - 1)) { + // This is needed in case there is a direction change in + // the label which is continued into the main body + if (row->par->getParDirection() == LYX_DIR_LEFT_TO_RIGHT) { + ComputeBidiTablesFromTo(row, bidi_start, + main_body - 2, 0); + log2vis_list[main_body - 1 - bidi_start] = + main_body - 1; + vis2log_list[main_body - 1 - bidi_start] = + main_body - 1; + if (main_body <= last) + ComputeBidiTablesFromTo(row, + main_body,last, 0); + } else { + ComputeBidiTablesFromTo(row, bidi_start, + main_body - 2, + last - main_body + 2); + log2vis_list[main_body - 1 - bidi_start] = + last - main_body + 1 + bidi_start; + vis2log_list[last - main_body + 1 - bidi_start] = + main_body - 1; + if (main_body <= last) + ComputeBidiTablesFromTo(row, main_body, + last, -main_body); + } + } else + ComputeBidiTablesFromTo(row, bidi_start, last, 0); +} + + +void LyXText::ComputeBidiTablesFromTo(Row * row, + LyXParagraph::size_type from, + LyXParagraph::size_type to, + LyXParagraph::size_type offset) const +{ + LyXParagraph::size_type vpos, old_lpos, stack[2]; + LyXDirection par_direction = row->par->getParDirection(); + LyXDirection direction = par_direction; + LyXParagraph::size_type lpos = from; + int level = 0; + + while (lpos <= to) { + if (row->par->getLetterDirection(lpos) == direction) { + log2vis_list[lpos - bidi_start] = direction; + ++lpos; + } else { + if (level == 0 || + (level == 1 && direction == LYX_DIR_RIGHT_TO_LEFT + && 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; + } else { + old_lpos = stack[--level]; + log2vis_list[old_lpos - bidi_start] = + log2vis_list[lpos - bidi_start] = + (old_lpos - lpos) * direction; + ++lpos; + } + direction = static_cast(-direction); + } + } + + while (level > 0) { + old_lpos = stack[--level]; + log2vis_list[old_lpos - bidi_start] = + (old_lpos - (to + 1)) * direction; + direction = static_cast(-direction); + } + + vpos = (par_direction == LYX_DIR_LEFT_TO_RIGHT) + ? from - 1 : to + 1; + vpos += offset; + for (lpos = from; lpos <= to; ++lpos) { + vpos += log2vis_list[lpos - bidi_start]; + vis2log_list[vpos - bidi_start] = lpos; + log2vis_list[lpos - bidi_start] = vpos; + } +} + + +void LyXText::draw(Row const * row, + LyXParagraph::size_type & vpos, + int offset, float & x) { + Painter & pain = owner_->painter(); + + LyXParagraph::size_type pos = vis2log(vpos); char c = row->par->GetChar(pos); if (IsNewlineChar(c)) { - ++pos; + ++vpos; // 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); + int asc = font.maxAscent(); + int y = offset + row->baseline; + int xp[3], yp[3]; + + if (row->par->getLetterDirection(pos) == LYX_DIR_LEFT_TO_RIGHT) { + xp[0] = int(x + wid * 0.375); + yp[0] = int(y - 0.875 * asc * 0.75); + + xp[1] = int(x); + yp[1] = int(y - 0.500 * asc * 0.75); + + xp[2] = int(x + wid * 0.375); + yp[2] = int(y - 0.125 * asc * 0.75); + + pain.lines(xp, yp, 3, LColor::eolmarker); + + xp[0] = int(x); + yp[0] = int(y - 0.500 * asc * 0.75); + + xp[1] = int(x + wid); + yp[1] = int(y - 0.500 * asc * 0.75); + + xp[2] = int(x + wid); + yp[2] = int(y - asc * 0.75); + + pain.lines(xp, yp, 3, LColor::eolmarker); + } else { + xp[0] = int(x + wid * 0.625); + yp[0] = int(y - 0.875 * asc * 0.75); + + xp[1] = int(x + wid); + yp[1] = int(y - 0.500 * asc * 0.75); + + xp[2] = int(x + wid * 0.625); + yp[2] = int(y - 0.125 * asc * 0.75); + + pain.lines(xp, yp, 3, LColor::eolmarker); + + xp[0] = int(x + wid); + yp[0] = int(y - 0.500 * asc * 0.75); + + xp[1] = int(x); + yp[1] = int(y - 0.500 * asc * 0.75); + + xp[2] = int(x); + yp[2] = int(y - asc * 0.75); + + pain.lines(xp, yp, 3, LColor::eolmarker); + } + x += wid; return; } @@ -166,9 +437,10 @@ void LyXText::Draw(Row * row, LyXParagraph::size_type & pos, switch (c) { case LyXParagraph::META_MARGIN: fs = "margin"; - // Draw a sign at the left margin! - scr.drawText(font, "!", 1, offset + row->baseline, - (LYX_PAPER_MARGIN - font.width('!'))/2); + // Draw a sign at the left margin! + owner_->painter() + .text((LYX_PAPER_MARGIN - font.width('!'))/2, + offset + row->baseline, "!", 1, font); break; case LyXParagraph::META_FIG: fs = "fig"; @@ -196,23 +468,27 @@ void LyXText::Draw(Row * row, LyXParagraph::size_type & pos, int y = (row->baseline - font2.maxAscent() + font.maxAscent()); - font.setColor(LyXFont::INSET); + font.setColor(LColor::footnote); float tmpx = x; // draw it and set new x position - x += scr.drawString(font, fs, offset + y, int(x)); + + pain.text(int(x), offset + y, fs, font); + x += pain.width(fs, font); + pain.line(int(tmpx), offset + row->baseline, + int(x), offset + row->baseline, + LColor::footnote); - scr.drawLine(gc_foot, offset + row->baseline, - int(tmpx), int(x - tmpx)); - - pos++; + ++vpos; return; } else if (c == LyXParagraph::META_INSET) { Inset * tmpinset = row->par->GetInset(pos); - if (tmpinset) - tmpinset->Draw(font, scr, offset + row->baseline, x); - pos++; + if (tmpinset) { + tmpinset->draw(owner_->painter(), font, + offset + row->baseline, x); + } + ++vpos; return; } @@ -229,36 +505,35 @@ void LyXText::Draw(Row * row, LyXParagraph::size_type & pos, // 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; - ++pos; + ++vpos; LyXParagraph::size_type last = RowLast(row); - while (pos <= last - && static_cast(c = row->par->GetChar(pos)) > ' ' + while (vpos <= last && + (pos = vis2log(vpos)) >= 0 + && static_cast(c = row->par->GetChar(pos)) > ' ' && font2 == GetFont(row->par, pos)) { + if (do_transform) + c = TransformChar(c, row->par, pos); textstring += c; - ++pos; + ++vpos; } 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.c_str(), - textstring.length()), a+d); - } // Draw text and set the new x position - x += scr.drawText(font, textstring.c_str(), textstring.length(), - offset + row->baseline, - int(x)); + pain.text(int(x), offset + row->baseline, textstring, font); + x += pain.width(textstring, font); // 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)); + pain.line(tmpx, offset + row->baseline + 2, + x, offset + row->baseline + 2); + } // If we want ulem.sty support, drawing @@ -267,314 +542,340 @@ void LyXText::Draw(Row * row, LyXParagraph::size_type & pos, } -/* 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) +// 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 const * row) const { - LyXFont labelfont; - LyXParagraph * newpar; - Row dummyrow; - LyXLayout const & layout = textclasslist.Style(parameters->textclass, - row->par->GetLayout()); - - string parindent = layout.parindent; - - /* table stuff -- begin*/ - if (row->par->table) - parindent.clear(); - /* table stuff -- end*/ - - int x = LYX_PAPER_MARGIN; - - x += textclasslist.TextClass(parameters->textclass). - defaultfont().signedStringWidth(textclasslist.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 && textclasslist.Style(parameters->textclass, - newpar->GetLayout()).nextnoindent) - parindent.clear(); - } - } - } - 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 - && textclasslist.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.clear(); - else - parindent = textclasslist.Style(parameters->textclass, - newpar->GetLayout()).parindent; - } - - } - - labelfont = GetFont(row->par, -2); - switch (layout.margintype) { - case MARGIN_DYNAMIC: - if (!layout.leftmargin.empty()) { - x += textclasslist.TextClass(parameters->textclass).defaultfont().signedStringWidth(layout.leftmargin); - } - if (!row->par->GetLabestring().empty()) { - x += labelfont.signedStringWidth(layout.labelindent); - x += labelfont.stringWidth(row->par->GetLabestring()); - 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 += ( textclasslist.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->GetLabestring()); - } - } - 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 += textclasslist.TextClass(parameters->textclass).defaultfont().signedStringWidth(layout.leftmargin); - x += minfill; - } - break; - } - if (row->par->pextra_type == LyXParagraph::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 == BufferParams::PARSEP_INDENT)) - x += textclasslist.TextClass(parameters->textclass).defaultfont().stringWidth(parindent); - else - if (layout.labeltype == LABEL_BIBLIO) { // ale970405 Right width for bibitems - x += bibitemMaxWidth(textclasslist.TextClass(parameters->textclass).defaultfont()); - } - } - - return x; + LyXLayout const & layout = textclasslist.Style(parameters->textclass, + row->par->GetLayout()); + + string parindent = layout.parindent; + + /* table stuff -- begin */ + if (row->par->table) + parindent.clear(); + /* table stuff -- end */ + + int x = LYX_PAPER_MARGIN; + + x += textclasslist.TextClass(parameters->textclass) + .defaultfont() + .signedStringWidth(textclasslist + .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()) { + LyXParagraph * newpar = row->par + ->DepthHook(row->par->GetDepth()); + if (newpar && + textclasslist.Style(parameters->textclass, + newpar->GetLayout()) + .nextnoindent) + parindent.clear(); + } + } + } else { + // find the next level paragraph + + LyXParagraph * 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 + && textclasslist + .Style(parameters->textclass, + newpar->GetLayout()).isEnvironment()) { + Row dummyrow; + 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 + row->par->FirstPhysicalPar()->depth = 0; + } + + if (newpar && !row->par->GetLayout()) { + if (newpar->FirstPhysicalPar()->noindent) + parindent.clear(); + else + parindent = textclasslist + .Style(parameters->textclass, + newpar->GetLayout()).parindent; + } + + } + + LyXFont labelfont = GetFont(row->par, -2); + switch (layout.margintype) { + case MARGIN_DYNAMIC: + if (!layout.leftmargin.empty()) { + x += textclasslist + .TextClass(parameters->textclass) + .defaultfont() + .signedStringWidth(layout.leftmargin); + } + if (!row->par->GetLabestring().empty()) { + x += labelfont.signedStringWidth(layout.labelindent); + x += labelfont.stringWidth(row->par->GetLabestring()); + 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 += textclasslist.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->GetLabestring()); + } + 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 const * 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 += textclasslist.TextClass(parameters->textclass) + .defaultfont().signedStringWidth(layout.leftmargin); + x += minfill; + } + break; + } + if (row->par->pextra_type == LyXParagraph::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(owner_); + + if (xx > paperwidth) + xx = paperwidth * 80 / 100; + x += xx; + } else { // should not happen + LyXFont font(LyXFont::ALL_SANE); + x += font.stringWidth("XXXXXX"); + } + } + + int align; // wrong type + 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 == + BufferParams::PARSEP_INDENT)) + x += textclasslist.TextClass(parameters->textclass) + .defaultfont().signedStringWidth(parindent); + else if (layout.labeltype == LABEL_BIBLIO) { + // ale970405 Right width for bibitems + x += bibitemMaxWidth(owner_->painter(), + textclasslist + .TextClass(parameters + ->textclass) + .defaultfont()); + } + } + return x; } -int LyXText::RightMargin(Row *row) +int LyXText::RightMargin(Row const * row) const { - LyXParagraph * newpar; - Row dummyrow; - LyXLayout const & layout = textclasslist.Style(parameters->textclass, row->par->GetLayout()); - - int x = LYX_PAPER_MARGIN; - - x += textclasslist.TextClass(parameters->textclass). - defaultfont().signedStringWidth(textclasslist.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 - && textclasslist.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; - } - } - - //lyxerr << "rightmargin: " << layout->rightmargin << endl; - x += (textclasslist.TextClass(parameters->textclass).defaultfont().signedStringWidth(layout.rightmargin) * 4 - / (row->par->GetDepth() + 4)); - return x; - + LyXLayout const & layout = + textclasslist.Style(parameters->textclass, + row->par->GetLayout()); + + int x = LYX_PAPER_MARGIN + + textclasslist + .TextClass(parameters->textclass) + .defaultfont() + .signedStringWidth(textclasslist + .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 + + LyXParagraph * 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 + && textclasslist.Style(parameters->textclass, + newpar->GetLayout()) + .isEnvironment()) { + Row dummyrow; + 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 + row->par->FirstPhysicalPar()->depth = 0; + } + } + + //lyxerr << "rightmargin: " << layout->rightmargin << endl; + x += textclasslist.TextClass(parameters->textclass) + .defaultfont() + .signedStringWidth(layout.rightmargin) * 4 + / (row->par->GetDepth() + 4); + return x; } -int LyXText::LabelEnd (Row * row) +int LyXText::LabelEnd (Row const * row) const { - if (textclasslist.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. */ + if (textclasslist.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, - LyXParagraph::size_type pos) + LyXParagraph::size_type pos) const { int cell = 0; LyXParagraph::size_type tmp_pos = 0; while (tmp_pos < pos) { if (par->IsNewline(tmp_pos)) - cell++; - tmp_pos++; + ++cell; + ++tmp_pos; } return cell; } -int LyXText::WidthOfCell(LyXParagraph * par, LyXParagraph::size_type & pos) +int LyXText::WidthOfCell(LyXParagraph * par, + LyXParagraph::size_type & pos) const { int w = 0; while (pos < par->Last() && !par->IsNewline(pos)) { w += SingleWidth(par, pos); - pos++; + ++pos; } if (par->IsNewline(pos)) - pos++; + ++pos; return w; } -bool LyXText::HitInTable(Row * row, int x) +bool LyXText::HitInTable(Row * row, int x) const { - float tmpx; - float fill_separator, fill_hfill, fill_label_hfill; - if (!row->par->table) - return false; - PrepareToPrint(row, tmpx, fill_separator, fill_hfill, fill_label_hfill); - return (x > tmpx && x < tmpx + row->par->table->WidthOfTable()); + float tmpx; + float fill_separator, fill_hfill, fill_label_hfill; + if (!row->par->table) + return false; + PrepareToPrint(row, tmpx, fill_separator, + fill_hfill, fill_label_hfill, false); + return (x > tmpx && x < tmpx + row->par->table->WidthOfTable()); } -bool LyXText::MouseHitInTable(int x, long y) +bool LyXText::MouseHitInTable(int x, long y) const { Row * row = GetRowNearY(y); return HitInTable(row, x); @@ -584,18 +885,11 @@ bool LyXText::MouseHitInTable(int x, long y) /* table stuff -- end*/ -/* get the next breakpoint in a given paragraph */ +// get the next breakpoint in a given paragraph LyXParagraph::size_type -LyXText::NextBreakPoint(Row * row, int width) +LyXText::NextBreakPoint(Row const * row, int width) const { - int x = 0; - LyXParagraph::size_type last_separator = -1; - /* position of the last possible breakpoint - * -1 isn't a suitable value, but a flag */ - int left_margin; - LyXParagraph * par = row->par; - LyXParagraph::size_type i = 0; LyXParagraph::size_type pos = row->pos; /* table stuff -- begin*/ @@ -607,93 +901,97 @@ LyXText::NextBreakPoint(Row * row, int width) par->GetInset(pos) && par->GetInset(pos)->display()){ par->GetInset(pos)->display(false); } - pos++; + ++pos; } return pos; } /* table stuff -- end*/ - left_margin = LabelEnd(row); + // position of the last possible breakpoint + // -1 isn't a suitable value, but a flag + LyXParagraph::size_type last_separator = -1; width -= RightMargin(row); - LyXParagraph::size_type main_body = - BeginningOfMainBody(par); - LyXLayout const & layout = textclasslist.Style(parameters->textclass, par->GetLayout()); - i = pos; - char c; + LyXParagraph::size_type main_body = BeginningOfMainBody(par); + LyXLayout const & layout = + textclasslist.Style(parameters->textclass, par->GetLayout()); + LyXParagraph::size_type i = pos; + 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; + i = par->Last() - 1; // this means break + //x = width; } else if (par->GetChar(i) == LyXParagraph::META_INSET && par->GetInset(i) && par->GetInset(i)->display()){ par->GetInset(i)->display(false); } - i++; + ++i; } } else { // Last position is an invariant LyXParagraph::size_type const last = par->Last(); - /* this is the usual handling */ - x = LeftMargin(row); + // this is the usual handling + int x = LeftMargin(row); while (x < width && i < last) { - c = par->GetChar(i); + char c = par->GetChar(i); if (IsNewlineChar(c)) { last_separator = i; - x = width; /* this means break */ + x = width; // this means break } else if (c == LyXParagraph::META_INSET && par->GetInset(i) && par->GetInset(i)->display()){ - /* check wether a Display() inset is valid here . - if not, change it to non-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 */ + // display istn't allowd par->GetInset(i)->display(false); x += SingleWidth(par, i, c); } else { - /* inset is display. So break the line here */ + // 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++; + ++last_separator; } else last_separator = last; // to avoid extra rows } else last_separator = i - 1; - x = width; /* this means break */ + x = width; // this means break } } else { if (IsLineSeparatorChar(c)) last_separator = i; x += SingleWidth(par, i, c); } - i++; + ++i; if (i == main_body) { 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; } } - /* end of paragraph is always a suitable separator */ + // 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 */ + // 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 */ + // manual labels cannot be broken in LaTeX, do not care if (main_body && last_separator < main_body) last_separator = main_body - 1; @@ -701,224 +999,231 @@ LyXText::NextBreakPoint(Row * row, int width) } -/* returns the minimum space a row needs on the screen in pixel */ -int LyXText::Fill(Row * row, int paperwidth) +// returns the minimum space a row needs on the screen in pixel +int LyXText::Fill(Row const * row, int paper_width) const { - int w, fill; - /* get the pure distance */ - LyXParagraph::size_type last = RowLast(row); - /* table stuff -- begin*/ - if (row->par->table) { - /* for tables FILL does calculate the widthes of each cell in - * the row */ - LyXParagraph::size_type 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*/ - - 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--; - - /* 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 (textclasslist.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; - } - else - w = LeftMargin(row); - - LyXLayout const & layout = textclasslist.Style(parameters->textclass, - row->par->GetLayout()); - LyXParagraph::size_type main_body = - BeginningOfMainBody(row->par); - LyXParagraph::size_type 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; + int w, fill; + // get the pure distance + LyXParagraph::size_type last = RowLast(row); + /* table stuff -- begin */ + if (row->par->table) { + // for tables FILL does calculate the widthes of each cell in + // the row + LyXParagraph::size_type 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*/ + + // 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 (textclasslist.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; + } else + w = LeftMargin(row); + + LyXLayout const & layout = textclasslist.Style(parameters->textclass, + row->par->GetLayout()); + LyXParagraph::size_type main_body = + BeginningOfMainBody(row->par); + LyXParagraph::size_type i = row->pos; + + while (i <= last) { + if (main_body > 0 && i == main_body) { + w += GetFont(row->par, -2). + 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; + } + w += SingleWidth(row->par, i); + ++i; + } + if (main_body > 0 && main_body > last) { + 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; + } + + fill = paper_width - w - RightMargin(row); + return fill; } -/* returns the minimum space a manual label needs on the screen in pixel */ -int LyXText::LabelFill(Row * row) +// returns the minimum space a manual label needs on the screen in pixel +int LyXText::LabelFill(Row const * row) const { - - LyXParagraph::size_type 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--; - - int w = 0; - int i = row->pos; - while (i<= last) { - w += SingleWidth(row->par, i); - i++; - } - - int fill = 0; - if (!row->par->labelwidthstring.empty()) { - fill = GetFont(row->par, -2).stringWidth(row->par->labelwidthstring) - w; - } - - if (fill < 0) - fill = 0; - - return fill; + LyXParagraph::size_type 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; + + int w = 0; + int i = row->pos; + while (i <= last) { + w += SingleWidth(row->par, i); + ++i; + } + + int fill = 0; + 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) +// returns the number of separators in the specified row. The separator +// on the very last column doesnt count +int LyXText::NumberOfSeparators(Row const * row) const { - int last = RowLast(row); - int n = 0; - int 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; + int last = RowLast(row); + int p = max(row->pos, BeginningOfMainBody(row->par)); + int n = 0; + 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) +// 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 const * row) const { - int last = RowLast(row); - int first = row->pos; - if (first) { /* hfill *DO* count at the beginning - * of paragraphs! */ - while(first <= last && row->par->IsHfill(first)) - first++; - } + int last = RowLast(row); + int first = row->pos; + if (first) { /* hfill *DO* count at the beginning + * of paragraphs! */ + while(first <= last && row->par->IsHfill(first)) + ++first; + } - int main_body = BeginningOfMainBody(row->par); - if (first < main_body) - first = main_body; - int n = 0; - for (int p = first; p <= last; p++) { // last, because the end is ignored! - if (row->par->IsHfill(p)) { - n++; - } - } - return n; + first = max(first, BeginningOfMainBody(row->par)); + int n = 0; + for (int 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) +// like NumberOfHfills, but only those in the manual label! +int LyXText::NumberOfLabelHfills(Row const * row) const { - LyXParagraph::size_type last = RowLast(row); - LyXParagraph::size_type first = row->pos; - if (first) { /* hfill *DO* count at the beginning - * of paragraphs! */ - while(first < last && row->par->IsHfill(first)) - first++; - } - LyXParagraph::size_type main_body = - BeginningOfMainBody(row->par); - if (last > main_body) - last = main_body; - - int n = 0; - for (LyXParagraph::size_type p = first; - p < last; ++p) { // last, because the end is ignored! - if (row->par->IsHfill(p)) { - ++n; - } - } - return n; + LyXParagraph::size_type last = RowLast(row); + LyXParagraph::size_type first = row->pos; + if (first) { /* hfill *DO* count at the beginning + * of paragraphs! */ + while(first < last && row->par->IsHfill(first)) + ++first; + } + + last = min(last, BeginningOfMainBody(row->par)); + int n = 0; + for (LyXParagraph::size_type 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, - LyXParagraph::size_type pos) +// returns true, if a expansion is needed. +// Rules are given by LaTeX +bool LyXText::HfillExpansion(Row const * row_ptr, + LyXParagraph::size_type pos) const { - /* 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 ( textclasslist.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 */ - LyXParagraph::size_type i = row_ptr->pos; - while (i < pos && (row_ptr->par->IsNewline(i) - || row_ptr->par->IsHfill(i))) - i++; - - return (i != 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 (textclasslist.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 + LyXParagraph::size_type 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) +void LyXText::SetHeightOfRow(Row * row_ptr) const { /* get the maximum ascent and the maximum descent */ - int asc, maxasc, desc, maxdesc, pos_end, pos, labeladdon; + int asc, desc, pos; float layoutasc = 0; float layoutdesc = 0; float tmptop = 0; @@ -941,7 +1246,8 @@ void LyXText::SetHeightOfRow(Row * row_ptr) LyXParagraph * par = row_ptr->par->LastPhysicalPar(); LyXParagraph * firstpar = row_ptr->par->FirstPhysicalPar(); - LyXLayout const & layout = textclasslist.Style(parameters->textclass, firstpar->GetLayout()); + LyXLayout const & layout = textclasslist.Style(parameters->textclass, + firstpar->GetLayout()); LyXFont font = GetFont(par, par->Last()-1); LyXFont::FONT_SIZE size = font.size(); @@ -950,25 +1256,25 @@ void LyXText::SetHeightOfRow(Row * row_ptr) LyXFont labelfont = GetFont(par, -2); - maxasc = int(font.maxAscent() * + int maxasc = int(font.maxAscent() * layout.spacing.getValue() * parameters->spacing.getValue()); - maxdesc = int(font.maxDescent() * + int maxdesc = int(font.maxDescent() * layout.spacing.getValue() * parameters->spacing.getValue()); - pos_end = RowLast(row_ptr); + int pos_end = RowLast(row_ptr); - labeladdon = 0; + int labeladdon = 0; // Check if any insets are larger - for (pos = row_ptr->pos; pos <= pos_end; pos++) { + for (pos = row_ptr->pos; pos <= pos_end; ++pos) { if (row_ptr->par->GetChar(pos) == LyXParagraph::META_INSET) { tmpfont = GetFont(row_ptr->par, pos); tmpinset = row_ptr->par->GetInset(pos); if (tmpinset) { - asc = tmpinset->Ascent(tmpfont); - desc = tmpinset->Descent(tmpfont); + asc = tmpinset->ascent(owner_->painter(), tmpfont); + desc = tmpinset->descent(owner_->painter(), tmpfont); if (asc > maxasc) maxasc = asc; if (desc > maxdesc) @@ -980,7 +1286,8 @@ void LyXText::SetHeightOfRow(Row * row_ptr) // 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); + LyXFont::FONT_SIZE maxsize = row_ptr->par->HighestFontInRange(row_ptr->pos, + pos_end); if (maxsize > font.size()) { font.setSize(maxsize); @@ -1001,8 +1308,8 @@ void LyXText::SetHeightOfRow(Row * row_ptr) /* table stuff -- end*/ // This is nicer with box insets: - maxasc++; - maxdesc++; + ++maxasc; + ++maxdesc; row_ptr->ascent_of_text = maxasc; @@ -1015,13 +1322,13 @@ void LyXText::SetHeightOfRow(Row * row_ptr) if (layout.isParagraph() && firstpar->GetDepth() == 0 && firstpar->Previous()) - maxasc += parameters->getDefSkip().inPixels(); + maxasc += parameters->getDefSkip().inPixels(owner_); else if (firstpar->Previous() && textclasslist.Style(parameters->textclass, firstpar->Previous()->GetLayout()).isParagraph() && firstpar->Previous()->GetDepth() == 0) // is it right to use defskip here too? (AS) - maxasc += parameters->getDefSkip().inPixels(); + maxasc += parameters->getDefSkip().inPixels(owner_); } /* the paper margins */ @@ -1030,7 +1337,7 @@ void LyXText::SetHeightOfRow(Row * row_ptr) /* add the vertical spaces, that the user added */ if (firstpar->added_space_top.kind() != VSpace::NONE) - maxasc += int(firstpar->added_space_top.inPixels()); + maxasc += int(firstpar->added_space_top.inPixels(owner_)); /* do not forget the DTP-lines! * there height depends on the font of the nearest character */ @@ -1074,7 +1381,7 @@ void LyXText::SetHeightOfRow(Row * row_ptr) * or between the items of a itemize or enumerate environment */ if (!firstpar->pagebreak_top) { - LyXParagraph *prev = row_ptr->par->Previous(); + LyXParagraph * prev = row_ptr->par->Previous(); if (prev) prev = row_ptr->par->DepthHook(row_ptr->par->GetDepth()); if (prev && prev->GetLayout() == firstpar->GetLayout() @@ -1127,7 +1434,7 @@ void LyXText::SetHeightOfRow(Row * row_ptr) /* add the vertical spaces, that the user added */ if (firstpar->added_space_bottom.kind() != VSpace::NONE) - maxdesc += int(firstpar->added_space_bottom.inPixels()); + maxdesc += int(firstpar->added_space_bottom.inPixels(owner_)); /* do not forget the DTP-lines! * there height depends on the font of the nearest character */ @@ -1141,8 +1448,8 @@ void LyXText::SetHeightOfRow(Row * row_ptr) /* 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; + LyXParagraph * nextpar = row_ptr->par->Next(); + LyXParagraph * comparepar = row_ptr->par; float usual = 0; float unusual = 0; @@ -1183,8 +1490,8 @@ void LyXText::SetHeightOfRow(Row * row_ptr) /* calculate the new height of the text */ height -= row_ptr->height; - row_ptr->height= maxasc+maxdesc+labeladdon; - row_ptr->baseline= maxasc+labeladdon; + row_ptr->height = maxasc + maxdesc + labeladdon; + row_ptr->baseline = maxasc + labeladdon; height += row_ptr->height; } @@ -1192,7 +1499,7 @@ void LyXText::SetHeightOfRow(Row * row_ptr) /* Appends the implicit specified paragraph behind the specified row, * start at the implicit given position */ -void LyXText::AppendParagraph(Row * row) +void LyXText::AppendParagraph(Row * row) const { bool not_ready = true; @@ -1208,7 +1515,7 @@ void LyXText::AppendParagraph(Row * row) // Insert the new row if (z < lastposition) { - z++; + ++z; InsertRow(row, row->par, z); row = row->next; @@ -1224,7 +1531,7 @@ void LyXText::AppendParagraph(Row * row) } -void LyXText::BreakAgain(Row * row) +void LyXText::BreakAgain(Row * row) const { bool not_ready = true; @@ -1236,14 +1543,14 @@ void LyXText::BreakAgain(Row * row) if (z < row->par->Last() ) { if (!row->next || (row->next && row->next->par != row->par)) { - /* insert a new row */ - z++; + // insert a new row + ++z; InsertRow(row, row->par, z); row = row->next; row->height = 0; } else { row = row->next; - z++; + ++z; if (row->pos == z) not_ready = false; // the rest will not change else { @@ -1281,14 +1588,14 @@ void LyXText::BreakAgainOneRow(Row * row) if (z < row->par->Last() ) { if (!row->next || (row->next && row->next->par != row->par)) { /* insert a new row */ - z++; + ++z; InsertRow(row, row->par, z); row = row->next; row->height = 0; } else { row= row->next; - z++; + ++z; if (row->pos != z) row->pos = z; } @@ -1317,16 +1624,16 @@ void LyXText::BreakParagraph(char keep_layout) LyXLayout const & layout = textclasslist.Style(parameters->textclass, cursor.par->GetLayout()); - /* table stuff -- begin*/ + /* 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->size() && !cursor.par->table->ShouldBeVeryLastCell(NumberOfCell(cursor.par, cursor.pos))) - return; /* no breaking of tables allowed */ + return; // no breaking of tables allowed } - /* table stuff -- end*/ + /* table stuff -- end */ - /* this is only allowed, if the current paragraph is not empty or caption*/ + // 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) @@ -1336,26 +1643,27 @@ void LyXText::BreakParagraph(char keep_layout) cursor.par->ParFromPos(cursor.pos)->previous, cursor.par->ParFromPos(cursor.pos)->next); - /* table stuff -- begin*/ + /* 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->text.size()); + SetCursor(cursor.par, cursor.par->size()); } - /* table stuff -- end*/ - /* please break alway behind a space */ + /* table stuff -- end */ + + // please break always behind a space if (cursor.pos < cursor.par->Last() && cursor.par->IsLineSeparator(cursor.pos)) cursor.pos++; - /* break the paragraph */ + // break the paragraph if (keep_layout) keep_layout = 2; else keep_layout = layout.isEnvironment(); cursor.par->BreakParagraph(cursor.pos, keep_layout); - /* table stuff -- begin*/ + /* table stuff -- begin */ if (cursor.par->table){ // the table should stay with the contents if (!cursor.pos){ @@ -1363,19 +1671,18 @@ void LyXText::BreakParagraph(char keep_layout) cursor.par->table = 0; } } - /* table stuff -- end*/ + /* table stuff -- end */ - /* well this is the caption hack since one caption is really enough */ + // 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 */ + cursor.par->SetLayout(0); // set to standard-layout else - cursor.par->Next()->SetLayout(0); /* set the new paragraph to standard-layout */ - + cursor.par->Next()->SetLayout(0); // set to standard-layout } /* if the cursor is at the beginning of a row without prior newline, - * move one row up! + * 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) && @@ -1387,7 +1694,7 @@ void LyXText::BreakParagraph(char keep_layout) refresh_row = cursor.row; refresh_y = cursor.y - cursor.row->baseline; - /* Do not forget the special right address boxes */ + // 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) { @@ -1397,7 +1704,7 @@ void LyXText::BreakParagraph(char keep_layout) } RemoveParagraph(cursor.row); - /* set the dimensions of the cursor row */ + // set the dimensions of the cursor row cursor.row->fill = Fill(cursor.row, paperwidth); SetHeightOfRow(cursor.row); @@ -1410,7 +1717,7 @@ void LyXText::BreakParagraph(char keep_layout) UpdateCounters(cursor.row->previous); - /* this check is necessary. Otherwise the new empty paragraph will + /* 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); @@ -1439,10 +1746,11 @@ void LyXText::OpenFootnote() /* 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++); + 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)->text.size()); + cursor.pos + cursor.par->ParFromPos(cursor.pos)->size()); /* the cursor must be exactly before the footnote */ par = cursor.par->ParFromPos(cursor.pos); @@ -1460,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) { @@ -1477,32 +1786,32 @@ void LyXText::OpenFootnote() /* table stuff -- begin*/ -void LyXText::TableFeatures(int feature, string val) +void LyXText::TableFeatures(int feature, string const & val) const { - if (!cursor.par->table) - return; /* this should never happen */ + if (!cursor.par->table) + return; /* this should never happen */ - int 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(); + int 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) +void LyXText::TableFeatures(int feature) const { int setLines = 0; int setAlign = LYX_ALIGN_LEFT; @@ -1546,37 +1855,41 @@ void LyXText::TableFeatures(int feature) !cursor.par->table->IsContRow(cell)) { while (pos < cursor.par->Last() && !cursor.par->IsNewline(pos)) - pos++; + ++pos; if (pos < cursor.par->Last()) - pos++; - cell++; + ++pos; + ++cell; } while((pos < cursor.par->Last()) && cursor.par->table->IsContRow(cell)) { while (pos < cursor.par->Last() && !cursor.par->IsNewline(pos)) - pos++; + ++pos; if (pos < cursor.par->Last()) - pos++; - cell++; + ++pos; + ++cell; } cell_org = --cell; if (pos < cursor.par->Last()) - pos--; + --pos; } while (pos < cursor.par->Last() && (cell == cell_org || !cursor.par->table->IsFirstCell(cell))){ while (pos < cursor.par->Last() && !cursor.par->IsNewline(pos)) - pos++; + ++pos; if (pos < cursor.par->Last()) - pos++; - cell++; + ++pos; + ++cell; } /* 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); @@ -1602,18 +1915,21 @@ void LyXText::TableFeatures(int feature) (cell == cell_org || !cursor.par->table->IsFirstCell(cell))){ while (pos < cursor.par->Last() && !cursor.par->IsNewline(pos)) - pos++; + ++pos; if (pos < cursor.par->Last()) - pos++; - cell++; + ++pos; + ++cell; } /* insert the new cells */ int number = cursor.par->table->NumberOfCellsInRow(cell_org); - int i; - for (i= 0; igetParLanguage(); + 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(); @@ -1623,10 +1939,13 @@ void LyXText::TableFeatures(int feature) 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)){ + 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; @@ -1636,9 +1955,12 @@ void LyXText::TableFeatures(int feature) ++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(), LyXParagraph::META_NEWLINE); + This saves one byte memory per table ;-) */ + 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); @@ -1647,8 +1969,8 @@ void LyXText::TableFeatures(int feature) return; } case LyXTable::DELETE_ROW: - if (current_view->buffer()->the_locking_inset) - UnlockInset(current_view->buffer()->the_locking_inset); + if (owner_->the_locking_inset) + owner_->unlockInset(owner_->the_locking_inset); RemoveTableRow(&cursor); RedoParagraph(); return; @@ -1657,8 +1979,8 @@ void LyXText::TableFeatures(int feature) LyXParagraph::size_type pos = 0; int cell_org = actCell; int cell = 0; - if (current_view->buffer()->the_locking_inset) - UnlockInset(current_view->buffer()->the_locking_inset); + if (owner_->the_locking_inset) + owner_->unlockInset(owner_->the_locking_inset); do { if (!pos || (cursor.par->IsNewline(pos-1))){ if (cursor.par->table->DeleteCellIfColumnIsDeleted(cell, cell_org)){ @@ -1740,9 +2062,9 @@ void LyXText::TableFeatures(int feature) if (!selection){ cursor.par->table->SetRightLine(actCell, lineSet); } else { - LyXParagraph::size_type i; int n = -1, m = -2; - for (i= sel_start_cursor.pos; i<= sel_end_cursor.pos; i++){ + LyXParagraph::size_type i = sel_start_cursor.pos; + for (; i <= sel_end_cursor.pos; ++i) { if ((n= NumberOfCell(sel_start_cursor.par, i)) != m) { cursor.par->table->SetRightLine(n, lineSet); m = n; @@ -1758,9 +2080,9 @@ void LyXText::TableFeatures(int feature) if (!selection){ cursor.par->table->SetAlignment(actCell, setAlign); } else { - LyXParagraph::size_type i; int n = -1, m = -2; - for (i= sel_start_cursor.pos; i<= sel_end_cursor.pos; i++){ + LyXParagraph::size_type i = sel_start_cursor.pos; + for (; i <= sel_end_cursor.pos; ++i) { if ((n= NumberOfCell(sel_start_cursor.par, i)) != m) { cursor.par->table->SetAlignment(n, setAlign); m = n; @@ -1778,7 +2100,7 @@ void LyXText::TableFeatures(int feature) // 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; @@ -1796,8 +2118,8 @@ void LyXText::TableFeatures(int feature) int newlines = cursor.par->table->UnsetMultiColumn(actCell); LyXParagraph::size_type pos = cursor.pos; while (pos < cursor.par->Last() && !cursor.par->IsNewline(pos)) - pos++; - for (;newlines;newlines--) + ++pos; + for (; newlines; --newlines) cursor.par->InsertChar(pos, LyXParagraph::META_NEWLINE); RedoParagraph(); return; @@ -1827,9 +2149,9 @@ void LyXText::TableFeatures(int feature) sel_start_cursor.par->InsertChar(i, ' '); else { sel_end_cursor.pos--; - i--; + --i; } - number++; + ++number; } } cursor.par->table-> @@ -1898,9 +2220,9 @@ void LyXText::TableFeatures(int feature) if (!selection){ cursor.par->table->SetRotateCell(actCell, false); } else { - LyXParagraph::size_type i; int n = -1, m = -2; - for (i= sel_start_cursor.pos; i<= sel_end_cursor.pos; i++){ + LyXParagraph::size_type i = sel_start_cursor.pos; + for (; i <= sel_end_cursor.pos; ++i) { if ((n= NumberOfCell(sel_start_cursor.par, i)) != m) { cursor.par->table->SetRotateCell(n, false); m = n; @@ -1970,16 +2292,17 @@ void LyXText::InsertCharInTable(char c) jumped_over_space = false; if (IsLineSeparatorChar(c)) { - + +#ifndef FIX_DOUBLE_SPACE /* 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->IsLineSeparator(cursor.pos)) { cursor.par->Erase(cursor.pos); jumped_over_space = true; - } - else if ((cursor.pos > 0 && + } else +#endif + if ((cursor.pos > 0 && cursor.par->IsLineSeparator(cursor.pos - 1)) || (cursor.pos > 0 && cursor.par->IsNewline(cursor.pos - 1)) || (cursor.pos == 0 && @@ -1987,8 +2310,7 @@ void LyXText::InsertCharInTable(char c) && cursor.par->Previous()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE))) return; - } - else if (IsNewlineChar(c)) { + } else if (IsNewlineChar(c)) { if (!IsEmptyTableCell()) { TableFeatures(LyXTable::APPEND_CONT_ROW); CursorDown(); @@ -2044,7 +2366,7 @@ void LyXText::CheckParagraphInTable(LyXParagraph * par, LyXParagraph::size_type tmp_pos = pos; /* update the table information */ while (tmp_pos && !par->IsNewline(tmp_pos - 1)) - tmp_pos--; + --tmp_pos; if (par->table->SetWidthOfCell(NumberOfCell(par, pos), WidthOfCell(par, tmp_pos))) { LyXCursor tmpcursor = cursor; @@ -2057,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; @@ -2088,13 +2411,12 @@ void LyXText::BackspaceInTable() /* no pasting of table paragraphs */ CursorLeft(); - } - else { + } 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); + SetUndo(Undo::DELETE, + cursor.par->ParFromPos(cursor.pos)->previous, + cursor.par->ParFromPos(cursor.pos)->next); CursorLeftIntern(); @@ -2121,7 +2443,8 @@ void LyXText::BackspaceInTable() tmprow = tmprow->next; tmprow->pos--; } - + +#ifndef FIX_DOUBLE_SPACE /* delete superfluous blanks */ if (cursor.pos < cursor.par->Last() - 1 && (cursor.par->IsLineSeparator(cursor.pos))) { @@ -2141,6 +2464,7 @@ void LyXText::BackspaceInTable() cursor.pos--; } } +#endif } CheckParagraphInTable(cursor.par, cursor.pos); @@ -2162,33 +2486,38 @@ void LyXText::BackspaceInTable() /* just a macro to make some thing easier. */ -void LyXText::RedoParagraph() +void LyXText::RedoParagraph() const { - LyXCursor tmpcursor = cursor; - ClearSelection(); - RedoParagraphs(cursor, cursor.par->Next());; - SetCursorIntern(tmpcursor.par, tmpcursor.pos); +#if 1 + // I suspect this version will work + // also. + ClearSelection(); + RedoParagraphs(cursor, cursor.par->Next()); + SetCursorIntern(cursor.par, cursor.pos); +#else + LyXCursor tmpcursor = cursor; + ClearSelection(); + RedoParagraphs(cursor, cursor.par->Next()); + SetCursorIntern(tmpcursor.par, tmpcursor.pos); +#endif } /* insert a character, moves all the following breaks in the * same Paragraph one to the right and make a rebreak */ -void LyXText::InsertChar(char c) +void LyXText::InsertChar(char c) { SetUndo(Undo::INSERT, cursor.par->ParFromPos(cursor.pos)->previous, cursor.par->ParFromPos(cursor.pos)->next); /* When the free-spacing option is set for the current layout, - * all spaces are converted to protected spaces. */ - bool freeSpacingBo = + * 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; - + /* table stuff -- begin*/ if (cursor.par->table) { InsertCharInTable(c); @@ -2197,11 +2526,11 @@ void LyXText::InsertChar(char c) } /* table stuff -- end*/ - /* first check, if there will be two blanks together or a blank at - * the beginning of a paragraph. - * I decided to handle blanks like normal characters, the main - * difference are the special checks when calculating the row.fill - * (blank does not count at the end of a row) and the check here */ + /* 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 */ // The bug is triggered when we type in a description environment: // The current_font is not changed when we go from label to main text @@ -2223,8 +2552,8 @@ 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)) { /* the user inserted a space before a space. So we @@ -2234,26 +2563,36 @@ void LyXText::InsertChar(char c) * blank at the end of a row we have to force * a rebreak.*/ - current_view->owner()->getMiniBuffer()->Set(_("You cannot type two spaces this way. Please read the Tutorial.")); + owner_->owner()->getMiniBuffer() + ->Set(_("You cannot type two spaces this way. " + " Please read the Tutorial.")); +#if 1 + // How can this ever happen? if (cursor.pos == RowLast(cursor.row) && !IsLineSeparatorChar(c)) - cursor.row->fill = -1; /* force rebreak */ - + cursor.row->fill = -1; // force rebreak cursor.par->Erase(cursor.pos); jumped_over_space = true; - - } else if ((cursor.pos > 0 - && cursor.par->IsLineSeparator(cursor.pos - 1)) - || (cursor.pos > 0 - && cursor.par->IsNewline(cursor.pos - 1)) - || (cursor.pos == 0 - && !(cursor.par->Previous() - && cursor.par->Previous()->footnoteflag - == LyXParagraph::OPEN_FOOTNOTE))) { +#else + // Seems to me that this works just as well. + CursorRight(); + charInserted(); + return; +#endif + } else +#endif + 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))) { if (cursor.pos == 0 ) - current_view->owner()->getMiniBuffer()->Set(_("You cannot insert a space at the beginning of a paragraph. Please read the Tutorial.")); + owner_->owner()->getMiniBuffer()->Set(_("You cannot insert a space at the beginning of a paragraph. Please read the Tutorial.")); else - current_view->owner()->getMiniBuffer()->Set(_("You cannot type two spaces this way. Please read the Tutorial.")); + owner_->owner()->getMiniBuffer()->Set(_("You cannot type two spaces this way. Please read the Tutorial.")); charInserted(); return; } @@ -2263,7 +2602,7 @@ void LyXText::InsertChar(char c) charInserted(); return; } - /* no newline at first position + /* No newline at first position * of a paragraph or behind labels. * TeX does not allow that. */ @@ -2273,26 +2612,22 @@ void LyXText::InsertChar(char c) cursor.row->fill = -1; // to force a new break } - /* the display inset stuff */ + // the display inset stuff if (cursor.row->par->GetChar(cursor.row->pos) == LyXParagraph::META_INSET && cursor.row->par->GetInset(cursor.row->pos) && cursor.row->par->GetInset(cursor.row->pos)->display()) cursor.row->fill = -1; // to force a new break - /* get the cursor row fist */ - /* this is a dumb solution, i will try to hold the cursor.row - in future */ - /* row = GetRow(cursor.par, cursor.pos, y);*/ - /* ok, heres a better way: */ + // get the cursor row fist Row * row = cursor.row; long y = cursor.y - row->baseline; - if (c != LyXParagraph::META_INSET) /* in this case LyXText::InsertInset - * already insertet the character */ + if (c != LyXParagraph::META_INSET) /* Here case LyXText::InsertInset + * already insertet the character */ cursor.par->InsertChar(cursor.pos, c); SetCharFont(cursor.par, cursor.pos, rawtmpfont); if (!jumped_over_space) { - /* refresh the positions */ + // refresh the positions Row * tmprow = row; while (tmprow->next && tmprow->next->par == row->par) { tmprow = tmprow->next; @@ -2300,7 +2635,7 @@ void LyXText::InsertChar(char c) } } - /* Is there a break one row above */ + // Is there a break one row above if ((cursor.par->IsLineSeparator(cursor.pos) || cursor.par->IsNewline(cursor.pos) || cursor.row->fill == -1) @@ -2310,7 +2645,7 @@ void LyXText::InsertChar(char c) if ( z >= row->pos) { row->pos = z + 1; - /* set the dimensions of the row above */ + // set the dimensions of the row above row->previous->fill = Fill(row->previous, paperwidth); SetHeightOfRow(row->previous); @@ -2321,16 +2656,16 @@ void LyXText::InsertChar(char c) status = LyXText::NEED_MORE_REFRESH; BreakAgainOneRow(row); - SetCursor(cursor.par, cursor.pos + 1); + + current_font = rawtmpfont; + real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos + 1, false); /* cursor MUST be in row now */ if (row->next && row->next->par == row->par) need_break_row = row->next; else need_break_row = 0; - - current_font = rawtmpfont; - real_current_font = realtmpfont; // check, wether the last characters font has changed. if (cursor.pos && cursor.pos == cursor.par->Last() @@ -2362,14 +2697,13 @@ void LyXText::InsertChar(char c) row = row->next; BreakAgainOneRow(row); } - SetCursor(cursor.par, cursor.pos + 1); + current_font = rawtmpfont; + real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos + 1, false); if (row->next && row->next->par == row->par) need_break_row = row->next; else - need_break_row = 0; - - current_font = rawtmpfont; - real_current_font = realtmpfont; + need_break_row = 0; } else { refresh_y = y; refresh_x = cursor.x; @@ -2383,9 +2717,9 @@ void LyXText::InsertChar(char c) else status = LyXText::NEED_MORE_REFRESH; - SetCursor(cursor.par, cursor.pos + 1); current_font = rawtmpfont; real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos + 1, false); } /* check, wether the last characters font has changed. */ @@ -2418,9 +2752,11 @@ void LyXText::charInserted() } } - -void LyXText::PrepareToPrint(Row * row, float & x, float & fill_separator, - float & fill_hfill, float & fill_label_hfill) +void LyXText::PrepareToPrint(Row * row, float & x, + float & fill_separator, + float & fill_hfill, + float & fill_label_hfill, + bool bidi) const { float nh, nlh, ns; @@ -2429,8 +2765,19 @@ void LyXText::PrepareToPrint(Row * row, float & x, float & fill_separator, fill_label_hfill = 0; fill_separator = 0; fill_label_hfill = 0; - - x = LeftMargin(row); + + LyXDirection direction = row->par->getParDirection(); + + if (direction == LYX_DIR_RIGHT_TO_LEFT) { + x = RightMargin(row); + if (row->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { + LyXFont font(LyXFont::ALL_SANE); + font.setSize(LyXFont::SIZE_SMALL); + x += font.textWidth("Mwide-figM", 10); + } + } + else + x = LeftMargin(row); /* is there a manual margin with a manual label */ if (textclasslist.Style(parameters->textclass, @@ -2461,11 +2808,11 @@ void LyXText::PrepareToPrint(Row * row, float & x, float & fill_separator, else { /* is it block, flushleft or flushright? * set x how you need it */ - int align; - if (row->par->FirstPhysicalPar()->align == LYX_ALIGN_LAYOUT) - align = textclasslist.Style(parameters->textclass, row->par->GetLayout()).align; - else - align = row->par->FirstPhysicalPar()->align; + int align; + if (row->par->FirstPhysicalPar()->align == LYX_ALIGN_LAYOUT) + align = textclasslist.Style(parameters->textclass, row->par->GetLayout()).align; + else + align = row->par->FirstPhysicalPar()->align; /* center displayed insets */ if (row->par->GetChar(row->pos) == LyXParagraph::META_INSET @@ -2483,6 +2830,8 @@ void LyXText::PrepareToPrint(Row * row, float & x, float & fill_separator, && row->next->par->GetInset(row->next->pos)->display()) ) fill_separator = w / ns; + else if (direction == LYX_DIR_RIGHT_TO_LEFT) + x += w; break; case LYX_ALIGN_RIGHT: x += w; @@ -2492,8 +2841,32 @@ void LyXText::PrepareToPrint(Row * row, float & x, float & fill_separator, break; } } - } + if (!bidi) + return; + ComputeBidiTables(row); + if (direction == LYX_DIR_RIGHT_TO_LEFT) { + LyXParagraph::size_type main_body = + BeginningOfMainBody(row->par); + LyXParagraph::size_type last = RowLast(row); + + if (row->pos <= last + && !row->par->table + && last != vis2log(last) + && row->par->IsLineSeparator(last)) { + if (!(main_body > 0 && main_body-1 == last)) + x -= fill_separator+SingleWidth(row->par,last); + } else if (main_body > 0 && + (main_body-1 > last || + !row->par->IsLineSeparator(main_body-1))) { + LyXLayout const & layout = textclasslist.Style(parameters->textclass, + row->par->GetLayout()); + x += GetFont(row->par, -2).stringWidth(layout.labelsep); + if (main_body-1 <= last) + x += fill_label_hfill; + } + } +} /* important for the screen */ @@ -2502,10 +2875,11 @@ void LyXText::PrepareToPrint(Row * row, float & x, float & fill_separator, * realize, that you left an empty paragraph, they will delete it. * They also delete the corresponding row */ -void LyXText::CursorRightOneWord() +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()) @@ -2521,7 +2895,7 @@ void LyXText::CursorRightOneWord() { // printf("Current pos1 %d", tmpcursor.pos) ; tmpcursor.pos++; - steps++; + ++steps; } // Advance through word. while ( tmpcursor.pos < tmpcursor.par->Last() && @@ -2529,14 +2903,14 @@ void LyXText::CursorRightOneWord() { // printf("Current pos2 %d", tmpcursor.pos) ; tmpcursor.pos++; - steps++; + ++steps; } } SetCursor(tmpcursor.par, tmpcursor.pos); } -void LyXText::CursorTab() +void LyXText::CursorTab() const { if (cursor.par->table) { int cell = NumberOfCell(cursor.par, cursor.pos); @@ -2588,7 +2962,7 @@ void LyXText::CursorTab() /* -------> Skip initial whitespace at end of word and move cursor to *start* of prior word, not to end of next prior word. */ -void LyXText::CursorLeftOneWord() +void LyXText::CursorLeftOneWord() const { // treat HFills, floats and Insets as words LyXCursor tmpcursor = cursor; @@ -2700,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; @@ -2737,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 */ @@ -2762,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() @@ -2788,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(); @@ -2805,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; @@ -2839,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) { @@ -2857,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); @@ -2865,45 +3267,57 @@ void LyXText::ChangeWordCase(LyXText::TextCase action) } -void LyXText::Delete() +void LyXText::Delete() { - LyXCursor old_cursor = cursor; - /* this is a very easy implementation*/ - - /* just move to the right */ - CursorRightIntern(); - - if (cursor.par->previous == old_cursor.par->previous - && cursor.par != old_cursor.par) - return; // delete-emty-paragraph-mechanism has done it - - /* if you had success make a backspace */ - if (old_cursor.par != cursor.par || old_cursor.pos != cursor.pos) { - LyXCursor tmpcursor = cursor; - cursor = old_cursor; // to make sure undo gets the right cursor position - SetUndo(Undo::DELETE, - cursor.par->ParFromPos(cursor.pos)->previous, - cursor.par->ParFromPos(cursor.pos)->next); - cursor = tmpcursor; - Backspace(); - } + // this is a very easy implementation + + LyXCursor old_cursor = cursor; + int old_cur_par_id = old_cursor.par->id(); + int old_cur_par_prev_id = old_cursor.par->previous ? + old_cursor.par->previous->id() : 0; + + // 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 + // old_cursor. Will a solution where we compare paragraph id's + //work better? +#if 1 + if ((cursor.par->previous ? cursor.par->previous->id() : 0) + == old_cur_par_prev_id + && cursor.par->id() != old_cur_par_id) + return; // delete-empty-paragraph-mechanism has done it +#else + if (cursor.par->previous == old_cursor.par->previous + && cursor.par != old_cursor.par) + return; // delete-empty-paragraph-mechanism has done it +#endif + // if you had success make a backspace + if (old_cursor.par != cursor.par || old_cursor.pos != cursor.pos) { + LyXCursor tmpcursor = cursor; + cursor = old_cursor; // to make sure undo gets the right cursor position + SetUndo(Undo::DELETE, + cursor.par->ParFromPos(cursor.pos)->previous, + cursor.par->ParFromPos(cursor.pos)->next); + cursor = tmpcursor; + Backspace(); + } } -void LyXText::Backspace() +void LyXText::Backspace() { - LyXParagraph * tmppar; - Row * tmprow, * row; - long y; - int tmpheight; - - /* table stuff -- begin*/ - + DebugTracer trc1("LyXText::Backspace"); + + /* table stuff -- begin */ if (cursor.par->table) { BackspaceInTable(); return; } - /* table stuff -- end*/ + /* table stuff -- end */ LyXFont rawtmpfont = current_font; LyXFont realtmpfont = real_current_font; @@ -2913,24 +3327,31 @@ void LyXText::Backspace() LyXFont rawparfont = cursor.par->GetFontSettings(lastpos - 1); if (cursor.pos == 0) { - /* we may paste some paragraphs */ + 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? */ + // is it an empty paragraph? if ((lastpos == 0 || (lastpos == 1 && cursor.par->IsSeparator(0))) && !(cursor.par->Next() - && cursor.par->footnoteflag == - LyXParagraph::NO_FOOTNOTE - && cursor.par->Next()->footnoteflag == - LyXParagraph::OPEN_FOOTNOTE)) { + && 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; @@ -2938,8 +3359,8 @@ void LyXText::Backspace() CursorLeftIntern(); - /* the layout things can change the height of a row ! */ - tmpheight = cursor.row->height; + // the layout things can change the height of a row ! + int tmpheight = cursor.row->height; SetHeightOfRow(cursor.row); if (cursor.row->height != tmpheight) { refresh_y = cursor.y - cursor.row->baseline; @@ -2949,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); + 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. @@ -2969,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--; @@ -2989,17 +3417,23 @@ void LyXText::Backspace() refresh_row = cursor.row; refresh_y = cursor.y - cursor.row->baseline; - /* remove the lost paragraph */ - RemoveParagraph(tmprow); - RemoveRow(tmprow); + // remove the lost paragraph + // 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. */ + // the row may have changed, block, hfills etc. SetCursor(cursor.par, cursor.pos); } - } else { + } else { + DebugTracer trc("LyXText::Backspace normal backspace"); + /* this is the code for a normal backspace, not pasting * any paragraphs */ SetUndo(Undo::DELETE, @@ -3007,12 +3441,12 @@ void LyXText::Backspace() cursor.par->ParFromPos(cursor.pos)->next); CursorLeftIntern(); - /* some insets are undeletable here */ + // some insets are undeletable here if (cursor.par->GetChar(cursor.pos) == LyXParagraph::META_INSET) { if (!cursor.par->GetInset(cursor.pos)->Deletable()) return; - /* force complete redo when erasing display insets */ - /* this is a cruel mathod but save..... Matthias */ + // force complete redo when erasing display insets + // this is a cruel mathod but save..... Matthias if (cursor.par->GetInset(cursor.pos)->display()){ cursor.par->Erase(cursor.pos); RedoParagraph(); @@ -3020,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 */ @@ -3034,8 +3468,8 @@ void LyXText::Backspace() * to the behavior when pasting paragraphs */ if (cursor.pos && cursor.par->IsNewline(cursor.pos)) { cursor.par->Erase(cursor.pos); - /* refresh the positions */ - tmprow = row; + // refresh the positions + Row * tmprow = row; while (tmprow->next && tmprow->next->par == row->par) { tmprow = tmprow->next; tmprow->pos--; @@ -3045,7 +3479,7 @@ void LyXText::Backspace() if (cursor.pos < cursor.par->Last() && !cursor.par->IsSeparator(cursor.pos)) { cursor.par->InsertChar(cursor.pos, ' '); - /* refresh the positions */ + // refresh the positions tmprow = row; while (tmprow->next && tmprow->next->par == row->par) { tmprow = tmprow->next; @@ -3055,14 +3489,15 @@ void LyXText::Backspace() } else { cursor.par->Erase(cursor.pos); - /* refresh the positions */ - tmprow = row; + // refresh the positions + Row * tmprow = row; while (tmprow->next && tmprow->next->par == row->par) { tmprow = tmprow->next; tmprow->pos--; } - - /* delete superfluous blanks */ + +#ifndef FIX_DOUBLE_SPACE + // delete superfluous blanks if (cursor.pos < cursor.par->Last() - 1 && (cursor.par->IsLineSeparator(cursor.pos))) { @@ -3070,24 +3505,25 @@ void LyXText::Backspace() || !cursor.pos || cursor.par->IsLineSeparator(cursor.pos - 1)) { cursor.par->Erase(cursor.pos); - /* refresh the positions */ + // 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 */ + if (cursor.pos) // move one character left cursor.pos--; } } +#endif - /* delete newlines at the beginning of paragraphs */ + // delete newlines at the beginning of paragraphs while (cursor.par->Last() && cursor.par->IsNewline(cursor.pos) && cursor.pos == BeginningOfMainBody(cursor.par)) { cursor.par->Erase(cursor.pos); - /* refresh the positions */ + // refresh the positions tmprow = row; while (tmprow->next && tmprow->next->par == row->par) { @@ -3097,21 +3533,20 @@ void LyXText::Backspace() } } - /* is there a break one row above */ + // is there a break one row above if (row->previous && row->previous->par == row->par) { z = NextBreakPoint(row->previous, paperwidth); if ( z >= row->pos) { row->pos = z + 1; - tmprow = row->previous; + Row * tmprow = row->previous; - /* maybe the current row is now empty */ + // maybe the current row is now empty if (row->pos >= row->par->Last()) { - /* remove it */ + // remove it RemoveRow(row); need_break_row = 0; - } - else { + } else { BreakAgainOneRow(row); if (row->next && row->next->par == row->par) need_break_row = row->next; @@ -3119,7 +3554,7 @@ void LyXText::Backspace() need_break_row = 0; } - /* set the dimensions of the row above */ + // set the dimensions of the row above y -= tmprow->height; tmprow->fill = Fill(tmprow, paperwidth); SetHeightOfRow(tmprow); @@ -3127,10 +3562,10 @@ void LyXText::Backspace() refresh_y = y; refresh_row = tmprow; status = LyXText::NEED_MORE_REFRESH; - SetCursor(cursor.par, cursor.pos); current_font = rawtmpfont; real_current_font = realtmpfont; - /* check, whether the last character's font has changed. */ + SetCursor(cursor.par, cursor.pos, false); + // check, whether the last character's font has changed. rawtmpfont = cursor.par->GetFontSettings(cursor.par->Last() - 1); if (rawparfont != rawtmpfont) RedoHeightOfParagraph(cursor); @@ -3138,12 +3573,12 @@ void LyXText::Backspace() } } - /* break the cursor row again */ + // break the cursor row again z = NextBreakPoint(row, paperwidth); - if ( z != RowLast(row) || - (row->next && row->next->par == row->par && - RowLast(row) == row->par->Last() - 1)){ + if (z != RowLast(row) || + (row->next && row->next->par == row->par && + RowLast(row) == row->par->Last() - 1)){ /* it can happen that a paragraph loses one row * without a real breakup. This is when a word @@ -3158,16 +3593,17 @@ void LyXText::Backspace() status = LyXText::NEED_MORE_REFRESH; BreakAgainOneRow(row); - - SetCursor(cursor.par, cursor.pos); - /* cursor MUST be in row now */ + current_font = rawtmpfont; + real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos, false); + // cursor MUST be in row now if (row->next && row->next->par == row->par) need_break_row = row->next; else need_break_row = 0; } else { - /* set the dimensions of the row */ + // set the dimensions of the row row->fill = Fill(row, paperwidth); int tmpheight = row->height; SetHeightOfRow(row); @@ -3177,86 +3613,110 @@ void LyXText::Backspace() status = LyXText::NEED_MORE_REFRESH; refresh_y = y; refresh_row = row; - SetCursor(cursor.par, cursor.pos); + current_font = rawtmpfont; + real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos, false); } } - - /* restore the current font - * That is what a user expects! */ + DebugTracer trc2("LyXText::Backspace wrap up"); + + // restore the current font + // That is what a user expects! current_font = rawtmpfont; real_current_font = realtmpfont; - /* check, wether the last characters font has changed. */ + // check, wether the last characters font has changed. rawtmpfont = cursor.par->GetFontSettings(cursor.par->Last() - 1); if (rawparfont != rawtmpfont) { RedoHeightOfParagraph(cursor); } else { - /* now the special right address boxes */ + // now the special right address boxes if (textclasslist.Style(parameters->textclass, - cursor.par->GetLayout()).margintype == MARGIN_RIGHT_ADDRESS_BOX) { + cursor.par->GetLayout()).margintype == MARGIN_RIGHT_ADDRESS_BOX) { RedoDrawingOfParagraph(cursor); } } } -void LyXText::GetVisibleRow(LyXScreen & scr, int offset, +void LyXText::GetVisibleRow(int offset, Row * row_ptr, long y) { /* returns a printed row */ - LyXParagraph::size_type pos, pos_end; + Painter & pain = owner_->painter(); + + LyXDirection direction = row_ptr->par->getParDirection(); + LyXParagraph::size_type vpos, pos, pos_end; float x, tmpx; int y_top, y_bottom; float fill_separator, fill_hfill, fill_label_hfill; LyXParagraph * par, * firstpar; - int left_margin; LyXFont font; int maxdesc; if (row_ptr->height <= 0) { lyxerr << "LYX_ERROR: row.height: " << row_ptr->height << endl; return; } - left_margin = LabelEnd(row_ptr); PrepareToPrint(row_ptr, x, fill_separator, fill_hfill, fill_label_hfill); - - LyXParagraph::size_type main_body = - BeginningOfMainBody(row_ptr->par); + /* initialize the pixmap */ - scr.fillRectangle(gc_clear, - 0, offset, paperwidth, row_ptr->height); - // check for NOT FAST SELECTION - if (!fast_selection && !mono_video && selection) { + pain.fillRectangle(0, offset, paperwidth, row_ptr->height); + + if (selection) { /* selection code */ if (sel_start_cursor.row == row_ptr && sel_end_cursor.row == row_ptr) { - scr.fillRectangle(gc_selection, sel_start_cursor.x, - offset, - sel_end_cursor.x - - sel_start_cursor.x, - row_ptr->height); - } - else if (sel_start_cursor.row == row_ptr) { - scr.fillRectangle(gc_selection, sel_start_cursor.x, - offset, - paperwidth - sel_start_cursor.x, - row_ptr->height); + if (sel_start_cursor.x < sel_end_cursor.x) + pain.fillRectangle(sel_start_cursor.x, offset, + sel_end_cursor.x - sel_start_cursor.x, + row_ptr->height, + LColor::selection); + else + pain.fillRectangle(sel_end_cursor.x, offset, + sel_start_cursor.x - sel_end_cursor.x, + row_ptr->height, + LColor::selection); + } else if (sel_start_cursor.row == row_ptr) { + if (direction == LYX_DIR_LEFT_TO_RIGHT) + pain.fillRectangle(sel_start_cursor.x, offset, + paperwidth - sel_start_cursor.x, + row_ptr->height, + LColor::selection); + else + pain.fillRectangle(0, offset, + sel_start_cursor.x, + row_ptr->height, + LColor::selection); } else if (sel_end_cursor.row == row_ptr) { - scr.fillRectangle(gc_selection, 0, offset, - sel_end_cursor.x, row_ptr->height); - } else if (y > sel_start_cursor.y && y < sel_end_cursor.y) { - scr.fillRectangle(gc_selection, 0, offset, - paperwidth, row_ptr->height); + if (direction == LYX_DIR_LEFT_TO_RIGHT) + pain.fillRectangle(0, offset, + sel_end_cursor.x, + row_ptr->height, + LColor::selection); + else + pain.fillRectangle(sel_end_cursor.x, offset, + paperwidth - sel_end_cursor.x, + row_ptr->height, + LColor::selection); + } else if (y > sel_start_cursor.y && y < sel_end_cursor.y) { + pain.fillRectangle(0, offset, + paperwidth, row_ptr->height, + LColor::selection); } - } // end of NOT FAST SELECTION code + } if (row_ptr->par->appendix){ - scr.drawVerticalLine(gc_math, 1, offset, offset+row_ptr->height); - scr.drawVerticalLine(gc_math, paperwidth-2 , offset, offset+row_ptr->height); + pain.line(1, offset, + 1, offset + row_ptr->height, + LColor::appendixline); + pain.line(paperwidth - 2, offset, + paperwidth - 2, offset + row_ptr->height, + LColor::appendixline); } - + if (row_ptr->par->pextra_type == LyXParagraph::PEXTRA_MINIPAGE) { /* draw a marker at the left margin! */ LyXFont font = GetFont(row_ptr->par, 0); @@ -3264,13 +3724,12 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, int x = (LYX_PAPER_MARGIN - font.width('|')) / 2; int y1 = (offset + row_ptr->baseline); int y2 = (offset + row_ptr->baseline) - asc; - - scr.drawVerticalLine(gc_minipage, x, y1, y2); + pain.line(x, y1, x, y2, LColor::minipageline); } if (row_ptr->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { LyXFont font(LyXFont::ALL_SANE); font.setSize(LyXFont::SIZE_FOOTNOTE); - font.setColor(LyXFont::RED); + font.setColor(LColor::footnote); int box_x = LYX_PAPER_MARGIN; box_x += font.textWidth(" wide-tab ", 10); @@ -3301,67 +3760,64 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, break; } - // Determine background color. - gc_type back = gc_lighted; - if (mono_video) { - back = gc_clear; - } - scr.fillRectangle(back, LYX_PAPER_MARGIN, offset+1, - box_x - LYX_PAPER_MARGIN, - int(font.maxAscent())+ - int(font.maxDescent())); + pain.fillRectangle(LYX_PAPER_MARGIN, + offset + 1, + box_x - LYX_PAPER_MARGIN, + int(font.maxAscent() + + font.maxDescent()), + LColor::footnotebg); + + pain.line(LYX_PAPER_MARGIN, offset, + paperwidth - LYX_PAPER_MARGIN, offset, + LColor::footnoteframe); - scr.drawLine(gc_foot, - offset, - LYX_PAPER_MARGIN, - paperwidth - 2*LYX_PAPER_MARGIN); + pain.text(LYX_PAPER_MARGIN, + offset + int(font.maxAscent()) + 1, + fs, font); - scr.drawString(font, fs, - offset + int(font.maxAscent())+1, - LYX_PAPER_MARGIN); - scr.drawVerticalLine(gc_foot, - LYX_PAPER_MARGIN, - offset, - offset - + int(font.maxAscent())+ - int(font.maxDescent())); + pain.line(LYX_PAPER_MARGIN, offset, + LYX_PAPER_MARGIN, + offset + int(font.maxAscent() + + font.maxDescent()), + LColor::footnoteframe); + + pain.line(LYX_PAPER_MARGIN, + offset + int(font.maxAscent() + + font.maxDescent()) + 1, + box_x, + offset + int(font.maxAscent() + + font.maxDescent()) + 1, + LColor::footnoteframe); - scr.drawLine(gc_foot, - offset - + int(font.maxAscent()) - + int(font.maxDescent()) + 1, - LYX_PAPER_MARGIN, box_x - LYX_PAPER_MARGIN); } /* draw the open floats in a red box */ - scr.drawVerticalLine(gc_foot, - box_x, - offset, offset + row_ptr->height); - - scr.drawVerticalLine(gc_foot, - paperwidth - LYX_PAPER_MARGIN, - offset, - offset + row_ptr->height); - + pain.line(box_x, offset, + box_x, offset + row_ptr->height, + LColor::footnoteframe); - } else { - if (row_ptr->previous && - row_ptr->previous->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { - LyXFont font(LyXFont::ALL_SANE); - font.setSize(LyXFont::SIZE_FOOTNOTE); - - int box_x = LYX_PAPER_MARGIN; - box_x += font.textWidth(" wide-tab ", 10); - - scr.drawLine(gc_foot, - offset, - box_x, - paperwidth - LYX_PAPER_MARGIN - box_x); - } + pain.line(paperwidth - LYX_PAPER_MARGIN, + offset, + paperwidth - LYX_PAPER_MARGIN, + offset + row_ptr->height, + LColor::footnoteframe); + } else if (row_ptr->previous && + row_ptr->previous->par->footnoteflag + == LyXParagraph::OPEN_FOOTNOTE) { + LyXFont font(LyXFont::ALL_SANE); + font.setSize(LyXFont::SIZE_FOOTNOTE); + + int box_x = LYX_PAPER_MARGIN; + box_x += font.textWidth(" wide-tab ", 10); + + pain.line(box_x, offset, + paperwidth - LYX_PAPER_MARGIN, + offset, LColor::footnote); } - LyXLayout const & layout = textclasslist.Style(parameters->textclass, - row_ptr->par->GetLayout()); + LyXLayout const & layout = + textclasslist.Style(parameters->textclass, + row_ptr->par->GetLayout()); firstpar = row_ptr->par->FirstPhysicalPar(); y_top = 0; @@ -3371,41 +3827,69 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, if (row_ptr->pos == 0 && row_ptr->par == firstpar) { - /* start of appendix? */ + /* start of appendix? */ if (row_ptr->par->start_of_appendix){ - scr.drawLine(gc_math, - offset, - 1, paperwidth-2); + pain.line(1, offset, + paperwidth - 2, offset, + LColor::appendixline); } - + /* think about the margins */ if (!row_ptr->previous) y_top += LYX_PAPER_MARGIN; if (row_ptr->par->pagebreak_top){ /* draw a top pagebreak */ - scr.drawOnOffLine(offset + y_top + 2 * DefaultHeight(), - 0, paperwidth); +#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(); } if (row_ptr->par->added_space_top.kind() == VSpace::VFILL) { /* draw a vfill top */ - scr.drawLine(gc_fill, - offset + 2 + y_top, - 0, LYX_PAPER_MARGIN); - scr.drawLine(gc_fill, - offset + y_top + 3 * DefaultHeight(), - 0, LYX_PAPER_MARGIN); - scr.drawVerticalOnOffLine(LYX_PAPER_MARGIN / 2, - offset + 2 + y_top, - offset + y_top + 3 * - DefaultHeight()); + pain.line(0, offset + 2 + y_top, + LYX_PAPER_MARGIN, offset + 2 + y_top, + LColor::vfillline); + + pain.line(0, offset + y_top + 3 * DefaultHeight(), + LYX_PAPER_MARGIN, + offset + y_top + 3 * DefaultHeight(), + LColor::vfillline); + + pain.line(LYX_PAPER_MARGIN / 2, offset + 2 + y_top, + LYX_PAPER_MARGIN / 2, + offset + y_top + 3 * DefaultHeight(), + LColor::vfillline); y_top += 3 * DefaultHeight(); } /* think about user added space */ - y_top += int(row_ptr->par->added_space_top.inPixels()); + y_top += int(row_ptr->par->added_space_top.inPixels(owner_)); /* think about the parskip */ /* some parskips VERY EASY IMPLEMENTATION */ @@ -3413,20 +3897,24 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, if (layout.latextype == LATEX_PARAGRAPH && firstpar->GetDepth() == 0 && firstpar->Previous()) - y_top += parameters->getDefSkip().inPixels(); + y_top += parameters->getDefSkip().inPixels(owner_); else if (firstpar->Previous() && textclasslist.Style(parameters->textclass, - firstpar->Previous()->GetLayout()).latextype == LATEX_PARAGRAPH + firstpar->Previous()->GetLayout()).latextype == LATEX_PARAGRAPH && firstpar->Previous()->GetDepth() == 0) // is it right to use defskip here, too? (AS) - y_top += parameters->getDefSkip().inPixels(); + y_top += parameters->getDefSkip().inPixels(owner_); } if (row_ptr->par->line_top) { /* draw a top line */ y_top += GetFont(row_ptr->par, 0).ascent('x'); - - scr.drawThickLine(offset + y_top, - 0, paperwidth); + + pain.line(0, offset + y_top, + paperwidth, offset + y_top, + LColor::topline, + Painter::line_solid, + Painter::line_thick); + y_top += GetFont(row_ptr->par, 0).ascent('x'); } @@ -3446,19 +3934,31 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, * an extra row and has a pagebreak at the top. */ maxdesc = int(font.maxDescent() * layout.spacing.getValue() * parameters->spacing.getValue()) + int(layout.parsep) * DefaultHeight(); - scr.drawString(font, tmpstring, - offset + row_ptr->baseline - - row_ptr->ascent_of_text - maxdesc, - int(x)); + if (direction == LYX_DIR_RIGHT_TO_LEFT) + tmpx = paperwidth - LeftMargin(row_ptr) - + font.stringWidth(tmpstring); + pain.text(int(tmpx), + offset + row_ptr->baseline - row_ptr->ascent_of_text - maxdesc, + tmpstring, font); } } else { - x -= font.stringWidth( layout.labelsep); - x -= font.stringWidth( tmpstring); + if (direction == LYX_DIR_LEFT_TO_RIGHT) + tmpx = x - font.stringWidth(layout.labelsep) + - font.stringWidth(tmpstring); + else { + tmpx = paperwidth - LeftMargin(row_ptr) + + font.stringWidth(layout.labelsep); + if (row_ptr->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { + LyXFont font(LyXFont::ALL_SANE); + font.setSize(LyXFont::SIZE_SMALL); + tmpx += font.textWidth("Mwide-figM", 10); + } + } /* draw it! */ - scr.drawString(font, tmpstring, - offset + row_ptr->baseline, int(x)); + pain.text(int(tmpx), + offset + row_ptr->baseline, + tmpstring, font); } - x = tmpx; } /* the labels at the top of an environment. More or less for bibliography */ } else if (layout.labeltype == LABEL_TOP_ENVIRONMENT || @@ -3470,33 +3970,38 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, string tmpstring = row_ptr->par->GetLabestring(); maxdesc = int(font.maxDescent() * layout.spacing.getValue() * parameters->spacing.getValue() - + (layout.labelbottomsep * DefaultHeight())); + + (layout.labelbottomsep * DefaultHeight())); - int top_label_x = int(x); + tmpx = x; if (layout.labeltype == LABEL_CENTERED_TOP_ENVIRONMENT){ - top_label_x = int(x + (paperwidth - RightMargin(row_ptr) - x) / 2); - top_label_x -= (font.stringWidth( tmpstring)/2); - } - - scr.drawString(font, tmpstring, - offset + row_ptr->baseline - - row_ptr->ascent_of_text - maxdesc, - top_label_x); + tmpx = ( ((direction == LYX_DIR_LEFT_TO_RIGHT) + ? x : LeftMargin(row_ptr) ) + + paperwidth - RightMargin(row_ptr) ) / 2; + tmpx -= (font.stringWidth(tmpstring)/2); + } else if (direction == LYX_DIR_RIGHT_TO_LEFT) + tmpx = paperwidth - LeftMargin(row_ptr) - + font.stringWidth(tmpstring); + pain.text(int(tmpx), + offset + row_ptr->baseline + - row_ptr->ascent_of_text + - maxdesc, + tmpstring, font); } } } - if (layout.labeltype == LABEL_BIBLIO) { // ale970302 - if (row_ptr->par->bibkey) { - tmpx = x; - x -= font.stringWidth(layout.labelsep); - font = GetFont(row_ptr->par, -1); - x -= row_ptr->par->bibkey->Width(font); - row_ptr->par->bibkey->Draw(font, scr, - offset + row_ptr->baseline, - x); - x = tmpx; - } - } + if (layout.labeltype == LABEL_BIBLIO && row_ptr->par->bibkey) { + font = GetFont(row_ptr->par, -1); + if (direction == LYX_DIR_LEFT_TO_RIGHT) + tmpx = x - font.stringWidth(layout.labelsep) + - row_ptr->par->bibkey->width(owner_->painter(), font); + else + tmpx = paperwidth - LeftMargin(row_ptr) + + font.stringWidth(layout.labelsep); + row_ptr->par->bibkey->draw(owner_->painter(), + font, + offset + row_ptr->baseline, + tmpx); + } } /* is it a last row? */ @@ -3510,43 +4015,107 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, /* draw a bottom pagebreak */ if (firstpar->pagebreak_bottom) { - scr.drawOnOffLine(offset + y_bottom - 2 * - DefaultHeight(), - 0, paperwidth); +#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(); } if (firstpar->added_space_bottom.kind() == VSpace::VFILL) { /* draw a vfill bottom */ - scr.drawLine(gc_fill, - offset + y_bottom - 3 * DefaultHeight(), - 0, LYX_PAPER_MARGIN); - scr.drawLine(gc_fill, offset + y_bottom - 2, - 0, LYX_PAPER_MARGIN); - scr.drawVerticalOnOffLine(LYX_PAPER_MARGIN / 2, - offset + y_bottom - 3 * DefaultHeight(), - offset + y_bottom - 2 - ); + pain.line(0, offset + y_bottom - 3 * DefaultHeight(), + LYX_PAPER_MARGIN, + offset + y_bottom - 3 * DefaultHeight(), + LColor::vfillline); + pain.line(0, offset + y_bottom - 2, + LYX_PAPER_MARGIN, + offset + y_bottom - 2, + LColor::vfillline); + pain.line(LYX_PAPER_MARGIN / 2, + offset + y_bottom - 3 * DefaultHeight(), + LYX_PAPER_MARGIN / 2, + offset + y_bottom - 2, + LColor::vfillline); y_bottom -= 3* DefaultHeight(); } /* think about user added space */ - y_bottom -= int(firstpar->added_space_bottom.inPixels()); + y_bottom -= int(firstpar->added_space_bottom.inPixels(owner_)); if (firstpar->line_bottom) { /* draw a bottom line */ y_bottom -= GetFont(par, par->Last() - 1).ascent('x'); - - scr.drawThickLine(offset + y_bottom, - 0, paperwidth); + pain.line(0, offset + y_bottom, + paperwidth, offset + y_bottom, + LColor::topline, Painter::line_solid, + 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 */ pos_end = RowLast(row_ptr); - pos = row_ptr->pos; + vpos = row_ptr->pos; /* table stuff -- begin*/ if (row_ptr->par->table) { bool on_off; @@ -3554,7 +4123,8 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, float x_old = x; x += row_ptr->par->table->GetBeginningOfTextInCell(cell); - while (pos <= pos_end) { + while (vpos <= pos_end) { + pos = vis2log(vpos); if (row_ptr->par->IsNewline(pos)) { x = x_old + row_ptr->par->table->WidthOfColumn(cell); @@ -3563,76 +4133,100 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, if ((!on_off || !row_ptr->par->table->TopAlreadyDrawed(cell)) && !row_ptr->par->table->IsContRow(cell)) - scr.drawTableLine(offset + row_ptr->baseline - - row_ptr->ascent_of_text, - int(x_old), int(x - x_old), on_off); + pain.line(int(x_old), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + LColor::tableline, + on_off ? Painter::line_onoffdash : Painter::line_solid); + on_off = !row_ptr->par->table->BottomLine(cell); if ((!on_off && !row_ptr->par->table->RowHasContRow(cell)) || row_ptr->par->table->VeryLastRow(cell)) - scr.drawTableLine(offset + y_bottom - 1, - int(x_old), int(x - x_old), on_off); + + pain.line(int(x_old), + offset + y_bottom - 1, + int(x), + offset + y_bottom - 1, + LColor::tableline, + on_off ? Painter::line_onoffdash : Painter::line_solid); + on_off = !row_ptr->par->table->LeftLine(cell); - scr.drawVerticalTableLine(int(x_old), - offset + row_ptr->baseline - - row_ptr->ascent_of_text, - offset + y_bottom - 1, - on_off); + pain.line(int(x_old), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x_old), + offset + y_bottom - 1, + LColor::tableline, + on_off ? Painter::line_onoffdash : Painter::line_solid); + on_off = !row_ptr->par->table->RightLine(cell); - scr.drawVerticalTableLine(int(x) - - row_ptr->par->table->AdditionalWidth(cell), - offset + row_ptr->baseline - - row_ptr->ascent_of_text, - offset + y_bottom - 1, - on_off); + pain.line(int(x) - row_ptr->par->table->AdditionalWidth(cell), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x) - row_ptr->par->table->AdditionalWidth(cell), + offset + y_bottom - 1, + LColor::tableline, + on_off ? Painter::line_onoffdash : Painter::line_solid); + x_old = x; - /* take care about the alignment and other spaces */ - cell++; + /* take care about the alignment and other spaces */ + ++cell; x += row_ptr->par->table->GetBeginningOfTextInCell(cell); if (row_ptr->par->table->IsFirstCell(cell)) - cell--; // little hack, sorry - pos++; + --cell; // little hack, sorry + ++vpos; } else if (row_ptr->par->IsHfill(pos)) { x += 1; - scr.drawVerticalLine(gc_fill, int(x), - offset + row_ptr->baseline - DefaultHeight()/2, - offset + row_ptr->baseline); + pain.line(int(x), + offset + row_ptr->baseline - DefaultHeight() / 2, + int(x), + offset + row_ptr->baseline, + LColor::vfillline); + x += 2; - pos++; - } else { - if (row_ptr->par->IsSeparator(pos)) { - tmpx = x; - x+= SingleWidth(row_ptr->par, pos); - /* -------> Only draw protected spaces when not in - * free-spacing mode. */ - if (row_ptr->par->GetChar(pos) == LyXParagraph::META_PROTECTED_SEPARATOR && !layout.free_spacing) { - scr.drawVerticalLine(gc_fill, int(tmpx), - offset + row_ptr->baseline - 3, - offset + row_ptr->baseline - 1); - scr.drawLine(gc_fill, - offset + row_ptr->baseline - 1, - int(tmpx), - int(x-tmpx-2)); - scr.drawVerticalLine(gc_fill, int(x-2), - offset + row_ptr->baseline - 3, - offset + row_ptr->baseline - 1); - /* what about underbars? */ - font = GetFont(row_ptr->par, pos); - if (font.underbar() == LyXFont::ON - && font.latex() != LyXFont::ON) { - scr.drawLine(gc_copy, - offset + - row_ptr->baseline + 2, - int(tmpx), - int(x - tmpx)); - } + ++vpos; + } else if (row_ptr->par->IsSeparator(pos)) { + tmpx = x; + x+= SingleWidth(row_ptr->par, pos); +#warning Think about this. +#if 0 + /* -------> Only draw protected spaces when + * not in free-spacing mode. */ + if (row_ptr->par->GetChar(pos) == LyXParagraph::META_PROTECTED_SEPARATOR && !layout.free_spacing) { + pain.line(int(tmpx), + offset + row_ptr->baseline - 3, + int(tmpx), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + pain.line(int(tmpx), + offset + row_ptr->baseline - 1, + int(x - 2), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + pain.line(int(x - 2), + offset + row_ptr->baseline - 3, + int(x - 2), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + /* what about underbars? */ + font = GetFont(row_ptr->par, pos); + if (font.underbar() == LyXFont::ON + && font.latex() != LyXFont::ON) { + pain.line(int(tmpx), + offset + row_ptr->baseline + 2, + int(x - tmpx), + offset + row_ptr->baseline + 2); } - pos++; - } else - Draw(row_ptr, pos, scr, offset, x); - } + } +#endif + ++vpos; + } else + draw(row_ptr, vpos, offset, x); } /* do not forget the very last cell. This has no NEWLINE so @@ -3644,136 +4238,142 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, !row_ptr->par->table->TopAlreadyDrawed(cell)) && !row_ptr->par->table->IsContRow(cell)) - scr.drawTableLine(offset + row_ptr->baseline - - row_ptr->ascent_of_text, - int(x_old), int(x - x_old), on_off); + pain.line(int(x_old), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + LColor::tableline, + on_off ? Painter::line_onoffdash : Painter::line_solid); on_off = !row_ptr->par->table->BottomLine(cell); if ((!on_off && !row_ptr->par->table->RowHasContRow(cell)) || row_ptr->par->table->VeryLastRow(cell)) - scr.drawTableLine(offset + y_bottom - 1, - int(x_old), int(x - x_old), on_off); + pain.line(int(x_old), + offset + y_bottom - 1, + int(x), + offset + y_bottom - 1, + LColor::tableline, + on_off ? Painter::line_onoffdash : Painter::line_solid); + on_off = !row_ptr->par->table->LeftLine(cell); - scr.drawVerticalTableLine(int(x_old), - offset + row_ptr->baseline - - row_ptr->ascent_of_text, - offset + y_bottom - 1, - on_off); + pain.line(int(x_old), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x_old), + offset + y_bottom - 1, + LColor::tableline, + on_off ? Painter::line_onoffdash : Painter::line_solid); + on_off = !row_ptr->par->table->RightLine(cell); - scr.drawVerticalTableLine(int(x) - - row_ptr->par->table->AdditionalWidth(cell), - offset + row_ptr->baseline - - row_ptr->ascent_of_text, - offset + y_bottom - 1, - on_off); + pain.line(int(x) - row_ptr->par->table->AdditionalWidth(cell), + offset + row_ptr->baseline - row_ptr->ascent_of_text, + int(x) - row_ptr->par->table->AdditionalWidth(cell), + offset + y_bottom - 1, + LColor::tableline, + on_off ? Painter::line_onoffdash : Painter::line_solid); } } else { /* table stuff -- end*/ + LyXParagraph::size_type main_body = + BeginningOfMainBody(row_ptr->par); + if (main_body > 0 && + (main_body-1 > pos_end || + !row_ptr->par->IsLineSeparator(main_body-1))) + main_body = 0; - while (pos <= pos_end) { + while (vpos <= pos_end) { + pos = vis2log(vpos); + if (main_body > 0 && pos == main_body-1) { + x += fill_label_hfill + + GetFont(row_ptr->par, -2).stringWidth(layout.labelsep) + - SingleWidth(row_ptr->par, main_body-1); + } if (row_ptr->par->IsHfill(pos)) { x += 1; - scr.drawVerticalLine(gc_fill, int(x), - offset + row_ptr->baseline - DefaultHeight()/2, - offset + row_ptr->baseline); + pain.line(int(x), + offset + row_ptr->baseline - DefaultHeight() / 2, + int(x), + offset + row_ptr->baseline, + LColor::vfillline); + if (HfillExpansion(row_ptr, pos)) { if (pos >= main_body) { - scr.drawOnOffLine(offset + row_ptr->baseline - - DefaultHeight()/4, - int(x), - int(fill_hfill)); + pain.line(int(x), + offset + row_ptr->baseline - DefaultHeight() / 4, + int(x + fill_hfill), + offset + row_ptr->baseline - DefaultHeight() / 4, + LColor::vfillline, + Painter::line_onoffdash); x += fill_hfill; - } else { - scr.drawOnOffLine(offset + row_ptr->baseline - - DefaultHeight()/4, - int(x), - int(fill_label_hfill)); - x += fill_label_hfill; - } - scr.drawVerticalLine(gc_fill, int(x), - offset + row_ptr->baseline - - DefaultHeight()/2, - offset + row_ptr->baseline); + } else { + pain.line(int(x), + offset + row_ptr->baseline - DefaultHeight() / 4, + int(x + fill_label_hfill), + offset + row_ptr->baseline - DefaultHeight() / 4, + LColor::vfillline, + Painter::line_onoffdash); + + x += fill_label_hfill; + } + pain.line(int(x), + offset + row_ptr->baseline - DefaultHeight() / 2, + int(x), + offset + row_ptr->baseline, + LColor::vfillline); } x += 2; - pos++; - } else { - if (row_ptr->par->IsSeparator(pos)) { - tmpx = x; - x+= SingleWidth(row_ptr->par, pos); - if (pos >= main_body) - x+= fill_separator; - /* -------> Only draw protected spaces when not in - * free-spacing mode. */ - if (row_ptr->par->GetChar(pos) == LyXParagraph::META_PROTECTED_SEPARATOR && !layout.free_spacing) { - - scr.drawVerticalLine(gc_fill, int(tmpx), - offset + row_ptr->baseline - 3, - offset + row_ptr->baseline - 1); - scr.drawLine(gc_fill, - offset + row_ptr->baseline - 1, - int(tmpx), - int(x-tmpx-2)); - scr.drawVerticalLine(gc_fill, int(x-2), - offset + row_ptr->baseline - 3, - offset + row_ptr->baseline - 1); - /* what about underbars? */ - font = GetFont(row_ptr->par, pos); - if (font.underbar() == LyXFont::ON - && font.latex() != LyXFont::ON) { - scr.drawLine(gc_copy, - offset + row_ptr->baseline + 2, - int(tmpx), - int(x - tmpx)); - } + ++vpos; + } else if (row_ptr->par->IsSeparator(pos)) { + tmpx = x; + x+= SingleWidth(row_ptr->par, pos); + if (pos >= main_body) + x+= fill_separator; +#warning Think about this +#if 0 + /* -------> Only draw protected spaces when + * not in free-spacing mode. */ + if (row_ptr->par->GetChar(pos) == LyXParagraph::META_PROTECTED_SEPARATOR && !layout.free_spacing) { + + pain.line(int(tmpx), + offset + row_ptr->baseline - 3, + int(tmpx), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + pain.line(int(tmpx), + offset + row_ptr->baseline - 1, + int(x - 2), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + pain.line(int(x - 2), + offset + row_ptr->baseline - 3, + int(x - 2), + offset + row_ptr->baseline - 1, + LColor::vfillline); + + /* what about underbars? */ + font = GetFont(row_ptr->par, pos); + if (font.underbar() == LyXFont::ON + && font.latex() != LyXFont::ON) { + pain.line(int(tmpx), + offset + row_ptr->baseline + 2, + int(x - tmpx), + offset + row_ptr->baseline + 2); } - pos++; - } else - Draw(row_ptr, pos, scr, offset, x); - } - if (pos == main_body) { - x += GetFont(row_ptr->par, -2).stringWidth( - layout.labelsep); - if (row_ptr->par->IsLineSeparator(pos - 1)) - x-= SingleWidth(row_ptr->par, pos - 1); - if (x < left_margin) - x = left_margin; - } - } - } - // check for FAST SELECTION - if (fast_selection || mono_video){ - if (selection) { - - /* selection code */ - if (sel_start_cursor.row == row_ptr && sel_end_cursor.row == row_ptr) { - scr.fillRectangle(gc_select, sel_start_cursor.x, offset, - sel_end_cursor.x - sel_start_cursor.x, - row_ptr->height); - } else if (sel_start_cursor.row == row_ptr) { - scr.fillRectangle(gc_select, sel_start_cursor.x, offset, - paperwidth - sel_start_cursor.x, - row_ptr->height); - } else if (sel_end_cursor.row == row_ptr) { - scr.fillRectangle(gc_select, 0, offset, - sel_end_cursor.x, - row_ptr->height); - } else if (y > sel_start_cursor.y && y < sel_end_cursor.y) { - scr.fillRectangle(gc_select, 0, offset, - paperwidth, row_ptr->height); - - } + } +#endif + ++vpos; + } else + draw(row_ptr, vpos, offset, x); } } -// end of FAST SELECTION code - /* thats it */ } -int LyXText::DefaultHeight() +int LyXText::DefaultHeight() const { LyXFont font(LyXFont::ALL_SANE); return int(font.maxAscent() + font.maxDescent() * 1.5); @@ -3782,61 +4382,66 @@ int LyXText::DefaultHeight() /* returns the column near the specified x-coordinate of the row * x is set to the real beginning of this column */ -int LyXText::GetColumnNearX(Row * row, int& x) +int LyXText::GetColumnNearX(Row * row, int & x) const { float tmpx = 0.0; float fill_separator, fill_hfill, fill_label_hfill; - int left_margin = LabelEnd(row); PrepareToPrint(row, tmpx, fill_separator, fill_hfill, fill_label_hfill); - int main_body = BeginningOfMainBody(row->par); - - int c = row->pos; - int last = RowLast(row); - if (row->par->IsNewline(last)) - last--; - + LyXDirection direction = row->par->getParDirection(); + LyXParagraph::size_type vc = row->pos; + LyXParagraph::size_type last = RowLast(row); + LyXParagraph::size_type c = 0; + LyXLayout const & layout = textclasslist.Style(parameters->textclass, - row->par->GetLayout()); + row->par->GetLayout()); /* table stuff -- begin */ if (row->par->table) { - if (!row->next || row->next->par != row->par) - last = RowLast(row); /* the last row doesn't need a newline at the end*/ + if (row->next && row->next->par == row->par //the last row doesn't need a newline at the end + && row->par->IsNewline(last)) + last--; int cell = NumberOfCell(row->par, row->pos); float x_old = tmpx; bool ready = false; tmpx += row->par->table->GetBeginningOfTextInCell(cell); - while (c <= last + while (vc <= last + && (c = vis2log(vc)) >= 0 && tmpx + (SingleWidth(row->par, c)/2) <= x && !ready){ if (row->par->IsNewline(c)) { if (x_old + row->par->table->WidthOfColumn(cell) <= x){ tmpx = x_old + row->par->table->WidthOfColumn(cell); x_old = tmpx; - cell++; + ++cell; tmpx += row->par->table->GetBeginningOfTextInCell(cell); - c++; + ++vc; } else ready = true; } else { tmpx += SingleWidth(row->par, c); - c++; + ++vc; } } - } else + } else { /* table stuff -- end*/ - - while (c <= last - && tmpx + (SingleWidth(row->par, c)/2) <= x) { - - if (c && c == main_body - && !row->par->IsLineSeparator(c - 1)) { - tmpx += GetFont(row->par, -2) - .stringWidth(layout.labelsep); - if (tmpx < left_margin) - tmpx = left_margin; + LyXParagraph::size_type main_body = BeginningOfMainBody(row->par); + float last_tmpx = tmpx; + + if (main_body > 0 && + (main_body-1 > last || + !row->par->IsLineSeparator(main_body-1))) + main_body = 0; + + while (vc <= last && tmpx <= x) { + c = vis2log(vc); + last_tmpx = tmpx; + if (main_body > 0 && c == main_body-1) { + tmpx += fill_label_hfill + + GetFont(row->par, -2).stringWidth(layout.labelsep); + if (row->par->IsLineSeparator(main_body-1)) + tmpx -= SingleWidth(row->par, main_body-1); } tmpx += SingleWidth(row->par, c); @@ -3850,25 +4455,55 @@ int LyXText::GetColumnNearX(Row * row, int& x) && row->par->IsSeparator(c)) { tmpx+= fill_separator; } - c++; - if (c == main_body - && row->par->IsLineSeparator(c - 1)) { - tmpx += GetFont(row->par, -2) - .stringWidth(layout.labelsep); - tmpx-= SingleWidth(row->par, c - 1); - if (tmpx < left_margin) - tmpx = left_margin; - } + ++vc; + } + + if (vc > row->pos && (tmpx+last_tmpx)/2 > x) { + vc--; + tmpx = last_tmpx; } + } /* make sure that a last space in a row doesnt count */ - if (c > 0 && c >= last - && row->par->IsLineSeparator(c - 1) - && !(!row->next || row->next->par != row->par)) { - tmpx -= SingleWidth(row->par, c - 1); - tmpx -= fill_separator; + if (row->pos <= last + && !(!row->next || row->next->par != row->par)) + if (direction == LYX_DIR_LEFT_TO_RIGHT && vc > last + && row->par->IsLineSeparator(vis2log(last)) ) { + vc = last; + tmpx -= fill_separator+SingleWidth(row->par, vis2log(last)); + } else if (direction == LYX_DIR_RIGHT_TO_LEFT + && vc == row->pos + && row->par->IsLineSeparator(vis2log(row->pos)) ) { + 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 || + (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) + && row->par->getLetterDirection(vis2log(vc - 1)) != direction) + c = vis2log(vc-1); + if (direction == LYX_DIR_RIGHT_TO_LEFT) + ++c; } - c-= row->pos; - + + if (!row->par->table && row->pos <= last && c > last + && row->par->IsNewline(last)) { + if (row->par->getLetterDirection(last) == LYX_DIR_LEFT_TO_RIGHT) + tmpx -= SingleWidth(row->par, last); + else + tmpx += SingleWidth(row->par, last); + c = last; + } + + c -= row->pos; x = int(tmpx); return c; } @@ -3976,11 +4611,17 @@ void LyXText::InsertFootnoteEnvironment(LyXParagraph::footnote_kind kind) || kind == LyXParagraph::WIDE_TAB || kind == LyXParagraph::WIDE_FIG || kind == LyXParagraph::ALGORITHM) { - int lay = textclasslist.NumberOfLayout(parameters->textclass, - "Caption").second; - if (lay == -1) // layout not found - // use default layout "Standard" (0) - lay = 0; + pair lres = + textclasslist.NumberOfLayout(parameters->textclass, + "Caption"); + LyXTextClass::size_type lay; + if (lres.first) { + // layout fount + lay = lres.second; + } else { + // layout not found + lay = 0; // use default layout "Standard" (0) + } tmppar->SetLayout(lay); } } @@ -4011,61 +4652,77 @@ void LyXText::InsertFootnoteEnvironment(LyXParagraph::footnote_kind kind) } -/* returns pointer to a specified row */ -Row * LyXText::GetRow(LyXParagraph * par, LyXParagraph::size_type pos, long &y) +// returns pointer to a specified row +Row * LyXText::GetRow(LyXParagraph * par, + LyXParagraph::size_type pos, long & y) const { - Row * tmprow; - - if (currentrow){ - if (par == currentrow->par || par == currentrow->par->Previous()){ - // do not dereference par, it may have been deleted - // already! (Matthias) - while (currentrow->previous && currentrow->previous->par != par){ - currentrow = currentrow->previous; - currentrow_y -= currentrow->height; - } - while (currentrow->previous && currentrow->previous->par == par){ - currentrow = currentrow->previous; - currentrow_y -= currentrow->height; - } - } - tmprow = currentrow; - y = currentrow_y; - /* find the first row of the specified paragraph */ - while (tmprow->next && (tmprow->par != par)) { - y += tmprow->height; - tmprow = tmprow->next; - } + Row * tmprow; - if (tmprow->par == par){ - /* now find the wanted row */ - while (tmprow->pos < pos && tmprow->next && tmprow->next->par == par && - tmprow->next->pos <= pos) { - y += tmprow->height; - tmprow = tmprow->next; - } - currentrow = tmprow; - currentrow_y = y; - return tmprow; - } - } - tmprow = firstrow; - y = 0; - /* find the first row of the specified paragraph */ - while (tmprow->next && (tmprow->par != par)) { - y += tmprow->height; - tmprow = tmprow->next; - } - - /* now find the wanted row */ - while (tmprow->pos < pos && tmprow->next && tmprow->next->par == par && - tmprow->next->pos <= pos) { - y += tmprow->height; - tmprow = tmprow->next; - } - - currentrow = tmprow; - currentrow_y = y; + if (currentrow) { + if (par == currentrow->par + || par == currentrow->par->Previous()) { + // do not dereference par, it may have been deleted + // already! (Matthias) + + // Walk backwards as long as the previous + // rows par is not par + while (currentrow->previous + && currentrow->previous->par != par) { + currentrow = currentrow->previous; + currentrow_y -= currentrow->height; + } + // Walk backwards as long as the previous + // rows par _is_ par + while (currentrow->previous + && currentrow->previous->par == par) { + currentrow = currentrow->previous; + currentrow_y -= currentrow->height; + } + } + + tmprow = currentrow; + y = currentrow_y; + // find the first row of the specified paragraph + while (tmprow->next + && tmprow->par != par) { + y += tmprow->height; + tmprow = tmprow->next; + } + + if (tmprow->par == par){ + // now find the wanted row + while (tmprow->pos < pos + && tmprow->next + && tmprow->next->par == par + && tmprow->next->pos <= pos) { + y += tmprow->height; + tmprow = tmprow->next; + } + currentrow = tmprow; + currentrow_y = y; + return tmprow; + } + } - return tmprow; + tmprow = firstrow; + y = 0; + // find the first row of the specified paragraph + while (tmprow->next && tmprow->par != par) { + y += tmprow->height; + tmprow = tmprow->next; + } + + // now find the wanted row + while (tmprow->pos < pos + && tmprow->next + && tmprow->next->par == par + && tmprow->next->pos <= pos) { + y += tmprow->height; + tmprow = tmprow->next; + } + + currentrow = tmprow; + currentrow_y = y; + + return tmprow; }