X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftext.C;h=c81fae1f9b3af9e3315795c7f73349b769992667;hb=91a2ea274e9c27f571a3cd4798d2e8ecc1b982a7;hp=abd212ef3cedb678a8955be5e51fdaf6a299cebe;hpb=5ba861bb096de90bd5c29c75626200958e3a5ca9;p=lyx.git diff --git a/src/text.C b/src/text.C index abd212ef3c..c81fae1f9b 100644 --- a/src/text.C +++ b/src/text.C @@ -4,7 +4,7 @@ * LyX, The Document Processor * * Copyright 1995 Matthias Ettrich - * Copyright 1995-1999 The LyX Team. + * Copyright 1995-2000 The LyX Team. * * ====================================================== */ @@ -31,20 +31,132 @@ #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 BufferView * current_view; -extern LyXRC * lyxrc; // ale070405 extern int bibitemMaxWidth(Painter &, LyXFont const &); #define FIX_DOUBLE_SPACE 1 +static int iso885968x[] = { + 0xbc, // 0xa8 = fathatan + 0xbd, // 0xa9 = dammatan + 0xbe, // 0xaa = kasratan + 0xdb, // 0xab = fatha + 0xdc, // 0xac = damma + 0xdd, // 0xad = kasra + 0xde, // 0xae = shadda + 0xdf, // 0xaf = sukun + + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xb0-0xbf + + 0, // 0xc0 + 0xc1, // 0xc1 = hamza + 0xc2, // 0xc2 = ligature madda + 0xc3, // 0xc3 = ligature hamza on alef + 0xc4, // 0xc4 = ligature hamza on waw + 0xc5, // 0xc5 = ligature hamza under alef + 0xc0, // 0xc6 = ligature hamza on ya + 0xc7, // 0xc7 = alef + 0xeb, // 0xc8 = baa + 0xc9, // 0xc9 = taa marbuta + 0xec, // 0xca = taa + 0xed, // 0xcb = thaa + 0xee, // 0xcc = jeem + 0xef, // 0xcd = haa + 0xf0, // 0xce = khaa + 0xcf, // 0xcf = dal + + 0xd0, // 0xd0 = thal + 0xd1, // 0xd1 = ra + 0xd2, // 0xd2 = zain + 0xf1, // 0xd3 = seen + 0xf2, // 0xd4 = sheen + 0xf3, // 0xd5 = sad + 0xf4, // 0xd6 = dad + 0xd7, // 0xd7 = tah + 0xd8, // 0xd8 = zah + 0xf5, // 0xd9 = ain + 0xf6, // 0xda = ghain + 0,0,0,0,0, // 0xdb- 0xdf + + 0, // 0xe0 + 0xf7, // 0xe1 = fa + 0xf8, // 0xe2 = qaf + 0xf9, // 0xe3 = kaf + 0xfa, // 0xe4 = lam + 0xfb, // 0xe5 = meem + 0xfc, // 0xe6 = noon + 0xfd, // 0xe7 = ha + 0xe8, // 0xe8 = waw + 0xe9, // 0xe9 = alef maksura + 0xfe // 0xea = ya +}; + +bool is_arabic(unsigned char c) +{ + return 0xa8 <= c && c <= 0xea && iso885968x[c-0xa8]; +} + +unsigned char LyXText::TransformChar(unsigned char c, Letter_Form form) const +{ + if (is_arabic(c) && + (form == FORM_INITIAL || form == FORM_MEDIAL) ) + return iso885968x[c-0xa8]; + else + return c; +} + +unsigned char LyXText::TransformChar(unsigned char c, LyXParagraph * par, + LyXParagraph::size_type pos) const +{ + if (!is_arabic(c)) + return c; + + bool not_first = (pos > 0 && is_arabic(par->GetChar(pos-1))); + if (pos < par->Last()-1 && is_arabic(par->GetChar(pos+1))) + if (not_first) + return TransformChar(c,FORM_MEDIAL); + else + return TransformChar(c,FORM_INITIAL); + else + if (not_first) + return TransformChar(c,FORM_FINAL); + else + return TransformChar(c,FORM_ISOLATED); +} + +// This is the comments that some of the warnings below refers to. +// There are some issues in this file and I don't think they are +// really related to the FIX_DOUBLE_SPACE patch. I'd rather think that +// this is a problem that has been here almost from day one and that a +// larger userbase with differenct access patters triggers the bad +// behaviour. (segfaults.) What I think happen is: In several places +// we store the paragraph in the current cursor and then moves the +// cursor. This movement of the cursor will delete paragraph at the +// old position if it is now empty. This will make the temporary +// pointer to the old cursor paragraph invalid and dangerous to use. +// And is some cases this will trigger a segfault. I have marked some +// of the cases where this happens with a warning, but I am sure there +// are others in this file and in text2.C. There is also a note in +// Delete() that you should read. In Delete I store the paragraph->id +// instead of a pointer to the paragraph. I am pretty sure this faulty +// use of temporary pointers to paragraphs that might have gotten +// invalidated (through a cursor movement) before they are used, are +// the cause of the strange crashes we get reported often. +// +// It is very tiresom to change this code, especially when it is as +// hard to read as it is. Help to fix all the cases where this is done +// would be greately appreciated. +// +// Lgb + int LyXText::SingleWidth(LyXParagraph * par, LyXParagraph::size_type pos) const { @@ -60,6 +172,8 @@ int LyXText::SingleWidth(LyXParagraph * par, // The most common case is handled first (Asger) if (IsPrintable(c)) { + if (lyxrc.rtl_support && lyxrc.font_norm == "iso8859-6.8x") + c = TransformChar(c, par, pos); return font.width(c); } else if (IsHfillChar(c)) { @@ -127,56 +241,13 @@ LyXParagraph::size_type LyXText::RowLast(Row const * row) const } -LyXDirection BufferParams::getDocumentDirection() const -{ - return (lyxrc->rtl_support && language == "hebrew") - ? LYX_DIR_RIGHT_TO_LEFT : LYX_DIR_LEFT_TO_RIGHT; -} - -LyXDirection LyXParagraph::getParDirection() const -{ - if (!lyxrc->rtl_support || table) - return LYX_DIR_LEFT_TO_RIGHT; - if (size() > 0) - return (getFont(0).direction() == LyXFont::RTL_DIR) - ? LYX_DIR_RIGHT_TO_LEFT : LYX_DIR_LEFT_TO_RIGHT; - else - return current_view->buffer()->params.getDocumentDirection(); -} - -LyXDirection LyXFont::getFontDirection() const -{ - if (lyxrc->rtl_support - && direction() == LyXFont::RTL_DIR - && latex() != LyXFont::ON) - return LYX_DIR_RIGHT_TO_LEFT; - else - return LYX_DIR_LEFT_TO_RIGHT; -} - -LyXDirection -LyXParagraph::getLetterDirection(LyXParagraph::size_type pos) const -{ - if (!lyxrc->rtl_support) - return LYX_DIR_LEFT_TO_RIGHT; - - LyXDirection direction = getFont(pos).getFontDirection(); - if (IsLineSeparator(pos) && 0 < pos && pos < Last() - 1 - && !IsLineSeparator(pos + 1) - && !(table && IsNewline(pos + 1)) - && (getFont(pos - 1).getFontDirection() != direction - || getFont(pos + 1).getFontDirection() != direction)) - return getParDirection(); - else - return direction; -} void LyXText::ComputeBidiTables(Row * row) const { - if (!lyxrc->rtl_support) { + if (!lyxrc.rtl_support) { bidi_start = -1; return; } @@ -250,10 +321,9 @@ void LyXText::ComputeBidiTablesFromTo(Row * row, } else { if (level == 0 || (level == 1 && direction == LYX_DIR_RIGHT_TO_LEFT - && row->par->getFont(lpos).direction() == - LyXFont::RTL_DIR - && row->par->getFont(lpos).latex() == - LyXFont::ON ) ) { + && row->par->getFont(lpos).isRightToLeft() + && row->par->getFont(lpos).latex() == LyXFont::ON + ) ) { // The last check is needed when the // char is a space stack[level++] = lpos; @@ -414,9 +484,10 @@ void LyXText::draw(Row const * row, return; } else if (c == LyXParagraph::META_INSET) { Inset * tmpinset = row->par->GetInset(pos); - if (tmpinset) + if (tmpinset) { tmpinset->draw(owner_->painter(), font, offset + row->baseline, x); + } ++vpos; return; } @@ -434,6 +505,9 @@ void LyXText::draw(Row const * row, // So IMHO we should go with the easier and clearer implementation. // And even if 1024 is a large number here it might overflow, string // will only overflow if the machine is out of memory... + bool do_transform = (lyxrc.rtl_support && lyxrc.font_norm == "iso8859-6.8x"); + if (do_transform) + c = TransformChar(c, row->par, pos); static string textstring; textstring = c; ++vpos; @@ -444,6 +518,8 @@ void LyXText::draw(Row const * row, (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; ++vpos; } @@ -633,7 +709,7 @@ int LyXText::LeftMargin(Row const * row) const 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(); + int xx = VSpace(row->par->pextra_width).inPixels(owner_); if (xx > paperwidth) xx = paperwidth * 80 / 100; @@ -644,7 +720,7 @@ int LyXText::LeftMargin(Row const * row) const } } - int align; + int align; // wrong type if (row->par->FirstPhysicalPar()->align == LYX_ALIGN_LAYOUT) align = layout.align; else @@ -834,7 +910,6 @@ LyXText::NextBreakPoint(Row const * row, int width) const // position of the last possible breakpoint // -1 isn't a suitable value, but a flag LyXParagraph::size_type last_separator = -1; - int left_margin = LabelEnd(row); width -= RightMargin(row); LyXParagraph::size_type main_body = BeginningOfMainBody(par); @@ -900,6 +975,7 @@ LyXText::NextBreakPoint(Row const * row, int width) const x += GetFont(par, -2).stringWidth(layout.labelsep); if (par->IsLineSeparator(i - 1)) x-= SingleWidth(par, i - 1); + int left_margin = LabelEnd(row); if (x < left_margin) x = left_margin; } @@ -953,9 +1029,7 @@ int LyXText::Fill(Row const * row, int paper_width) const * this point. */ } /* table stuff -- end*/ - - int left_margin = LabelEnd(row); - + // if the row ends with newline, this newline will not be relevant //if (last >= 0 && row->par->IsNewline(last)) // --last; @@ -987,6 +1061,7 @@ int LyXText::Fill(Row const * row, int paper_width) const stringWidth(layout.labelsep); if (row->par->IsLineSeparator(i - 1)) w -= SingleWidth(row->par, i - 1); + int left_margin = LabelEnd(row); if (w < left_margin) w = left_margin; } @@ -997,6 +1072,7 @@ int LyXText::Fill(Row const * row, int paper_width) const w += GetFont(row->par, -2).stringWidth(layout.labelsep); if (last >= 0 && row->par->IsLineSeparator(last)) w -= SingleWidth(row->par, last); + int left_margin = LabelEnd(row); if (w < left_margin) w = left_margin; } @@ -1049,11 +1125,6 @@ int LyXText::LabelFill(Row const * row) const int LyXText::NumberOfSeparators(Row const * row) const { int last = RowLast(row); - //int p = row->pos; - //int main_body = BeginningOfMainBody(row->par); - //if (p < main_body) - // p = main_body; - // I think this is equivalent to the above. (Lgb) int p = max(row->pos, BeginningOfMainBody(row->par)); int n = 0; for (; p < last; ++p) { @@ -1078,10 +1149,6 @@ int LyXText::NumberOfHfills(Row const * row) const ++first; } - //int main_body = BeginningOfMainBody(row->par); - //if (first < main_body) - // first = main_body; - // I think this is equivalent to the above. (Lgb) first = max(first, BeginningOfMainBody(row->par)); int n = 0; for (int p = first; p <= last; ++p) { // last, because the end is ignored! @@ -1103,11 +1170,7 @@ int LyXText::NumberOfLabelHfills(Row const * row) const while(first < last && row->par->IsHfill(first)) ++first; } - //LyXParagraph::size_type main_body = - //BeginningOfMainBody(row->par); - //if (last > main_body) - //last = main_body; - // I think this is eqvialent to the above. (Lgb) + last = min(last, BeginningOfMainBody(row->par)); int n = 0; for (LyXParagraph::size_type p = first; @@ -1259,13 +1322,13 @@ void LyXText::SetHeightOfRow(Row * row_ptr) const 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 */ @@ -1274,7 +1337,7 @@ void LyXText::SetHeightOfRow(Row * row_ptr) const /* 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 */ @@ -1371,7 +1434,7 @@ void LyXText::SetHeightOfRow(Row * row_ptr) const /* 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 */ @@ -1584,7 +1647,7 @@ void LyXText::BreakParagraph(char keep_layout) if (cursor.par->table) { int cell = NumberOfCell(cursor.par, cursor.pos); if (cursor.par->table->ShouldBeVeryLastCell(cell)) - SetCursor(cursor.par, cursor.par->text.size()); + SetCursor(cursor.par, cursor.par->size()); } /* table stuff -- end */ @@ -1687,7 +1750,7 @@ void LyXText::OpenFootnote() cursor.par->ParFromPos(cursor.pos) != par; cursor.pos++); /* now the cursor is at the beginning of the physical par */ SetCursor(cursor.par, - cursor.pos + cursor.par->ParFromPos(cursor.pos)->text.size()); + cursor.pos + cursor.par->ParFromPos(cursor.pos)->size()); /* the cursor must be exactly before the footnote */ par = cursor.par->ParFromPos(cursor.pos); @@ -1705,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) { @@ -1820,8 +1884,12 @@ void LyXText::TableFeatures(int feature) const /* insert the new cells */ int number = cursor.par->table->NumberOfCellsInRow(cell_org); - for (int i = 0; i < number; ++i) + Language const * lang = cursor.par->getParLanguage(); + LyXFont font(LyXFont::ALL_INHERIT,lang); + for (int i = 0; i < number; ++i) { cursor.par->InsertChar(pos, LyXParagraph::META_NEWLINE); + cursor.par->SetFont(pos, font); + } /* append the row into the table */ cursor.par->table->AppendRow(cell_org); @@ -1855,9 +1923,13 @@ void LyXText::TableFeatures(int feature) const /* insert the new cells */ int number = cursor.par->table->NumberOfCellsInRow(cell_org); - for (int i = 0; i < number; ++i) + Language const * lang = cursor.par->getParLanguage(); + LyXFont font(LyXFont::ALL_INHERIT,lang); + for (int i = 0; i < number; ++i) { cursor.par->InsertChar(pos, LyXParagraph::META_NEWLINE); - + cursor.par->SetFont(pos, font); + } + /* append the row into the table */ cursor.par->table->AppendContRow(cell_org); RedoParagraph(); @@ -1867,10 +1939,13 @@ void LyXText::TableFeatures(int feature) const LyXParagraph::size_type pos = 0; int cell_org = actCell; int cell = 0; + Language const * lang = cursor.par->getParLanguage(); + LyXFont font(LyXFont::ALL_INHERIT,lang); do{ if (pos && (cursor.par->IsNewline(pos-1))){ - if (cursor.par->table->AppendCellAfterCell(cell_org, cell)){ + 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; @@ -1880,9 +1955,12 @@ void LyXText::TableFeatures(int feature) const ++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); @@ -1891,8 +1969,8 @@ void LyXText::TableFeatures(int feature) const return; } case LyXTable::DELETE_ROW: - if (current_view->the_locking_inset) - current_view->unlockInset(current_view->the_locking_inset); + if (owner_->the_locking_inset) + owner_->unlockInset(owner_->the_locking_inset); RemoveTableRow(&cursor); RedoParagraph(); return; @@ -1901,8 +1979,8 @@ void LyXText::TableFeatures(int feature) const LyXParagraph::size_type pos = 0; int cell_org = actCell; int cell = 0; - if (current_view->the_locking_inset) - current_view->unlockInset(current_view->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)){ @@ -2022,7 +2100,7 @@ void LyXText::TableFeatures(int feature) const // dummy-paragraph !! // not necessar anymore with UNDO :) for (LyXParagraph::size_type i = - cursor.par->text.size() - 1; i >= 0; --i) + cursor.par->size() - 1; i >= 0; --i) cursor.par->Erase(i); RedoParagraph(); return; @@ -2301,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; @@ -2426,22 +2505,19 @@ void LyXText::RedoParagraph() const /* 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); @@ -2476,7 +2552,7 @@ void LyXText::InsertChar(char c) bool jumped_over_space = false; - if (IsLineSeparatorChar(c)) { + if (!freeSpacing && IsLineSeparatorChar(c)) { #ifndef FIX_DOUBLE_SPACE if (cursor.pos < lastpos && cursor.par->IsLineSeparator(cursor.pos)) { @@ -2487,7 +2563,7 @@ void LyXText::InsertChar(char c) * blank at the end of a row we have to force * a rebreak.*/ - current_view->owner()->getMiniBuffer() + owner_->owner()->getMiniBuffer() ->Set(_("You cannot type two spaces this way. " " Please read the Tutorial.")); #if 1 @@ -2514,9 +2590,9 @@ void LyXText::InsertChar(char c) && 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; } @@ -2803,6 +2879,7 @@ void LyXText::CursorRightOneWord() const { // treat floats, HFills and Insets as words LyXCursor tmpcursor = cursor; +#warning See comment on top of text.C if (tmpcursor.pos == tmpcursor.par->Last() && tmpcursor.par->Next()) @@ -2997,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; @@ -3034,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 */ @@ -3059,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() @@ -3085,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(); @@ -3102,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; @@ -3136,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) { @@ -3154,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); @@ -3174,6 +3279,7 @@ void LyXText::Delete() // just move to the right CursorRightIntern(); +#warning Look at the comment here. // This check is not very good... // The CursorRightIntern calls DeleteEmptyParagrapgMechanism // and that can very well delete the par or par->previous in @@ -3202,13 +3308,10 @@ void LyXText::Delete() } -void LyXText::Backspace() +void LyXText::Backspace() { - LyXParagraph * tmppar; - Row * tmprow, * row; - long y; - int tmpheight; - + DebugTracer trc1("LyXText::Backspace"); + /* table stuff -- begin */ if (cursor.par->table) { BackspaceInTable(); @@ -3224,6 +3327,11 @@ void LyXText::Backspace() LyXFont rawparfont = cursor.par->GetFontSettings(lastpos - 1); if (cursor.pos == 0) { + DebugTracer trc("LyXText::Backspace cursor.pos == 0"); + + // The cursor is at the beginning of a paragraph, so the the backspace + // will collapse two paragraphs into one. + // we may paste some paragraphs // is it an empty paragraph? @@ -3231,17 +3339,19 @@ void LyXText::Backspace() if ((lastpos == 0 || (lastpos == 1 && cursor.par->IsSeparator(0))) && !(cursor.par->Next() - && cursor.par->footnoteflag == - LyXParagraph::NO_FOOTNOTE - && cursor.par->Next()->footnoteflag == - LyXParagraph::OPEN_FOOTNOTE)) { + && cursor.par->footnoteflag == LyXParagraph::NO_FOOTNOTE + && cursor.par->Next()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)) { + // This is an empty paragraph and we delete it just by moving the curosr one step + // left and let the DeleteEmptyParagraphMechanism handle the actual deleteion + // of the paragraph. if (cursor.par->previous) { - tmppar = cursor.par->previous->FirstPhysicalPar(); + LyXParagraph * tmppar = cursor.par->previous->FirstPhysicalPar(); if (cursor.par->GetLayout() == tmppar->GetLayout() && cursor.par->footnoteflag == tmppar->footnoteflag && cursor.par->GetAlign() == tmppar->GetAlign()) { - + // Inherit botom DTD from the paragraph below. + // (the one we are deleting) tmppar->line_bottom = cursor.par->line_bottom; tmppar->added_space_bottom = cursor.par->added_space_bottom; tmppar->pagebreak_bottom = cursor.par->pagebreak_bottom; @@ -3250,7 +3360,7 @@ void LyXText::Backspace() CursorLeftIntern(); // the layout things can change the height of a row ! - tmpheight = cursor.row->height; + int tmpheight = cursor.row->height; SetHeightOfRow(cursor.row); if (cursor.row->height != tmpheight) { refresh_y = cursor.y - cursor.row->baseline; @@ -3260,14 +3370,17 @@ void LyXText::Backspace() return; } } + if (cursor.par->ParFromPos(cursor.pos)->previous){ SetUndo(Undo::DELETE, cursor.par->ParFromPos(cursor.pos)->previous->previous, cursor.par->ParFromPos(cursor.pos)->next); } - tmppar = cursor.par; - tmprow = cursor.row; + + LyXParagraph * tmppar = cursor.par; + Row * tmprow = cursor.row; CursorLeftIntern(); +#warning See comment on top of text.C /* Pasting is not allowed, if the paragraphs have different layout. I think it is a real bug of all other word processors to allow it. It confuses the user. @@ -3280,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--; @@ -3301,16 +3418,22 @@ void LyXText::Backspace() refresh_y = cursor.y - cursor.row->baseline; // remove the lost paragraph - RemoveParagraph(tmprow); - RemoveRow(tmprow); + // This one is not safe, since the paragraph that the tmprow and the + // following rows belong to has been deleted by the PasteParagraph + // above. The question is... could this be moved in front of the + // PasteParagraph? + //RemoveParagraph(tmprow); + //RemoveRow(tmprow); - AppendParagraph(cursor.row); + AppendParagraph(cursor.row); // This rebuilds the rows. UpdateCounters(cursor.row); // the row may have changed, block, hfills etc. SetCursor(cursor.par, cursor.pos); } } else { + DebugTracer trc("LyXText::Backspace normal backspace"); + /* this is the code for a normal backspace, not pasting * any paragraphs */ SetUndo(Undo::DELETE, @@ -3331,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 */ @@ -3346,7 +3469,7 @@ void LyXText::Backspace() if (cursor.pos && cursor.par->IsNewline(cursor.pos)) { cursor.par->Erase(cursor.pos); // refresh the positions - tmprow = row; + Row * tmprow = row; while (tmprow->next && tmprow->next->par == row->par) { tmprow = tmprow->next; tmprow->pos--; @@ -3367,7 +3490,7 @@ void LyXText::Backspace() cursor.par->Erase(cursor.pos); // refresh the positions - tmprow = row; + Row * tmprow = row; while (tmprow->next && tmprow->next->par == row->par) { tmprow = tmprow->next; tmprow->pos--; @@ -3416,7 +3539,7 @@ void LyXText::Backspace() if ( z >= row->pos) { row->pos = z + 1; - tmprow = row->previous; + Row * tmprow = row->previous; // maybe the current row is now empty if (row->pos >= row->par->Last()) { @@ -3495,7 +3618,8 @@ void LyXText::Backspace() SetCursor(cursor.par, cursor.pos, false); } } - + DebugTracer trc2("LyXText::Backspace wrap up"); + // restore the current font // That is what a user expects! current_font = rawtmpfont; @@ -3715,10 +3839,33 @@ void LyXText::GetVisibleRow(int offset, y_top += LYX_PAPER_MARGIN; if (row_ptr->par->pagebreak_top){ /* draw a top pagebreak */ +#if 0 pain.line(0, offset + y_top + 2 * DefaultHeight(), paperwidth, offset + y_top + 2 * DefaultHeight(), LColor::pagebreak, Painter::line_onoffdash); +#else + LyXFont pb_font; + pb_font.setColor(LColor::pagebreak).decSize(); + int w = 0, a = 0, d = 0; + pain.line(0, offset + y_top + 2*DefaultHeight(), + paperwidth, + offset + y_top + 2*DefaultHeight(), + LColor::pagebreak, + Painter::line_onoffdash) + .rectText(0, + 0, + _("Page Break (top)"), + pb_font, + LColor::background, + LColor::background, false, w, a, d); + pain.rectText((paperwidth - w)/2, + offset +y_top + 2*DefaultHeight() +d, + _("Page Break (top)"), + pb_font, + LColor::background, + LColor::background); +#endif y_top += 3 * DefaultHeight(); } @@ -3742,7 +3889,7 @@ void LyXText::GetVisibleRow(int offset, } /* 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 */ @@ -3750,13 +3897,13 @@ void LyXText::GetVisibleRow(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()->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 */ @@ -3868,10 +4015,34 @@ void LyXText::GetVisibleRow(int offset, /* draw a bottom pagebreak */ if (firstpar->pagebreak_bottom) { +#if 0 pain.line(0, offset + y_bottom - 2 * DefaultHeight(), paperwidth, offset + y_bottom - 2 * DefaultHeight(), LColor::pagebreak, Painter::line_onoffdash); +#else + LyXFont pb_font; + pb_font.setColor(LColor::pagebreak).decSize(); + int w = 0, a = 0, d = 0; + pain.line(0, + offset + y_bottom - 2 * DefaultHeight(), + paperwidth, + offset + y_bottom - 2 * DefaultHeight(), + LColor::pagebreak, + Painter::line_onoffdash) + .rectText(0, + 0, + _("Page Break (bottom)"), + pb_font, + LColor::background, + LColor::background, false, w, a, d); + pain.rectText((paperwidth - w)/2, + offset +y_top + 2*DefaultHeight() +d, + _("Page Break (bottom)"), + pb_font, + LColor::background, + LColor::background); +#endif y_bottom -= 3 * DefaultHeight(); } @@ -3894,7 +4065,7 @@ void LyXText::GetVisibleRow(int offset, } /* 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 */ @@ -3905,6 +4076,40 @@ void LyXText::GetVisibleRow(int offset, Painter::line_thick); y_bottom -= GetFont(par, par->Last() - 1).ascent('x'); } + + // draw an endlabel + int endlabel = row_ptr->par->GetEndLabel(); + if (endlabel == END_LABEL_BOX || + endlabel == END_LABEL_FILLED_BOX) { + LyXFont font = GetFont(row_ptr->par, RowLast(row_ptr)); + int size = int(0.75*font.maxAscent()); + int y = (offset + row_ptr->baseline) - size; + int x = (direction == LYX_DIR_LEFT_TO_RIGHT) + ? paperwidth - LYX_PAPER_MARGIN - size + : LYX_PAPER_MARGIN; + if (row_ptr->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) + if (direction == LYX_DIR_LEFT_TO_RIGHT) + x -= LYX_PAPER_MARGIN/2; + else { + LyXFont font(LyXFont::ALL_SANE); + font.setSize(LyXFont::SIZE_SMALL); + x += font.textWidth("Mwide-figM", 10); + } + if (row_ptr->fill <= size) + x += (size - row_ptr->fill + 1) * direction; + if (endlabel == END_LABEL_BOX) { + pain.line(x, y, x, y + size, + LColor::eolmarker); + pain.line(x + size, y, x + size , y + size, + LColor::eolmarker); + pain.line(x, y, x + size, y, + LColor::eolmarker); + pain.line(x, y + size, x + size, y + size, + LColor::eolmarker); + } else + pain.fillRectangle(x, y, size, size, + LColor::eolmarker); + } } /* draw the text in the pixmap */ @@ -3985,8 +4190,10 @@ void LyXText::GetVisibleRow(int offset, } 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. */ +#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, @@ -4016,6 +4223,7 @@ void LyXText::GetVisibleRow(int offset, offset + row_ptr->baseline + 2); } } +#endif ++vpos; } else draw(row_ptr, vpos, offset, x); @@ -4122,8 +4330,10 @@ void LyXText::GetVisibleRow(int offset, x+= SingleWidth(row_ptr->par, pos); if (pos >= main_body) x+= fill_separator; - /* -------> Only draw protected spaces when not in - * free-spacing mode. */ +#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), @@ -4154,6 +4364,7 @@ void LyXText::GetVisibleRow(int offset, offset + row_ptr->baseline + 2); } } +#endif ++vpos; } else draw(row_ptr, vpos, offset, x); @@ -4182,10 +4393,10 @@ int LyXText::GetColumnNearX(Row * row, int & x) const LyXDirection direction = row->par->getParDirection(); LyXParagraph::size_type vc = row->pos; LyXParagraph::size_type last = RowLast(row); - LyXParagraph::size_type c; + LyXParagraph::size_type c = 0; LyXLayout const & layout = textclasslist.Style(parameters->textclass, - row->par->GetLayout()); + row->par->GetLayout()); /* table stuff -- begin */ if (row->par->table) { if (row->next && row->next->par == row->par //the last row doesn't need a newline at the end @@ -4265,10 +4476,15 @@ int LyXText::GetColumnNearX(Row * row, int & x) const vc = row->pos+1; tmpx += fill_separator+SingleWidth(row->par, vis2log(row->pos)); } - if (row->pos > last) // Row is empty? c = row->pos; - else if (vc <= last) { + else if (vc > last || + (row->par->table && vc > row->pos && row->par->IsNewline(vc)) ){ + int pos = (vc > last+1) ? last : vc - 1; + c = vis2log(pos); + if (row->par->getLetterDirection(c) == LYX_DIR_LEFT_TO_RIGHT) + ++c; + } else { c = vis2log(vc); LyXDirection direction = row->par->getLetterDirection(c); if (vc > row->pos && row->par->IsLineSeparator(c) @@ -4276,10 +4492,6 @@ int LyXText::GetColumnNearX(Row * row, int & x) const c = vis2log(vc-1); if (direction == LYX_DIR_RIGHT_TO_LEFT) ++c; - } else { - c = vis2log(last)+1; - if (row->par->getLetterDirection(c - 1) == LYX_DIR_RIGHT_TO_LEFT) - --c; } if (!row->par->table && row->pos <= last && c > last @@ -4399,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); } } @@ -4439,32 +4657,44 @@ Row * LyXText::GetRow(LyXParagraph * par, LyXParagraph::size_type pos, long & y) const { Row * tmprow; - + if (currentrow) { - if (par == currentrow->par || par == currentrow->par->Previous()) { + 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) { + // 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; } - while (currentrow->previous && currentrow->previous->par == par) { + // 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)) { + 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) { + while (tmprow->pos < pos + && tmprow->next + && tmprow->next->par == par + && tmprow->next->pos <= pos) { y += tmprow->height; tmprow = tmprow->next; } @@ -4473,17 +4703,20 @@ Row * LyXText::GetRow(LyXParagraph * par, return tmprow; } } + tmprow = firstrow; y = 0; // find the first row of the specified paragraph - while (tmprow->next && (tmprow->par != par)) { + 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) { + while (tmprow->pos < pos + && tmprow->next + && tmprow->next->par == par + && tmprow->next->pos <= pos) { y += tmprow->height; tmprow = tmprow->next; }