1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2000 The LyX Team.
9 * ====================================================== */
13 #include FORMS_H_LOCATION
17 #pragma implementation "lyxtext.h"
21 #include "lyxparagraph.h"
22 #include "insets/inseterror.h"
23 #include "insets/insetbib.h"
24 #include "insets/insetspecialchar.h"
25 #include "insets/insettext.h"
26 #include "insets/insetfloat.h"
29 #include "support/textutils.h"
31 #include "minibuffer.h"
33 #include "bufferparams.h"
34 #include "lyx_gui_misc.h"
37 #include "BufferView.h"
40 #include "CutAndPaste.h"
45 #include "FloatList.h"
52 LyXText::LyXText(BufferView * bv)
60 LyXText::LyXText(InsetText * inset)
70 the_locking_inset = 0;
78 status = LyXText::UNCHANGED;
79 // set cursor at the very top position
80 selection = true; /* these setting is necessary
81 because of the delete-empty-
82 paragraph mechanism in
85 LyXParagraph * par = OwnerParagraph();
86 current_font = GetFont(bv_owner->buffer(), par, 0);
88 InsertParagraph(bv_owner, par, lastrow);
91 SetCursor(bv_owner, firstrow->par(), 0);
93 current_font = LyXFont(LyXFont::ALL_SANE);
99 // no rebreak necessary
102 undo_finished = true;
105 // Default layouttype for copy environment type
109 // Dump all rowinformation:
110 Row * tmprow = firstrow;
111 lyxerr << "Baseline Paragraph Pos Height Ascent Fill\n";
113 lyxerr << tmprow->baseline() << '\t'
114 << tmprow->par << '\t'
115 << tmprow->pos() << '\t'
116 << tmprow->height << '\t'
117 << tmprow->ascent_of_text << '\t'
118 << tmprow->fill << '\n';
119 tmprow = tmprow->next();
126 void LyXText::init(BufferView * bview)
131 LyXParagraph * par = OwnerParagraph();
132 current_font = GetFont(bview->buffer(), par, 0);
134 InsertParagraph(bview, par, lastrow);
137 SetCursorIntern(bview, firstrow->par(), 0);
140 // Dump all rowinformation:
141 Row * tmprow = firstrow;
142 lyxerr << "Width = " << width << endl;
143 lyxerr << "Baseline Paragraph Pos Height Ascent Fill\n";
145 lyxerr << tmprow->baseline() << '\t'
146 << tmprow->par() << '\t'
147 << tmprow->pos() << '\t'
148 << tmprow->height() << '\t'
149 << tmprow->ascent_of_text() << '\t'
150 << tmprow->fill() << '\n';
151 tmprow = tmprow->next();
159 // Delete all rows, this does not touch the paragraphs!
160 Row * tmprow = firstrow;
162 tmprow = firstrow->next();
169 // Gets the fully instantiated font at a given position in a paragraph
170 // Basically the same routine as LyXParagraph::getFont() in paragraph.C.
171 // The difference is that this one is used for displaying, and thus we
172 // are allowed to make cosmetic improvements. For instance make footnotes
174 // If position is -1, we get the layout font of the paragraph.
175 // If position is -2, we get the font of the manual label of the paragraph.
176 LyXFont const LyXText::GetFont(Buffer const * buf, LyXParagraph * par,
177 LyXParagraph::size_type pos) const
179 LyXLayout const & layout =
180 textclasslist.Style(buf->params.textclass, par->GetLayout());
182 char par_depth = par->GetDepth();
183 // We specialize the 95% common case:
186 par->footnoteflag == LyXParagraph::NO_FOOTNOTE &&
191 if (layout.labeltype == LABEL_MANUAL
192 && pos < BeginningOfMainBody(buf, par)) {
194 LyXFont f = par->GetFontSettings(buf->params,
196 return f.realize(layout.reslabelfont);
198 LyXFont f = par->GetFontSettings(buf->params, pos);
199 return f.realize(layout.resfont);
204 // process layoutfont for pos == -1 and labelfont for pos < -1
206 return layout.resfont;
208 return layout.reslabelfont;
212 // The uncommon case need not be optimized as much
214 LyXFont layoutfont, tmpfont;
218 if (pos < BeginningOfMainBody(buf, par)) {
220 layoutfont = layout.labelfont;
223 layoutfont = layout.font;
225 tmpfont = par->GetFontSettings(buf->params, pos);
226 tmpfont.realize(layoutfont);
229 // process layoutfont for pos == -1 and labelfont for pos < -1
231 tmpfont = layout.font;
233 tmpfont = layout.labelfont;
236 // Resolve against environment font information
237 while (par && par_depth && !tmpfont.resolved()) {
238 par = par->DepthHook(par_depth - 1);
240 tmpfont.realize(textclasslist.
241 Style(buf->params.textclass,
242 par->GetLayout()).font);
243 par_depth = par->GetDepth();
247 tmpfont.realize(textclasslist.TextClass(buf->params.textclass).defaultfont());
250 // Cosmetic improvement: If this is an open footnote, make the font
252 if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
253 && par->footnotekind == LyXParagraph::FOOTNOTE) {
261 void LyXText::SetCharFont(Buffer const * buf, LyXParagraph * par,
262 LyXParagraph::size_type pos,
266 // Let the insets convert their font
267 if (par->GetChar(pos) == LyXParagraph::META_INSET) {
268 if (par->GetInset(pos))
269 font = par->GetInset(pos)->ConvertFont(font);
272 LyXLayout const & layout =
273 textclasslist.Style(buf->params.textclass,
276 // Get concrete layout font to reduce against
279 if (pos < BeginningOfMainBody(buf, par))
280 layoutfont = layout.labelfont;
282 layoutfont = layout.font;
284 // Realize against environment font information
285 if (par->GetDepth()){
286 LyXParagraph * tp = par;
287 while (!layoutfont.resolved() && tp && tp->GetDepth()) {
288 tp = tp->DepthHook(tp->GetDepth()-1);
290 layoutfont.realize(textclasslist.
291 Style(buf->params.textclass,
292 tp->GetLayout()).font);
296 layoutfont.realize(textclasslist.TextClass(buf->params.textclass).defaultfont());
299 if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
300 && par->footnotekind == LyXParagraph::FOOTNOTE) {
301 layoutfont.decSize();
304 // Now, reduce font against full layout font
305 font.reduce(layoutfont);
307 par->SetFont(pos, font);
311 /* inserts a new row behind the specified row, increments
312 * the touched counters */
313 void LyXText::InsertRow(Row * row, LyXParagraph * par,
314 LyXParagraph::size_type pos) const
316 Row * tmprow = new Row;
319 tmprow->next(firstrow);
322 tmprow->previous(row);
323 tmprow->next(row->next());
328 tmprow->next()->previous(tmprow);
330 if (tmprow->previous())
331 tmprow->previous()->next(tmprow);
339 ++number_of_rows; // one more row
343 // removes the row and reset the touched counters
344 void LyXText::RemoveRow(Row * row) const
346 /* this must not happen before the currentrow for clear reasons.
347 so the trick is just to set the current row onto the previous
350 GetRow(row->par(), row->pos(), unused_y);
353 row->next()->previous(row->previous());
354 if (!row->previous()) {
355 firstrow = row->next();
357 row->previous()->next(row->next());
360 lastrow = row->previous();
362 height -= row->height(); // the text becomes smaller
365 --number_of_rows; // one row less
369 // remove all following rows of the paragraph of the specified row.
370 void LyXText::RemoveParagraph(Row * row) const
372 LyXParagraph * tmppar = row->par();
376 while (row && row->par() == tmppar) {
377 tmprow = row->next();
384 // insert the specified paragraph behind the specified row
385 void LyXText::InsertParagraph(BufferView * bview, LyXParagraph * par,
388 InsertRow(row, par, 0); /* insert a new row, starting
391 SetCounter(bview->buffer(), par); // set the counters
393 // and now append the whole paragraph behind the new row
396 AppendParagraph(bview, firstrow);
398 row->next()->height(0);
399 AppendParagraph(bview, row->next());
405 void LyXText::ToggleFootnote(BufferView * bview)
407 LyXParagraph * par = cursor.par()->ParFromPos(cursor.pos());
409 && par->next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
411 bview->owner()->getMiniBuffer()->Set(_("Opened float"));
413 bview->owner()->getMiniBuffer()->Set(_("Closed float"));
414 CloseFootnote(bview);
421 void LyXText::OpenStuff(BufferView * bview)
423 if (cursor.pos() == 0 && cursor.par()->bibkey){
424 cursor.par()->bibkey->Edit(bview, 0, 0, 0);
425 } else if (cursor.pos() < cursor.par()->Last()
426 && cursor.par()->GetChar(cursor.pos()) == LyXParagraph::META_INSET
427 && cursor.par()->GetInset(cursor.pos())->Editable()) {
428 bview->owner()->getMiniBuffer()
429 ->Set(cursor.par()->GetInset(cursor.pos())->EditMessage());
430 if (cursor.par()->GetInset(cursor.pos())->Editable() != Inset::HIGHLY_EDITABLE)
431 SetCursorParUndo(bview->buffer());
432 cursor.par()->GetInset(cursor.pos())->Edit(bview, 0, 0, 0);
436 ToggleFootnote(bview);
444 void LyXText::CloseFootnote(BufferView * bview)
446 LyXParagraph * tmppar;
447 LyXParagraph * par = cursor.par()->ParFromPos(cursor.pos());
449 // if the cursor is not in an open footnote, or
450 // there is no open footnote in this paragraph, just return.
451 if (cursor.par()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE) {
454 par->next->footnoteflag != LyXParagraph::OPEN_FOOTNOTE) {
455 bview->owner()->getMiniBuffer()
456 ->Set(_("Nothing to do"));
460 // ok, move the cursor right before the footnote
461 // just a little faster than using CursorRight()
463 cursor.par()->ParFromPos(cursor.pos()) != par;) {
464 cursor.pos(cursor.pos() + 1);
467 // now the cursor is at the beginning of the physical par
468 SetCursor(bview, cursor.par(),
470 cursor.par()->ParFromPos(cursor.pos())->size());
472 /* we are in a footnote, so let us move at the beginning */
473 /* this is just faster than using just CursorLeft() */
475 tmppar = cursor.par();
476 while (tmppar->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
477 // just a little bit faster than movin the cursor
478 tmppar = tmppar->Previous();
480 SetCursor(bview, tmppar, tmppar->Last());
483 // the cursor must be exactly before the footnote
484 par = cursor.par()->ParFromPos(cursor.pos());
486 status = LyXText::NEED_MORE_REFRESH;
487 refresh_row = cursor.row();
488 refresh_y = cursor.y() - cursor.row()->baseline();
490 tmppar = cursor.par();
491 LyXParagraph * endpar = par->NextAfterFootnote()->Next();
492 Row * row = cursor.row();
494 tmppar->CloseFootnote(cursor.pos());
496 while (tmppar != endpar) {
497 RemoveRow(row->next());
499 tmppar = row->next()->par();
504 AppendParagraph(bview, cursor.row());
506 SetCursor(bview, cursor.par(), cursor.pos());
510 if (cursor.row()->next())
511 SetHeightOfRow(bview, cursor.row()->next());
516 /* used in setlayout */
517 // Asger is not sure we want to do this...
518 void LyXText::MakeFontEntriesLayoutSpecific(Buffer const * buf,
522 LyXLayout const & layout =
523 textclasslist.Style(buf->params.textclass, par->GetLayout());
525 LyXFont layoutfont, tmpfont;
526 for (LyXParagraph::size_type pos = 0;
527 pos < par->Last(); ++pos) {
528 if (pos < BeginningOfMainBody(buf, par))
529 layoutfont = layout.labelfont;
531 layoutfont = layout.font;
533 tmpfont = par->GetFontSettings(buf->params, pos);
534 tmpfont.reduce(layoutfont);
535 par->SetFont(pos, tmpfont);
540 LyXParagraph * LyXText::SetLayout(BufferView * bview,
541 LyXCursor & cur, LyXCursor & sstart_cur,
542 LyXCursor & send_cur,
543 LyXTextClass::size_type layout)
546 LyXParagraph * endpar = send_cur.par()->LastPhysicalPar()->Next();
548 LyXParagraph * endpar = send_cur.par()->Next();
550 LyXParagraph * undoendpar = endpar;
552 if (endpar && endpar->GetDepth()) {
553 while (endpar && endpar->GetDepth()) {
555 endpar = endpar->LastPhysicalPar()->Next();
557 endpar = endpar->Next();
562 endpar = endpar->Next(); // because of parindents etc.
565 SetUndo(bview->buffer(), Undo::EDIT,
567 sstart_cur.par()->ParFromPos(sstart_cur.pos())->previous,
569 sstart_cur.par()->previous,
573 /* ok we have a selection. This is always between sstart_cur
574 * and sel_end cursor */
577 LyXLayout const & lyxlayout =
578 textclasslist.Style(bview->buffer()->params.textclass, layout);
580 while (cur.par() != send_cur.par()) {
582 if (cur.par()->footnoteflag == sstart_cur.par()->footnoteflag) {
584 cur.par()->SetLayout(bview->buffer()->params, layout);
585 MakeFontEntriesLayoutSpecific(bview->buffer(), cur.par());
587 LyXParagraph * fppar = cur.par()->FirstPhysicalPar();
589 LyXParagraph * fppar = cur.par();
591 fppar->added_space_top = lyxlayout.fill_top ?
592 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
593 fppar->added_space_bottom = lyxlayout.fill_bottom ?
594 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
595 if (lyxlayout.margintype == MARGIN_MANUAL)
596 cur.par()->SetLabelWidthString(lyxlayout.labelstring());
597 if (lyxlayout.labeltype != LABEL_BIBLIO
599 delete fppar->bibkey;
605 cur.par(cur.par()->Next());
608 if (cur.par()->footnoteflag == sstart_cur.par()->footnoteflag) {
610 cur.par()->SetLayout(bview->buffer()->params, layout);
611 MakeFontEntriesLayoutSpecific(bview->buffer(), cur.par());
613 LyXParagraph * fppar = cur.par()->FirstPhysicalPar();
615 LyXParagraph * fppar = cur.par();
617 fppar->added_space_top = lyxlayout.fill_top ?
618 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
619 fppar->added_space_bottom = lyxlayout.fill_bottom ?
620 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
621 if (lyxlayout.margintype == MARGIN_MANUAL)
622 cur.par()->SetLabelWidthString(lyxlayout.labelstring());
623 if (lyxlayout.labeltype != LABEL_BIBLIO
625 delete fppar->bibkey;
634 // set layout over selection and make a total rebreak of those paragraphs
635 void LyXText::SetLayout(BufferView * bview, LyXTextClass::size_type layout)
637 LyXCursor tmpcursor = cursor; /* store the current cursor */
639 // if there is no selection just set the layout
640 // of the current paragraph */
642 sel_start_cursor = cursor; // dummy selection
643 sel_end_cursor = cursor;
646 endpar = SetLayout(bview, cursor, sel_start_cursor,
647 sel_end_cursor, layout);
648 RedoParagraphs(bview, sel_start_cursor, endpar);
650 // we have to reset the selection, because the
651 // geometry could have changed
652 SetCursor(bview, sel_start_cursor.par(),
653 sel_start_cursor.pos(), false);
655 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos(),
657 UpdateCounters(bview, cursor.row());
660 SetCursor(bview, tmpcursor.par(), tmpcursor.pos(), true);
664 // increment depth over selection and
665 // make a total rebreak of those paragraphs
666 void LyXText::IncDepth(BufferView * bview)
668 // If there is no selection, just use the current paragraph
670 sel_start_cursor = cursor; // dummy selection
671 sel_end_cursor = cursor;
674 // We end at the next paragraph with depth 0
675 LyXParagraph * endpar =
677 sel_end_cursor.par()->LastPhysicalPar()->Next();
679 sel_end_cursor.par()->Next();
681 LyXParagraph * undoendpar = endpar;
683 if (endpar && endpar->GetDepth()) {
684 while (endpar && endpar->GetDepth()) {
686 endpar = endpar->LastPhysicalPar()->Next();
688 endpar = endpar->Next();
694 endpar = endpar->Next(); // because of parindents etc.
697 SetUndo(bview->buffer(), Undo::EDIT,
700 .par()->ParFromPos(sel_start_cursor.pos())->previous,
702 sel_start_cursor.par()->previous,
706 LyXCursor tmpcursor = cursor; // store the current cursor
708 // ok we have a selection. This is always between sel_start_cursor
709 // and sel_end cursor
710 cursor = sel_start_cursor;
712 bool anything_changed = false;
715 // NOTE: you can't change the depth of a bibliography entry
718 cursor.par()->footnoteflag ==
719 sel_start_cursor.par()->footnoteflag &&
721 textclasslist.Style(bview->buffer()->params.textclass,
722 cursor.par()->GetLayout()
723 ).labeltype != LABEL_BIBLIO) {
724 LyXParagraph * prev =
726 cursor.par()->FirstPhysicalPar()->Previous();
728 cursor.par()->Previous();
731 && (prev->GetDepth() - cursor.par()->GetDepth() > 0
732 || (prev->GetDepth() == cursor.par()->GetDepth()
733 && textclasslist.Style(bview->buffer()->params.textclass,
734 prev->GetLayout()).isEnvironment()))) {
736 cursor.par()->FirstPhysicalPar()->depth++;
738 cursor.par()->depth++;
740 anything_changed = true;
743 if (cursor.par() == sel_end_cursor.par())
745 cursor.par(cursor.par()->Next());
748 // if nothing changed set all depth to 0
749 if (!anything_changed) {
750 cursor = sel_start_cursor;
751 while (cursor.par() != sel_end_cursor.par()) {
753 cursor.par()->FirstPhysicalPar()->depth = 0;
755 cursor.par()->depth = 0;
757 cursor.par(cursor.par()->Next());
760 if (cursor.par()->footnoteflag == sel_start_cursor.par()->footnoteflag)
761 cursor.par()->FirstPhysicalPar()->depth = 0;
763 cursor.par()->depth = 0;
767 RedoParagraphs(bview, sel_start_cursor, endpar);
769 // we have to reset the selection, because the
770 // geometry could have changed
771 SetCursor(bview, sel_start_cursor.par(),
772 sel_start_cursor.pos());
774 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
775 UpdateCounters(bview, cursor.row());
778 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
782 // decrement depth over selection and
783 // make a total rebreak of those paragraphs
784 void LyXText::DecDepth(BufferView * bview)
786 // if there is no selection just set the layout
787 // of the current paragraph
789 sel_start_cursor = cursor; // dummy selection
790 sel_end_cursor = cursor;
793 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
795 LyXParagraph * endpar = sel_end_cursor.par()->Next();
797 LyXParagraph * undoendpar = endpar;
799 if (endpar && endpar->GetDepth()) {
800 while (endpar && endpar->GetDepth()) {
802 endpar = endpar->LastPhysicalPar()->Next();
804 endpar = endpar->Next();
810 endpar = endpar->Next(); // because of parindents etc.
813 SetUndo(bview->buffer(), Undo::EDIT,
816 .par()->ParFromPos(sel_start_cursor.pos())->previous,
818 sel_start_cursor.par()->previous,
822 LyXCursor tmpcursor = cursor; // store the current cursor
824 // ok we have a selection. This is always between sel_start_cursor
825 // and sel_end cursor
826 cursor = sel_start_cursor;
830 if (cursor.par()->footnoteflag ==
831 sel_start_cursor.par()->footnoteflag) {
832 if (cursor.par()->FirstPhysicalPar()->depth)
833 cursor.par()->FirstPhysicalPar()->depth--;
836 if (cursor.par()->depth)
837 cursor.par()->depth--;
839 if (cursor.par() == sel_end_cursor.par())
841 cursor.par(cursor.par()->Next());
844 RedoParagraphs(bview, sel_start_cursor, endpar);
846 // we have to reset the selection, because the
847 // geometry could have changed
848 SetCursor(bview, sel_start_cursor.par(),
849 sel_start_cursor.pos());
851 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
852 UpdateCounters(bview, cursor.row());
855 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
859 // set font over selection and make a total rebreak of those paragraphs
860 void LyXText::SetFont(BufferView * bview, LyXFont const & font, bool toggleall)
862 // if there is no selection just set the current_font
864 // Determine basis font
866 if (cursor.pos() < BeginningOfMainBody(bview->buffer(),
868 layoutfont = GetFont(bview->buffer(), cursor.par(),-2);
870 layoutfont = GetFont(bview->buffer(), cursor.par(),-1);
871 // Update current font
872 real_current_font.update(font,
873 bview->buffer()->params.language,
876 // Reduce to implicit settings
877 current_font = real_current_font;
878 current_font.reduce(layoutfont);
879 // And resolve it completely
880 real_current_font.realize(layoutfont);
884 LyXCursor tmpcursor = cursor; // store the current cursor
886 // ok we have a selection. This is always between sel_start_cursor
887 // and sel_end cursor
889 SetUndo(bview->buffer(), Undo::EDIT,
891 sel_start_cursor.par()->ParFromPos(sel_start_cursor.pos())->previous,
892 sel_end_cursor.par()->ParFromPos(sel_end_cursor.pos())->next
894 sel_start_cursor.par()->previous,
895 sel_end_cursor.par()->next
898 cursor = sel_start_cursor;
899 while (cursor.par() != sel_end_cursor.par() ||
902 cursor.par()->footnoteflag == sel_start_cursor.par()->footnoteflag &&
904 cursor.pos() < sel_end_cursor.pos()))
906 if (cursor.pos() < cursor.par()->Last()
908 && cursor.par()->footnoteflag
909 == sel_start_cursor.par()->footnoteflag
912 // an open footnote should behave
914 LyXFont newfont = GetFont(bview->buffer(),
915 cursor.par(), cursor.pos());
917 bview->buffer()->params.language,
919 SetCharFont(bview->buffer(),
920 cursor.par(), cursor.pos(), newfont);
921 cursor.pos(cursor.pos() + 1);
924 cursor.par(cursor.par()->Next());
928 RedoParagraphs(bview, sel_start_cursor, sel_end_cursor.par()->Next());
930 // we have to reset the selection, because the
931 // geometry could have changed
932 SetCursor(bview, sel_start_cursor.par(), sel_start_cursor.pos());
934 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
937 SetCursor(bview, tmpcursor.par(), tmpcursor.pos(), true,
938 tmpcursor.boundary());
942 void LyXText::RedoHeightOfParagraph(BufferView * bview, LyXCursor const & cur)
944 Row * tmprow = cur.row();
945 int y = cur.y() - tmprow->baseline();
947 SetHeightOfRow(bview, tmprow);
949 LyXParagraph * first_phys_par = tmprow->par()->FirstPhysicalPar();
951 LyXParagraph * first_phys_par = tmprow->par();
953 // find the first row of the paragraph
954 if (first_phys_par != tmprow->par())
955 while (tmprow->previous()
956 && tmprow->previous()->par() != first_phys_par) {
957 tmprow = tmprow->previous();
958 y -= tmprow->height();
959 SetHeightOfRow(bview, tmprow);
961 while (tmprow->previous() && tmprow->previous()->par() == first_phys_par) {
962 tmprow = tmprow->previous();
963 y -= tmprow->height();
964 SetHeightOfRow(bview, tmprow);
967 // we can set the refreshing parameters now
968 status = LyXText::NEED_MORE_REFRESH;
970 refresh_row = tmprow;
971 SetCursor(bview, cur.par(), cur.pos(), false, cursor.boundary());
975 void LyXText::RedoDrawingOfParagraph(BufferView * bview, LyXCursor const & cur)
977 Row * tmprow = cur.row();
979 int y = cur.y() - tmprow->baseline();
980 SetHeightOfRow(bview, tmprow);
982 LyXParagraph * first_phys_par = tmprow->par()->FirstPhysicalPar();
984 LyXParagraph * first_phys_par = tmprow->par();
986 // find the first row of the paragraph
987 if (first_phys_par != tmprow->par())
988 while (tmprow->previous() && tmprow->previous()->par() != first_phys_par) {
989 tmprow = tmprow->previous();
990 y -= tmprow->height();
992 while (tmprow->previous() && tmprow->previous()->par() == first_phys_par) {
993 tmprow = tmprow->previous();
994 y -= tmprow->height();
997 // we can set the refreshing parameters now
998 if (status == LyXText::UNCHANGED || y < refresh_y) {
1000 refresh_row = tmprow;
1002 status = LyXText::NEED_MORE_REFRESH;
1003 SetCursor(bview, cur.par(), cur.pos());
1007 /* deletes and inserts again all paragaphs between the cursor
1008 * and the specified par
1009 * This function is needed after SetLayout and SetFont etc. */
1010 void LyXText::RedoParagraphs(BufferView * bview, LyXCursor const & cur,
1011 LyXParagraph const * endpar) const
1014 LyXParagraph * tmppar = 0, * first_phys_par = 0;
1016 Row * tmprow = cur.row();
1018 int y = cur.y() - tmprow->baseline();
1020 if (!tmprow->previous()){
1021 first_phys_par = FirstParagraph(); // a trick/hack for UNDO
1024 first_phys_par = tmprow->par()->FirstPhysicalPar();
1026 first_phys_par = tmprow->par();
1028 // find the first row of the paragraph
1029 if (first_phys_par != tmprow->par())
1030 while (tmprow->previous() &&
1031 (tmprow->previous()->par() != first_phys_par)) {
1032 tmprow = tmprow->previous();
1033 y -= tmprow->height();
1035 while (tmprow->previous()
1036 && tmprow->previous()->par() == first_phys_par) {
1037 tmprow = tmprow->previous();
1038 y -= tmprow->height();
1042 // we can set the refreshing parameters now
1043 status = LyXText::NEED_MORE_REFRESH;
1045 refresh_row = tmprow->previous(); /* the real refresh row will
1046 be deleted, so I store
1047 the previous here */
1050 tmppar = tmprow->next()->par();
1053 while (tmppar != endpar) {
1054 RemoveRow(tmprow->next());
1056 tmppar = tmprow->next()->par();
1061 // remove the first one
1062 tmprow2 = tmprow; /* this is because tmprow->previous()
1064 tmprow = tmprow->previous();
1067 tmppar = first_phys_par;
1071 InsertParagraph(bview, tmppar, tmprow);
1074 while (tmprow->next() && tmprow->next()->par() == tmppar)
1075 tmprow = tmprow->next();
1076 tmppar = tmppar->Next();
1078 } while (tmppar != endpar);
1080 // this is because of layout changes
1082 refresh_y -= refresh_row->height();
1083 SetHeightOfRow(bview, refresh_row);
1085 refresh_row = firstrow;
1087 SetHeightOfRow(bview, refresh_row);
1090 if (tmprow && tmprow->next())
1091 SetHeightOfRow(bview, tmprow->next());
1095 bool LyXText::FullRebreak(BufferView * bview)
1101 if (need_break_row) {
1102 BreakAgain(bview, need_break_row);
1110 /* important for the screen */
1113 /* the cursor set functions have a special mechanism. When they
1114 * realize, that you left an empty paragraph, they will delete it.
1115 * They also delete the corresponding row */
1117 // need the selection cursor:
1118 void LyXText::SetSelection()
1121 last_sel_cursor = sel_cursor;
1122 sel_start_cursor = sel_cursor;
1123 sel_end_cursor = sel_cursor;
1128 // first the toggling area
1129 if (cursor.y() < last_sel_cursor.y()
1130 || (cursor.y() == last_sel_cursor.y()
1131 && cursor.x() < last_sel_cursor.x())) {
1132 toggle_end_cursor = last_sel_cursor;
1133 toggle_cursor = cursor;
1135 toggle_end_cursor = cursor;
1136 toggle_cursor = last_sel_cursor;
1139 last_sel_cursor = cursor;
1141 // and now the whole selection
1143 if (sel_cursor.par() == cursor.par())
1144 if (sel_cursor.pos() < cursor.pos()) {
1145 sel_end_cursor = cursor;
1146 sel_start_cursor = sel_cursor;
1148 sel_end_cursor = sel_cursor;
1149 sel_start_cursor = cursor;
1151 else if (sel_cursor.y() < cursor.y() ||
1152 (sel_cursor.y() == cursor.y() && sel_cursor.x() < cursor.x())) {
1153 sel_end_cursor = cursor;
1154 sel_start_cursor = sel_cursor;
1157 sel_end_cursor = sel_cursor;
1158 sel_start_cursor = cursor;
1161 // a selection with no contents is not a selection
1162 if (sel_start_cursor.par() == sel_end_cursor.par() &&
1163 sel_start_cursor.pos() == sel_end_cursor.pos())
1168 string const LyXText::selectionAsString(Buffer const * buffer) const
1170 if (!selection) return string();
1173 // Special handling if the whole selection is within one paragraph
1174 if (sel_start_cursor.par() == sel_end_cursor.par()) {
1175 result += sel_start_cursor.par()->String(buffer,
1176 sel_start_cursor.pos(),
1177 sel_end_cursor.pos());
1181 // The selection spans more than one paragraph
1183 // First paragraph in selection
1184 result += sel_start_cursor.par()->String(buffer,
1185 sel_start_cursor.pos(),
1186 sel_start_cursor.par()->Last())
1189 // The paragraphs in between (if any)
1190 LyXCursor tmpcur(sel_start_cursor);
1191 tmpcur.par(tmpcur.par()->Next());
1192 while (tmpcur.par() != sel_end_cursor.par()) {
1193 result += tmpcur.par()->String(buffer, 0, tmpcur.par()->Last()) + "\n\n";
1194 tmpcur.par(tmpcur.par()->Next()); // Or NextAfterFootnote??
1197 // Last paragraph in selection
1198 result += sel_end_cursor.par()->String(buffer, 0, sel_end_cursor.pos());
1204 void LyXText::ClearSelection() const
1207 status = LyXText::NEED_MORE_REFRESH;
1213 void LyXText::CursorHome(BufferView * bview) const
1215 SetCursor(bview, cursor.par(), cursor.row()->pos());
1219 void LyXText::CursorEnd(BufferView * bview) const
1221 if (!cursor.row()->next() || cursor.row()->next()->par() != cursor.row()->par())
1222 SetCursor(bview, cursor.par(), RowLast(cursor.row()) + 1);
1224 if (cursor.par()->Last() &&
1225 (cursor.par()->GetChar(RowLast(cursor.row())) == ' '
1226 || cursor.par()->IsNewline(RowLast(cursor.row()))))
1227 SetCursor(bview, cursor.par(), RowLast(cursor.row()));
1229 SetCursor(bview,cursor.par(), RowLast(cursor.row()) + 1);
1234 void LyXText::CursorTop(BufferView * bview) const
1236 while (cursor.par()->Previous())
1237 cursor.par(cursor.par()->Previous());
1238 SetCursor(bview, cursor.par(), 0);
1242 void LyXText::CursorBottom(BufferView * bview) const
1244 while (cursor.par()->Next())
1245 cursor.par(cursor.par()->Next());
1246 SetCursor(bview, cursor.par(), cursor.par()->Last());
1250 /* returns a pointer to the row near the specified y-coordinate
1251 * (relative to the whole text). y is set to the real beginning
1253 Row * LyXText::GetRowNearY(int & y) const
1255 Row * tmprow = firstrow;
1258 while (tmprow->next() && tmpy + tmprow->height() <= y) {
1259 tmpy += tmprow->height();
1260 tmprow = tmprow->next();
1263 y = tmpy; // return the real y
1268 void LyXText::ToggleFree(BufferView * bview,
1269 LyXFont const & font, bool toggleall)
1271 // If the mask is completely neutral, tell user
1272 if (font == LyXFont(LyXFont::ALL_IGNORE)) {
1273 // Could only happen with user style
1274 bview->owner()->getMiniBuffer()
1275 ->Set(_("No font change defined. Use Character under"
1276 " the Layout menu to define font change."));
1280 // Try implicit word selection
1281 // If there is a change in the language the implicit word selection
1283 LyXCursor resetCursor = cursor;
1284 bool implicitSelection = (font.language() == ignore_language
1285 && font.number() == LyXFont::IGNORE)
1286 ? SelectWordWhenUnderCursor(bview) : false;
1289 SetFont(bview, font, toggleall);
1291 /* Implicit selections are cleared afterwards and cursor is set to the
1292 original position. */
1293 if (implicitSelection) {
1295 cursor = resetCursor;
1296 SetCursor(bview, cursor.par(), cursor.pos());
1297 sel_cursor = cursor;
1302 LyXParagraph::size_type
1303 LyXText::BeginningOfMainBody(Buffer const * buf,
1304 LyXParagraph const * par) const
1306 if (textclasslist.Style(buf->params.textclass,
1307 par->GetLayout()).labeltype != LABEL_MANUAL)
1310 return par->BeginningOfMainBody();
1315 /* if there is a selection, reset every environment you can find
1316 * in the selection, otherwise just the environment you are in */
1317 void LyXText::MeltFootnoteEnvironment(BufferView * bview)
1319 LyXParagraph * tmppar, * firsttmppar;
1323 /* is is only allowed, if the cursor is IN an open footnote.
1324 * Otherwise it is too dangerous */
1325 if (cursor.par()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE)
1328 SetUndo(bview->buffer(), Undo::FINISH,
1329 cursor.par()->PreviousBeforeFootnote()->previous,
1330 cursor.par()->NextAfterFootnote()->next);
1332 /* ok, move to the beginning of the footnote. */
1333 while (cursor.par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
1334 cursor.par(cursor.par()->Previous());
1336 SetCursor(bview, cursor.par(), cursor.par()->Last());
1337 /* this is just faster than using CursorLeft(); */
1339 firsttmppar = cursor.par()->ParFromPos(cursor.pos());
1340 tmppar = firsttmppar;
1341 /* tmppar is now the paragraph right before the footnote */
1343 bool first_footnote_par_is_not_empty = tmppar->next->size();
1346 && tmppar->next->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1347 tmppar = tmppar->next; /* I use next instead of Next(),
1348 * because there cannot be any
1349 * footnotes in a footnote
1351 tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE;
1353 /* remember the captions and empty paragraphs */
1354 if ((textclasslist.Style(bview->buffer()->params.textclass,
1355 tmppar->GetLayout())
1356 .labeltype == LABEL_SENSITIVE)
1358 tmppar->SetLayout(bview->buffer()->params, 0);
1361 // now we will paste the ex-footnote, if the layouts allow it
1362 // first restore the layout of the paragraph right behind
1365 tmppar->next->MakeSameLayout(cursor.par());
1368 if (!tmppar->GetLayout()
1370 && (!tmppar->Next()->Last()
1371 || tmppar->Next()->HasSameLayout(tmppar)))) {
1372 if (tmppar->Next()->Last()
1373 && tmppar->Next()->IsLineSeparator(0))
1374 tmppar->Next()->Erase(0);
1375 tmppar->PasteParagraph(bview->buffer()->params);
1378 tmppar = tmppar->Next(); /* make sure tmppar cannot be touched
1379 * by the pasting of the beginning */
1381 /* then the beginning */
1382 /* if there is no space between the text and the footnote, so we insert
1384 * (only if the previous par and the footnotepar are not empty!) */
1385 if (!firsttmppar->next->GetLayout()
1386 || firsttmppar->HasSameLayout(firsttmppar->next)) {
1387 if (firsttmppar->size()
1388 && !firsttmppar->IsSeparator(firsttmppar->size() - 1)
1389 && first_footnote_par_is_not_empty) {
1390 firsttmppar->next->InsertChar(0, ' ');
1392 firsttmppar->PasteParagraph(bview->buffer()->params);
1395 /* now redo the paragaphs */
1396 RedoParagraphs(bview, cursor, tmppar);
1398 SetCursor(bview, cursor.par(), cursor.pos());
1400 /* sometimes it can happen, that there is a counter change */
1401 Row * row = cursor.row();
1402 while (row->next() && row->par() != tmppar && row->next()->par() != tmppar)
1404 UpdateCounters(bview, row);
1412 /* the DTP switches for paragraphs. LyX will store them in the
1413 * first physicla paragraph. When a paragraph is broken, the top settings
1414 * rest, the bottom settings are given to the new one. So I can make shure,
1415 * they do not duplicate themself and you cannnot make dirty things with
1418 void LyXText::SetParagraph(BufferView * bview,
1419 bool line_top, bool line_bottom,
1420 bool pagebreak_top, bool pagebreak_bottom,
1421 VSpace const & space_top,
1422 VSpace const & space_bottom,
1424 string labelwidthstring,
1427 LyXCursor tmpcursor = cursor;
1429 sel_start_cursor = cursor;
1430 sel_end_cursor = cursor;
1433 // make sure that the depth behind the selection are restored, too
1435 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
1437 LyXParagraph * endpar = sel_end_cursor.par()->Next();
1439 LyXParagraph * undoendpar = endpar;
1441 if (endpar && endpar->GetDepth()) {
1442 while (endpar && endpar->GetDepth()) {
1444 endpar = endpar->LastPhysicalPar()->Next();
1446 endpar = endpar->Next();
1448 undoendpar = endpar;
1452 endpar = endpar->Next(); // because of parindents etc.
1455 SetUndo(bview->buffer(), Undo::EDIT,
1458 .par()->ParFromPos(sel_start_cursor.pos())->previous,
1460 sel_start_cursor.par()->previous,
1465 LyXParagraph * tmppar = sel_end_cursor.par();
1467 while (tmppar != sel_start_cursor.par()->FirstPhysicalPar()->Previous()) {
1468 SetCursor(bview, tmppar->FirstPhysicalPar(), 0);
1470 while (tmppar != sel_start_cursor.par()->Previous()) {
1471 SetCursor(bview, tmppar, 0);
1473 status = LyXText::NEED_MORE_REFRESH;
1474 refresh_row = cursor.row();
1475 refresh_y = cursor.y() - cursor.row()->baseline();
1477 if (cursor.par()->footnoteflag ==
1478 sel_start_cursor.par()->footnoteflag) {
1480 cursor.par()->line_top = line_top;
1481 cursor.par()->line_bottom = line_bottom;
1482 cursor.par()->pagebreak_top = pagebreak_top;
1483 cursor.par()->pagebreak_bottom = pagebreak_bottom;
1484 cursor.par()->added_space_top = space_top;
1485 cursor.par()->added_space_bottom = space_bottom;
1486 // does the layout allow the new alignment?
1487 if (align == LYX_ALIGN_LAYOUT)
1488 align = textclasslist
1489 .Style(bview->buffer()->params.textclass,
1490 cursor.par()->GetLayout()).align;
1491 if (align & textclasslist
1492 .Style(bview->buffer()->params.textclass,
1493 cursor.par()->GetLayout()).alignpossible) {
1494 if (align == textclasslist
1495 .Style(bview->buffer()->params.textclass,
1496 cursor.par()->GetLayout()).align)
1497 cursor.par()->align = LYX_ALIGN_LAYOUT;
1499 cursor.par()->align = align;
1501 cursor.par()->SetLabelWidthString(labelwidthstring);
1502 cursor.par()->noindent = noindent;
1506 tmppar = cursor.par()->FirstPhysicalPar()->Previous();
1508 tmppar = cursor.par()->Previous();
1512 RedoParagraphs(bview, sel_start_cursor, endpar);
1515 SetCursor(bview, sel_start_cursor.par(), sel_start_cursor.pos());
1516 sel_cursor = cursor;
1517 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
1519 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
1521 bview->updateInset(inset_owner, true);
1525 void LyXText::SetParagraphExtraOpt(BufferView * bview, int type,
1526 string const & width,
1527 string const & widthp,
1528 int alignment, bool hfill,
1529 bool start_minipage)
1531 LyXCursor tmpcursor = cursor;
1532 LyXParagraph * tmppar;
1534 sel_start_cursor = cursor;
1535 sel_end_cursor = cursor;
1538 // make sure that the depth behind the selection are restored, too
1540 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
1542 LyXParagraph * endpar = sel_end_cursor.par()->Next();
1544 LyXParagraph * undoendpar = endpar;
1546 if (endpar && endpar->GetDepth()) {
1547 while (endpar && endpar->GetDepth()) {
1549 endpar = endpar->LastPhysicalPar()->Next();
1551 endpar = endpar->Next();
1553 undoendpar = endpar;
1557 endpar = endpar->Next(); // because of parindents etc.
1560 SetUndo(bview->buffer(), Undo::EDIT,
1563 .par()->ParFromPos(sel_start_cursor.pos())->previous,
1565 sel_start_cursor.par()->previous,
1569 tmppar = sel_end_cursor.par();
1571 while(tmppar != sel_start_cursor.par()->FirstPhysicalPar()->Previous()) {
1572 SetCursor(bview, tmppar->FirstPhysicalPar(), 0);
1574 while(tmppar != sel_start_cursor.par()->Previous()) {
1575 SetCursor(bview, tmppar, 0);
1577 status = LyXText::NEED_MORE_REFRESH;
1578 refresh_row = cursor.row();
1579 refresh_y = cursor.y() - cursor.row()->baseline();
1581 if (cursor.par()->footnoteflag ==
1582 sel_start_cursor.par()->footnoteflag) {
1584 if (type == LyXParagraph::PEXTRA_NONE) {
1585 if (cursor.par()->pextra_type != LyXParagraph::PEXTRA_NONE) {
1586 cursor.par()->UnsetPExtraType(bview->buffer()->params);
1587 cursor.par()->pextra_type = LyXParagraph::PEXTRA_NONE;
1590 cursor.par()->SetPExtraType(bview->buffer()->params,
1591 type, width, widthp);
1592 cursor.par()->pextra_hfill = hfill;
1593 cursor.par()->pextra_start_minipage = start_minipage;
1594 cursor.par()->pextra_alignment = alignment;
1598 tmppar = cursor.par()->FirstPhysicalPar()->Previous();
1600 tmppar = cursor.par()->Previous();
1603 RedoParagraphs(bview, sel_start_cursor, endpar);
1605 SetCursor(bview, sel_start_cursor.par(), sel_start_cursor.pos());
1606 sel_cursor = cursor;
1607 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
1609 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
1613 char loweralphaCounter(int n)
1615 if (n < 1 || n > 26)
1623 char alphaCounter(int n)
1625 if (n < 1 || n > 26)
1633 char hebrewCounter(int n)
1635 static const char hebrew[22] = {
1636 'à ', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è',
1637 'é', 'ë', 'ì', 'î', 'ð', 'ñ', 'ò', 'ô', 'ö',
1638 '÷', 'ø', 'ù', 'ú'
1640 if (n < 1 || n > 22)
1648 string const romanCounter(int n)
1650 static char const * roman[20] = {
1651 "i", "ii", "iii", "iv", "v",
1652 "vi", "vii", "viii", "ix", "x",
1653 "xi", "xii", "xiii", "xiv", "xv",
1654 "xvi", "xvii", "xviii", "xix", "xx"
1656 if (n < 1 || n > 20)
1663 // set the counter of a paragraph. This includes the labels
1664 void LyXText::SetCounter(Buffer const * buf, LyXParagraph * par) const
1667 // this is only relevant for the beginning of paragraph
1668 par = par->FirstPhysicalPar();
1670 LyXLayout const & layout =
1671 textclasslist.Style(buf->params.textclass,
1674 LyXTextClass const & textclass =
1675 textclasslist.TextClass(buf->params.textclass);
1677 /* copy the prev-counters to this one, unless this is the start of a
1678 footnote or of a bibliography or the very first paragraph */
1681 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1682 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1683 && par->footnotekind == LyXParagraph::FOOTNOTE)
1685 && !(textclasslist.Style(buf->params.textclass,
1686 par->Previous()->GetLayout()
1687 ).labeltype != LABEL_BIBLIO
1688 && layout.labeltype == LABEL_BIBLIO)) {
1689 for (int i = 0; i < 10; ++i) {
1690 par->setCounter(i, par->Previous()->GetFirstCounter(i));
1693 par->appendix = par->Previous()->FirstPhysicalPar()->appendix;
1695 par->appendix = par->Previous()->appendix;
1697 if (!par->appendix && par->start_of_appendix){
1698 par->appendix = true;
1699 for (int i = 0; i < 10; ++i) {
1700 par->setCounter(i, 0);
1704 par->enumdepth = par->Previous()->FirstPhysicalPar()->enumdepth;
1705 par->itemdepth = par->Previous()->FirstPhysicalPar()->itemdepth;
1707 par->enumdepth = par->Previous()->enumdepth;
1708 par->itemdepth = par->Previous()->itemdepth;
1711 for (int i = 0; i < 10; ++i) {
1712 par->setCounter(i, 0);
1714 par->appendix = par->start_of_appendix;
1720 // if this is an open marginnote and this is the first
1721 // entry in the marginnote and the enclosing
1722 // environment is an enum/item then correct for the
1723 // LaTeX behaviour (ARRae)
1724 if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1725 && par->footnotekind == LyXParagraph::MARGIN
1727 && par->Previous()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE
1728 && (par->PreviousBeforeFootnote()
1729 && textclasslist.Style(buf->params.textclass,
1730 par->PreviousBeforeFootnote()->GetLayout()
1731 ).labeltype >= LABEL_COUNTER_ENUMI)) {
1732 // Any itemize or enumerate environment in a marginnote
1733 // that is embedded in an itemize or enumerate
1734 // paragraph is seen by LaTeX as being at a deeper
1735 // level within that enclosing itemization/enumeration
1736 // even if there is a "standard" layout at the start of
1742 /* Maybe we have to increment the enumeration depth.
1743 * BUT, enumeration in a footnote is considered in isolation from its
1744 * surrounding paragraph so don't increment if this is the
1745 * first line of the footnote
1746 * AND, bibliographies can't have their depth changed ie. they
1747 * are always of depth 0
1750 && par->Previous()->GetDepth() < par->GetDepth()
1751 && textclasslist.Style(buf->params.textclass,
1752 par->Previous()->GetLayout()
1753 ).labeltype == LABEL_COUNTER_ENUMI
1754 && par->enumdepth < 3
1756 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1757 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1758 && par->footnotekind == LyXParagraph::FOOTNOTE)
1760 && layout.labeltype != LABEL_BIBLIO) {
1764 /* Maybe we have to decrement the enumeration depth, see note above */
1766 && par->Previous()->GetDepth() > par->GetDepth()
1768 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1769 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1770 && par->footnotekind == LyXParagraph::FOOTNOTE)
1772 && layout.labeltype != LABEL_BIBLIO) {
1773 par->enumdepth = par->DepthHook(par->GetDepth())->enumdepth;
1774 par->setCounter(6 + par->enumdepth,
1775 par->DepthHook(par->GetDepth())->getCounter(6 + par->enumdepth));
1776 /* reset the counters.
1777 * A depth change is like a breaking layout
1779 for (int i = 6 + par->enumdepth + 1; i < 10; ++i)
1780 par->setCounter(i, 0);
1783 if (!par->labelstring.empty()) {
1784 par->labelstring.erase();
1787 if (layout.margintype == MARGIN_MANUAL) {
1788 if (par->labelwidthstring.empty()) {
1789 par->SetLabelWidthString(layout.labelstring());
1792 par->SetLabelWidthString(string());
1795 /* is it a layout that has an automatic label ? */
1796 if (layout.labeltype >= LABEL_COUNTER_CHAPTER) {
1798 int i = layout.labeltype - LABEL_COUNTER_CHAPTER;
1799 if (i >= 0 && i<= buf->params.secnumdepth) {
1800 par->incCounter(i); // increment the counter
1802 // Is there a label? Useful for Chapter layout
1803 if (!par->appendix){
1804 if (!layout.labelstring().empty())
1805 par->labelstring = layout.labelstring();
1807 par->labelstring.erase();
1809 if (!layout.labelstring_appendix().empty())
1810 par->labelstring = layout.labelstring_appendix();
1812 par->labelstring.erase();
1815 std::ostringstream s;
1817 if (!par->appendix) {
1818 switch (2 * LABEL_COUNTER_CHAPTER -
1819 textclass.maxcounter() + i) {
1820 case LABEL_COUNTER_CHAPTER:
1821 s << par->getCounter(i);
1823 case LABEL_COUNTER_SECTION:
1824 s << par->getCounter(i - 1) << '.'
1825 << par->getCounter(i);
1827 case LABEL_COUNTER_SUBSECTION:
1828 s << par->getCounter(i - 2) << '.'
1829 << par->getCounter(i - 1) << '.'
1830 << par->getCounter(i);
1832 case LABEL_COUNTER_SUBSUBSECTION:
1833 s << par->getCounter(i - 3) << '.'
1834 << par->getCounter(i - 2) << '.'
1835 << par->getCounter(i - 1) << '.'
1836 << par->getCounter(i);
1839 case LABEL_COUNTER_PARAGRAPH:
1840 s << par->getCounter(i - 4) << '.'
1841 << par->getCounter(i - 3) << '.'
1842 << par->getCounter(i - 2) << '.'
1843 << par->getCounter(i - 1) << '.'
1844 << par->getCounter(i);
1846 case LABEL_COUNTER_SUBPARAGRAPH:
1847 s << par->getCounter(i - 5) << '.'
1848 << par->getCounter(i - 4) << '.'
1849 << par->getCounter(i - 3) << '.'
1850 << par->getCounter(i - 2) << '.'
1851 << par->getCounter(i - 1) << '.'
1852 << par->getCounter(i);
1856 // Can this ever be reached? And in the
1857 // case it is, how can this be correct?
1859 s << par->getCounter(i) << '.';
1862 } else { // appendix
1863 switch (2 * LABEL_COUNTER_CHAPTER - textclass.maxcounter() + i) {
1864 case LABEL_COUNTER_CHAPTER:
1865 if (par->isRightToLeftPar(buf->params))
1866 s << hebrewCounter(par->getCounter(i));
1868 s << alphaCounter(par->getCounter(i));
1870 case LABEL_COUNTER_SECTION:
1871 if (par->isRightToLeftPar(buf->params))
1872 s << hebrewCounter(par->getCounter(i - 1));
1874 s << alphaCounter(par->getCounter(i - 1));
1877 << par->getCounter(i);
1880 case LABEL_COUNTER_SUBSECTION:
1881 if (par->isRightToLeftPar(buf->params))
1882 s << hebrewCounter(par->getCounter(i - 2));
1884 s << alphaCounter(par->getCounter(i - 2));
1887 << par->getCounter(i-1) << '.'
1888 << par->getCounter(i);
1891 case LABEL_COUNTER_SUBSUBSECTION:
1892 if (par->isRightToLeftPar(buf->params))
1893 s << hebrewCounter(par->getCounter(i-3));
1895 s << alphaCounter(par->getCounter(i-3));
1898 << par->getCounter(i-2) << '.'
1899 << par->getCounter(i-1) << '.'
1900 << par->getCounter(i);
1903 case LABEL_COUNTER_PARAGRAPH:
1904 if (par->isRightToLeftPar(buf->params))
1905 s << hebrewCounter(par->getCounter(i-4));
1907 s << alphaCounter(par->getCounter(i-4));
1910 << par->getCounter(i-3) << '.'
1911 << par->getCounter(i-2) << '.'
1912 << par->getCounter(i-1) << '.'
1913 << par->getCounter(i);
1916 case LABEL_COUNTER_SUBPARAGRAPH:
1917 if (par->isRightToLeftPar(buf->params))
1918 s << hebrewCounter(par->getCounter(i-5));
1920 s << alphaCounter(par->getCounter(i-5));
1923 << par->getCounter(i-4) << '.'
1924 << par->getCounter(i-3) << '.'
1925 << par->getCounter(i-2) << '.'
1926 << par->getCounter(i-1) << '.'
1927 << par->getCounter(i);
1931 // Can this ever be reached? And in the
1932 // case it is, how can this be correct?
1934 s << par->getCounter(i) << '.';
1940 par->labelstring += s.str().c_str();
1941 // We really want to remove the c_str as soon as
1944 for (i++; i < 10; ++i) {
1945 // reset the following counters
1946 par->setCounter(i, 0);
1948 } else if (layout.labeltype < LABEL_COUNTER_ENUMI) {
1949 for (i++; i < 10; ++i) {
1950 // reset the following counters
1951 par->setCounter(i, 0);
1953 } else if (layout.labeltype == LABEL_COUNTER_ENUMI) {
1954 par->incCounter(i + par->enumdepth);
1955 int number = par->getCounter(i + par->enumdepth);
1957 std::ostringstream s;
1959 switch (par->enumdepth) {
1961 if (par->isRightToLeftPar(buf->params))
1963 << hebrewCounter(number)
1967 << loweralphaCounter(number)
1971 if (par->isRightToLeftPar(buf->params))
1972 s << '.' << romanCounter(number);
1974 s << romanCounter(number) << '.';
1977 if (par->isRightToLeftPar(buf->params))
1979 << alphaCounter(number);
1981 s << alphaCounter(number)
1985 if (par->isRightToLeftPar(buf->params))
1992 par->labelstring = s.str().c_str();
1993 // we really want to get rid of that c_str()
1995 for (i += par->enumdepth + 1; i < 10; ++i)
1996 par->setCounter(i, 0); /* reset the following counters */
1999 } else if (layout.labeltype == LABEL_BIBLIO) {// ale970302
2000 int i = LABEL_COUNTER_ENUMI - LABEL_COUNTER_CHAPTER + par->enumdepth;
2002 int number = par->getCounter(i);
2004 InsetCommandParams p( "bibitem" );
2005 par->bibkey = new InsetBibKey(p);
2007 par->bibkey->setCounter(number);
2008 par->labelstring = layout.labelstring();
2010 // In biblio should't be following counters but...
2012 string s = layout.labelstring();
2014 // the caption hack:
2015 if (layout.labeltype == LABEL_SENSITIVE) {
2016 bool isOK (par->InInset() && par->InInset()->owner() &&
2017 (par->InInset()->owner()->LyxCode() == Inset::FLOAT_CODE));
2019 if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2020 && (par->footnotekind == LyXParagraph::FIG
2021 || par->footnotekind == LyXParagraph::WIDE_FIG)) {
2022 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2023 ? ":øåéà " : "Figure:";
2024 } else if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2025 && (par->footnotekind == LyXParagraph::TAB
2026 || par->footnotekind == LyXParagraph::WIDE_TAB)) {
2027 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2028 ? ":äìáè" : "Table:";
2029 } else if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2030 && par->footnotekind == LyXParagraph::ALGORITHM) {
2031 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2032 ? ":Ãúéøåâìà " : "Algorithm:";
2036 InsetFloat * tmp = static_cast<InsetFloat*>(par->InInset()->owner());
2038 = floatList.getType(tmp->type());
2039 // We should get the correct number here too.
2040 s = fl.name() + " #:";
2042 /* par->SetLayout(0);
2043 s = layout->labelstring; */
2044 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2045 ? " :úåòîùî øñç" : "Senseless: ";
2048 par->labelstring = s;
2050 /* reset the enumeration counter. They are always resetted
2051 * when there is any other layout between */
2052 for (int i = 6 + par->enumdepth; i < 10; ++i)
2053 par->setCounter(i, 0);
2058 /* Updates all counters BEHIND the row. Changed paragraphs
2059 * with a dynamic left margin will be rebroken. */
2060 void LyXText::UpdateCounters(BufferView * bview, Row * row) const
2067 if (row->par()->next
2069 && row->par()->next->footnoteflag != LyXParagraph::OPEN_FOOTNOTE
2073 par = row->par()->LastPhysicalPar()->Next();
2075 par = row->par()->Next();
2078 par = row->par()->next;
2083 while (row->par() != par)
2086 SetCounter(bview->buffer(), par);
2088 /* now check for the headline layouts. remember that they
2089 * have a dynamic left margin */
2094 ( textclasslist.Style(bview->buffer()->params.textclass,
2095 par->layout).margintype == MARGIN_DYNAMIC
2096 || textclasslist.Style(bview->buffer()->params.textclass,
2097 par->layout).labeltype == LABEL_SENSITIVE)
2100 /* Rebreak the paragraph */
2101 RemoveParagraph(row);
2102 AppendParagraph(bview, row);
2105 /* think about the damned open footnotes! */
2106 while (par->Next() &&
2107 (par->Next()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
2108 || par->Next()->IsDummy())){
2110 if (par->IsDummy()) {
2111 while (row->par() != par)
2113 RemoveParagraph(row);
2114 AppendParagraph(bview, row);
2120 par = par->LastPhysicalPar()->Next();
2129 /* insets an inset. */
2130 void LyXText::InsertInset(BufferView * bview, Inset * inset)
2132 if (!cursor.par()->InsertInsetAllowed(inset))
2134 SetUndo(bview->buffer(), Undo::INSERT,
2136 cursor.par()->ParFromPos(cursor.pos())->previous,
2137 cursor.par()->ParFromPos(cursor.pos())->next
2139 cursor.par()->previous,
2143 cursor.par()->InsertInset(cursor.pos(), inset);
2144 InsertChar(bview, LyXParagraph::META_INSET); /* just to rebreak and refresh correctly.
2145 * The character will not be inserted a
2148 // If we enter a highly editable inset the cursor should be to before
2149 // the inset. This couldn't happen before as Undo was not handled inside
2150 // inset now after the Undo LyX tries to call inset->Edit(...) again
2151 // and cannot do this as the cursor is behind the inset and GetInset
2152 // does not return the inset!
2153 if (inset->Editable() == Inset::HIGHLY_EDITABLE) {
2154 CursorLeft(bview, true);
2160 void LyXText::copyEnvironmentType()
2162 copylayouttype = cursor.par()->GetLayout();
2166 void LyXText::pasteEnvironmentType(BufferView * bview)
2168 SetLayout(bview, copylayouttype);
2172 void LyXText::CutSelection(BufferView * bview, bool doclear)
2174 // Stuff what we got on the clipboard. Even if there is no selection.
2176 // There is a problem with having the stuffing here in that the
2177 // larger the selection the slower LyX will get. This can be
2178 // solved by running the line below only when the selection has
2179 // finished. The solution used currently just works, to make it
2180 // faster we need to be more clever and probably also have more
2181 // calls to stuffClipboard. (Lgb)
2182 bview->stuffClipboard(selectionAsString(bview->buffer()));
2184 // This doesn't make sense, if there is no selection
2188 // OK, we have a selection. This is always between sel_start_cursor
2189 // and sel_end_cursor
2191 // Check whether there are half footnotes in the selection
2192 if (sel_start_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE
2193 || sel_end_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2194 LyXParagraph * tmppar = sel_start_cursor.par();
2195 while (tmppar != sel_end_cursor.par()){
2196 if (tmppar->footnoteflag != sel_end_cursor.par()->footnoteflag) {
2197 WriteAlert(_("Impossible operation"),
2198 _("Don't know what to do with half floats."),
2202 tmppar = tmppar->Next();
2207 // make sure that the depth behind the selection are restored, too
2209 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
2211 LyXParagraph * endpar = sel_end_cursor.par()->Next();
2213 LyXParagraph * undoendpar = endpar;
2215 if (endpar && endpar->GetDepth()) {
2216 while (endpar && endpar->GetDepth()) {
2218 endpar = endpar->LastPhysicalPar()->Next();
2220 endpar = endpar->Next();
2222 undoendpar = endpar;
2224 } else if (endpar) {
2225 endpar = endpar->Next(); // because of parindents etc.
2228 SetUndo(bview->buffer(), Undo::DELETE,
2231 .par()->ParFromPos(sel_start_cursor.pos())->previous,
2233 sel_start_cursor.par()->previous,
2239 // there are two cases: cut only within one paragraph or
2240 // more than one paragraph
2242 if (sel_start_cursor.par()->ParFromPos(sel_start_cursor.pos())
2243 == sel_end_cursor.par()->ParFromPos(sel_end_cursor.pos()))
2245 if (sel_start_cursor.par() == sel_end_cursor.par())
2248 // only within one paragraph
2249 endpar = sel_start_cursor.par();
2250 int pos = sel_end_cursor.pos();
2251 cap.cutSelection(sel_start_cursor.par(), &endpar,
2252 sel_start_cursor.pos(), pos,
2253 bview->buffer()->params.textclass, doclear);
2254 sel_end_cursor.pos(pos);
2256 endpar = sel_end_cursor.par();
2258 int pos = sel_end_cursor.pos();
2259 cap.cutSelection(sel_start_cursor.par(), &endpar,
2260 sel_start_cursor.pos(), pos,
2261 bview->buffer()->params.textclass, doclear);
2263 sel_end_cursor.par(endpar);
2264 sel_end_cursor.pos(pos);
2265 cursor.pos(sel_end_cursor.pos());
2267 endpar = endpar->Next();
2269 // sometimes necessary
2271 sel_start_cursor.par()->StripLeadingSpaces(bview->buffer()->params.textclass);
2273 RedoParagraphs(bview, sel_start_cursor, endpar);
2276 cursor = sel_start_cursor;
2277 SetCursor(bview, cursor.par(), cursor.pos());
2278 sel_cursor = cursor;
2279 UpdateCounters(bview, cursor.row());
2283 void LyXText::CopySelection(BufferView * bview)
2285 // Stuff what we got on the clipboard. Even if there is no selection.
2287 // There is a problem with having the stuffing here in that the
2288 // larger the selection the slower LyX will get. This can be
2289 // solved by running the line below only when the selection has
2290 // finished. The solution used currently just works, to make it
2291 // faster we need to be more clever and probably also have more
2292 // calls to stuffClipboard. (Lgb)
2293 bview->stuffClipboard(selectionAsString(bview->buffer()));
2295 // this doesnt make sense, if there is no selection
2299 // ok we have a selection. This is always between sel_start_cursor
2300 // and sel_end cursor
2303 /* check wether there are half footnotes in the selection */
2304 if (sel_start_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE
2305 || sel_end_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2306 LyXParagraph * tmppar = sel_start_cursor.par();
2307 while (tmppar != sel_end_cursor.par()) {
2308 if (tmppar->footnoteflag !=
2309 sel_end_cursor.par()->footnoteflag) {
2310 WriteAlert(_("Impossible operation"),
2311 _("Don't know what to do"
2312 " with half floats."),
2316 tmppar = tmppar->Next();
2321 // copy behind a space if there is one
2322 while (sel_start_cursor.par()->Last() > sel_start_cursor.pos()
2323 && sel_start_cursor.par()->IsLineSeparator(sel_start_cursor.pos())
2324 && (sel_start_cursor.par() != sel_end_cursor.par()
2325 || sel_start_cursor.pos() < sel_end_cursor.pos()))
2326 sel_start_cursor.pos(sel_start_cursor.pos() + 1);
2330 cap.copySelection(sel_start_cursor.par(), sel_end_cursor.par(),
2331 sel_start_cursor.pos(), sel_end_cursor.pos(),
2332 bview->buffer()->params.textclass);
2336 void LyXText::PasteSelection(BufferView * bview)
2340 // this does not make sense, if there is nothing to paste
2341 if (!cap.checkPastePossible(cursor.par(), cursor.pos()))
2344 SetUndo(bview->buffer(), Undo::INSERT,
2346 cursor.par()->ParFromPos(cursor.pos())->previous,
2347 cursor.par()->ParFromPos(cursor.pos())->next
2349 cursor.par()->previous,
2354 LyXParagraph * endpar;
2355 LyXParagraph * actpar = cursor.par();
2357 int pos = cursor.pos();
2358 cap.pasteSelection(&actpar, &endpar, pos, bview->buffer()->params.textclass);
2360 RedoParagraphs(bview, cursor, endpar);
2362 SetCursor(bview, cursor.par(), cursor.pos());
2365 sel_cursor = cursor;
2366 SetCursor(bview, actpar, pos);
2368 UpdateCounters(bview, cursor.row());
2372 // returns a pointer to the very first LyXParagraph
2373 LyXParagraph * LyXText::FirstParagraph() const
2375 return OwnerParagraph();
2379 // returns true if the specified string is at the specified position
2380 bool LyXText::IsStringInText(LyXParagraph * par,
2381 LyXParagraph::size_type pos,
2382 string const & str) const
2387 LyXParagraph::size_type i = 0;
2388 while (pos + i < par->Last()
2389 && string::size_type(i) < str.length()
2390 && str[i] == par->GetChar(pos + i)) {
2393 if (str.length() == string::size_type(i))
2399 // sets the selection over the number of characters of string, no check!!
2400 void LyXText::SetSelectionOverString(BufferView * bview, string const & str)
2402 sel_cursor = cursor;
2403 for (int i = 0; str[i]; ++i)
2409 // simple replacing. The font of the first selected character is used
2410 void LyXText::ReplaceSelectionWithString(BufferView * bview,
2413 SetCursorParUndo(bview->buffer());
2416 if (!selection) { // create a dummy selection
2417 sel_end_cursor = cursor;
2418 sel_start_cursor = cursor;
2421 // Get font setting before we cut
2422 LyXParagraph::size_type pos = sel_end_cursor.pos();
2423 LyXFont const font = sel_start_cursor.par()
2424 ->GetFontSettings(bview->buffer()->params,
2425 sel_start_cursor.pos());
2427 // Insert the new string
2428 for (string::const_iterator cit = str.begin(); cit != str.end(); ++cit) {
2429 sel_end_cursor.par()->InsertChar(pos, (*cit), font);
2433 // Cut the selection
2434 CutSelection(bview);
2440 // if the string can be found: return true and set the cursor to
2442 bool LyXText::SearchForward(BufferView * bview, string const & str) const
2444 LyXParagraph * par = cursor.par();
2445 LyXParagraph::size_type pos = cursor.pos();
2446 while (par && !IsStringInText(par, pos, str)) {
2447 if (pos < par->Last() - 1)
2455 SetCursor(bview, par, pos);
2463 bool LyXText::SearchBackward(BufferView * bview, string const & str) const
2465 LyXParagraph * par = cursor.par();
2466 int pos = cursor.pos();
2472 // We skip empty paragraphs (Asger)
2474 par = par->Previous();
2476 pos = par->Last() - 1;
2477 } while (par && pos < 0);
2479 } while (par && !IsStringInText(par, pos, str));
2482 SetCursor(bview, par, pos);
2489 // needed to insert the selection
2490 void LyXText::InsertStringA(BufferView * bview, string const & str)
2492 LyXParagraph * par = cursor.par();
2493 LyXParagraph::size_type pos = cursor.pos();
2494 LyXParagraph::size_type a = 0;
2495 LyXParagraph * endpar = cursor.par()->Next();
2497 SetCursorParUndo(bview->buffer());
2500 textclasslist.Style(bview->buffer()->params.textclass,
2501 cursor.par()->GetLayout()).isEnvironment();
2502 // only to be sure, should not be neccessary
2505 // insert the string, don't insert doublespace
2506 string::size_type i = 0;
2507 while (i < str.length()) {
2508 if (str[i] != '\n') {
2510 && i + 1 < str.length() && str[i + 1] != ' '
2511 && pos && par->GetChar(pos - 1)!= ' ') {
2512 par->InsertChar(pos, ' ', current_font);
2514 } else if (str[i] == ' ') {
2515 InsetSpecialChar * new_inset =
2516 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2517 if (par->InsertInsetAllowed(new_inset)) {
2518 par->InsertInset(pos, new_inset,
2524 } else if (str[i] == '\t') {
2525 for (a = pos; a < (pos / 8 + 1) * 8 ; ++a) {
2526 InsetSpecialChar * new_inset =
2527 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2528 if (par->InsertInsetAllowed(new_inset)) {
2529 par->InsertInset(pos, new_inset,
2536 } else if (str[i] != 13 &&
2537 // Ignore unprintables
2538 (str[i] & 127) >= ' ') {
2539 par->InsertChar(pos, str[i], current_font);
2543 if (!par->size()) { // par is empty
2544 InsetSpecialChar * new_inset =
2545 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2546 if (par->InsertInsetAllowed(new_inset)) {
2547 par->InsertInset(pos,
2555 par->BreakParagraph(bview->buffer()->params, pos, flag);
2562 RedoParagraphs(bview, cursor, endpar);
2563 SetCursor(bview, cursor.par(), cursor.pos());
2564 sel_cursor = cursor;
2565 SetCursor(bview, par, pos);
2570 /* turns double-CR to single CR, others where converted into one blank and 13s
2571 * that are ignored .Double spaces are also converted into one. Spaces at
2572 * the beginning of a paragraph are forbidden. tabs are converted into one
2573 * space. then InsertStringA is called */
2574 void LyXText::InsertStringB(BufferView * bview, string const & s)
2577 string::size_type i = 1;
2578 while (i < str.length()) {
2581 if (str[i] == ' ' && i + 1 < str.length() && str[i + 1] == ' ')
2583 if (str[i] == '\n' && i + 1 < str.length()) {
2584 if (str[i + 1] != '\n') {
2585 if (str[i - 1] != ' ')
2590 while (i + 1 < str.length()
2591 && (str[i + 1] == ' '
2592 || str[i + 1] == '\t'
2593 || str[i + 1] == '\n'
2594 || str[i + 1] == 13)) {
2601 InsertStringA(bview, str);
2605 bool LyXText::GotoNextError(BufferView * bview) const
2607 LyXCursor res = cursor;
2609 if (res.pos() < res.par()->Last() - 1) {
2610 res.pos(res.pos() + 1);
2612 res.par(res.par()->Next());
2616 } while (res.par() &&
2617 !(res.par()->GetChar(res.pos()) == LyXParagraph::META_INSET
2618 && res.par()->GetInset(res.pos())->AutoDelete()));
2621 SetCursor(bview, res.par(), res.pos());
2628 bool LyXText::GotoNextNote(BufferView * bview) const
2630 LyXCursor res = cursor;
2632 if (res.pos() < res.par()->Last() - 1) {
2633 res.pos(res.pos() + 1);
2635 res.par(res.par()->Next());
2639 } while (res.par() &&
2640 !(res.par()->GetChar(res.pos()) == LyXParagraph::META_INSET
2641 && res.par()->GetInset(res.pos())->LyxCode() == Inset::IGNORE_CODE));
2644 SetCursor(bview, res.par(), res.pos());
2651 void LyXText::CheckParagraph(BufferView * bview, LyXParagraph * par,
2652 LyXParagraph::size_type pos)
2654 LyXCursor tmpcursor;
2657 LyXParagraph::size_type z;
2658 Row * row = GetRow(par, pos, y);
2660 // is there a break one row above
2661 if (row->previous() && row->previous()->par() == row->par()) {
2662 z = NextBreakPoint(bview, row->previous(), workWidth(bview));
2663 if (z >= row->pos()) {
2664 // set the dimensions of the row above
2665 y -= row->previous()->height();
2667 refresh_row = row->previous();
2668 status = LyXText::NEED_MORE_REFRESH;
2670 BreakAgain(bview, row->previous());
2672 // set the cursor again. Otherwise
2673 // dangling pointers are possible
2674 SetCursor(bview, cursor.par(), cursor.pos(),
2675 false, cursor.boundary());
2676 sel_cursor = cursor;
2681 int const tmpheight = row->height();
2682 LyXParagraph::size_type const tmplast = RowLast(row);
2686 BreakAgain(bview, row);
2687 if (row->height() == tmpheight && RowLast(row) == tmplast)
2688 status = LyXText::NEED_VERY_LITTLE_REFRESH;
2690 status = LyXText::NEED_MORE_REFRESH;
2692 // check the special right address boxes
2693 if (textclasslist.Style(bview->buffer()->params.textclass,
2694 par->GetLayout()).margintype
2695 == MARGIN_RIGHT_ADDRESS_BOX) {
2702 RedoDrawingOfParagraph(bview, tmpcursor);
2705 // set the cursor again. Otherwise dangling pointers are possible
2706 // also set the selection
2710 SetCursorIntern(bview, sel_cursor.par(), sel_cursor.pos(),
2711 false, sel_cursor.boundary());
2712 sel_cursor = cursor;
2713 SetCursorIntern(bview, sel_start_cursor.par(),
2714 sel_start_cursor.pos(),
2715 false, sel_start_cursor.boundary());
2716 sel_start_cursor = cursor;
2717 SetCursorIntern(bview, sel_end_cursor.par(),
2718 sel_end_cursor.pos(),
2719 false, sel_end_cursor.boundary());
2720 sel_end_cursor = cursor;
2721 SetCursorIntern(bview, last_sel_cursor.par(),
2722 last_sel_cursor.pos(),
2723 false, last_sel_cursor.boundary());
2724 last_sel_cursor = cursor;
2727 SetCursorIntern(bview, cursor.par(), cursor.pos(),
2728 false, cursor.boundary());
2732 // returns false if inset wasn't found
2733 bool LyXText::UpdateInset(BufferView * bview, Inset * inset)
2735 // first check the current paragraph
2736 int pos = cursor.par()->GetPositionOfInset(inset);
2738 CheckParagraph(bview, cursor.par(), pos);
2742 // check every paragraph
2744 LyXParagraph * par = FirstParagraph();
2747 // make sure the paragraph is open
2748 if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
2750 pos = par->GetPositionOfInset(inset);
2752 CheckParagraph(bview, par, pos);
2765 void LyXText::SetCursor(BufferView * bview, LyXParagraph * par,
2766 LyXParagraph::size_type pos,
2767 bool setfont, bool boundary) const
2769 LyXCursor old_cursor = cursor;
2770 SetCursorIntern(bview, par, pos, setfont, boundary);
2771 DeleteEmptyParagraphMechanism(bview, old_cursor);
2775 void LyXText::SetCursor(BufferView *bview, LyXCursor & cur, LyXParagraph * par,
2776 LyXParagraph::size_type pos, bool boundary) const
2779 // correct the cursor position if impossible
2780 if (pos > par->Last()){
2781 LyXParagraph * tmppar = par->ParFromPos(pos);
2782 pos = par->PositionInParFromPos(pos);
2785 if (par->IsDummy() && par->previous &&
2786 par->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2787 while (par->previous &&
2788 ((par->previous->IsDummy() &&
2789 (par->previous->previous->footnoteflag ==
2790 LyXParagraph::CLOSED_FOOTNOTE)) ||
2791 (par->previous->footnoteflag ==
2792 LyXParagraph::CLOSED_FOOTNOTE))) {
2793 par = par->previous ;
2794 if (par->IsDummy() &&
2795 (par->previous->footnoteflag ==
2796 LyXParagraph::CLOSED_FOOTNOTE))
2797 pos += par->size() + 1;
2799 if (par->previous) {
2800 par = par->previous;
2802 pos += par->size() + 1;
2807 cur.boundary(boundary);
2809 /* get the cursor y position in text */
2811 Row * row = GetRow(par, pos, y);
2812 /* y is now the beginning of the cursor row */
2813 y += row->baseline();
2814 /* y is now the cursor baseline */
2817 /* now get the cursors x position */
2819 float fill_separator, fill_hfill, fill_label_hfill;
2820 PrepareToPrint(bview, row, x, fill_separator, fill_hfill,
2822 LyXParagraph::size_type cursor_vpos = 0;
2823 LyXParagraph::size_type last = RowLastPrintable(row);
2825 if (pos > last + 1) // This shouldn't happen.
2827 else if (pos < row->pos())
2830 if (last < row->pos())
2831 cursor_vpos = row->pos();
2832 else if (pos > last && !boundary)
2833 cursor_vpos = (row->par()->isRightToLeftPar(bview->buffer()->params))
2834 ? row->pos() : last + 1;
2835 else if (pos > row->pos() &&
2836 (pos > last || boundary))
2837 /// Place cursor after char at (logical) position pos - 1
2838 cursor_vpos = (bidi_level(pos - 1) % 2 == 0)
2839 ? log2vis(pos - 1) + 1 : log2vis(pos - 1);
2841 /// Place cursor before char at (logical) position pos
2842 cursor_vpos = (bidi_level(pos) % 2 == 0)
2843 ? log2vis(pos) : log2vis(pos) + 1;
2845 LyXParagraph::size_type main_body =
2846 BeginningOfMainBody(bview->buffer(), row->par());
2847 if ((main_body > 0) &&
2848 ((main_body-1 > last) ||
2849 !row->par()->IsLineSeparator(main_body-1)))
2852 for (LyXParagraph::size_type vpos = row->pos();
2853 vpos < cursor_vpos; ++vpos) {
2854 pos = vis2log(vpos);
2855 if (main_body > 0 && pos == main_body - 1) {
2856 x += fill_label_hfill +
2857 lyxfont::width(textclasslist.Style(
2858 bview->buffer()->params.textclass,
2859 row->par()->GetLayout())
2861 GetFont(bview->buffer(), row->par(), -2));
2862 if (row->par()->IsLineSeparator(main_body-1))
2863 x -= SingleWidth(bview, row->par(),main_body-1);
2865 if (HfillExpansion(bview->buffer(), row, pos)) {
2866 x += SingleWidth(bview, row->par(), pos);
2867 if (pos >= main_body)
2870 x += fill_label_hfill;
2871 } else if (row->par()->IsSeparator(pos)) {
2872 x += SingleWidth(bview, row->par(), pos);
2873 if (pos >= main_body)
2874 x += fill_separator;
2876 x += SingleWidth(bview, row->par(), pos);
2885 void LyXText::SetCursorIntern(BufferView * bview, LyXParagraph * par,
2886 LyXParagraph::size_type pos,
2887 bool setfont, bool boundary) const
2889 SetCursor(bview, cursor, par, pos, boundary);
2891 SetCurrentFont(bview);
2895 void LyXText::SetCurrentFont(BufferView * bview) const
2897 LyXParagraph::size_type pos = cursor.pos();
2898 if (cursor.boundary() && pos > 0)
2902 if (pos == cursor.par()->Last())
2904 else if (cursor.par()->IsSeparator(pos)) {
2905 if (pos > cursor.row()->pos() &&
2906 bidi_level(pos) % 2 ==
2907 bidi_level(pos - 1) % 2)
2909 else if (pos + 1 < cursor.par()->Last())
2915 cursor.par()->GetFontSettings(bview->buffer()->params, pos);
2916 real_current_font = GetFont(bview->buffer(), cursor.par(), pos);
2918 if (cursor.pos() == cursor.par()->Last() &&
2919 IsBoundary(bview->buffer(), cursor.par(), cursor.pos()) &&
2920 !cursor.boundary()) {
2921 Language const * lang =
2922 cursor.par()->getParLanguage(bview->buffer()->params);
2923 current_font.setLanguage(lang);
2924 real_current_font.setLanguage(lang);
2929 void LyXText::SetCursorFromCoordinates(BufferView * bview, int x, int y) const
2931 LyXCursor old_cursor = cursor;
2933 /* get the row first */
2935 Row * row = GetRowNearY(y);
2936 cursor.par(row->par());
2939 int column = GetColumnNearX(bview, row, x, bound);
2940 cursor.pos(row->pos() + column);
2942 cursor.y(y + row->baseline());
2944 cursor.boundary(bound);
2945 SetCurrentFont(bview);
2946 DeleteEmptyParagraphMechanism(bview, old_cursor);
2950 void LyXText::SetCursorFromCoordinates(BufferView * bview, LyXCursor & cur,
2953 /* get the row first */
2955 Row * row = GetRowNearY(y);
2957 int column = GetColumnNearX(bview, row, x, bound);
2959 cur.par(row->par());
2960 cur.pos(row->pos() + column);
2962 cur.y(y + row->baseline());
2964 cur.boundary(bound);
2968 void LyXText::CursorLeft(BufferView * bview, bool internal) const
2970 if (cursor.pos() > 0) {
2971 bool boundary = cursor.boundary();
2972 SetCursor(bview, cursor.par(), cursor.pos() - 1, true, false);
2973 if (!internal && !boundary &&
2974 IsBoundary(bview->buffer(), cursor.par(), cursor.pos() + 1))
2975 SetCursor(bview, cursor.par(), cursor.pos() + 1, true, true);
2976 } else if (cursor.par()->Previous()) { // steps into the above paragraph.
2977 LyXParagraph * par = cursor.par()->Previous();
2978 SetCursor(bview, par, par->Last());
2983 void LyXText::CursorRight(BufferView * bview, bool internal) const
2985 if (!internal && cursor.boundary() &&
2986 !cursor.par()->IsNewline(cursor.pos()))
2987 SetCursor(bview, cursor.par(), cursor.pos(), true, false);
2988 else if (cursor.pos() < cursor.par()->Last()) {
2989 SetCursor(bview, cursor.par(), cursor.pos() + 1, true, false);
2991 IsBoundary(bview->buffer(), cursor.par(), cursor.pos()))
2992 SetCursor(bview, cursor.par(), cursor.pos(), true, true);
2993 } else if (cursor.par()->Next())
2994 SetCursor(bview, cursor.par()->Next(), 0);
2998 void LyXText::CursorUp(BufferView * bview) const
3000 SetCursorFromCoordinates(bview, cursor.x_fix(),
3001 cursor.y() - cursor.row()->baseline() - 1);
3005 void LyXText::CursorDown(BufferView * bview) const
3007 SetCursorFromCoordinates(bview, cursor.x_fix(),
3008 cursor.y() - cursor.row()->baseline()
3009 + cursor.row()->height() + 1);
3013 void LyXText::CursorUpParagraph(BufferView * bview) const
3015 if (cursor.pos() > 0) {
3016 SetCursor(bview, cursor.par(), 0);
3018 else if (cursor.par()->Previous()) {
3019 SetCursor(bview, cursor.par()->Previous(), 0);
3024 void LyXText::CursorDownParagraph(BufferView * bview) const
3026 if (cursor.par()->Next()) {
3027 SetCursor(bview, cursor.par()->Next(), 0);
3029 SetCursor(bview, cursor.par(), cursor.par()->Last());
3034 void LyXText::DeleteEmptyParagraphMechanism(BufferView * bview,
3035 LyXCursor const & old_cursor) const
3037 // Would be wrong to delete anything if we have a selection.
3038 if (selection) return;
3040 // We allow all kinds of "mumbo-jumbo" when freespacing.
3041 if (textclasslist.Style(bview->buffer()->params.textclass,
3042 old_cursor.par()->GetLayout()).free_spacing)
3045 bool deleted = false;
3047 /* Ok I'll put some comments here about what is missing.
3048 I have fixed BackSpace (and thus Delete) to not delete
3049 double-spaces automagically. I have also changed Cut,
3050 Copy and Paste to hopefully do some sensible things.
3051 There are still some small problems that can lead to
3052 double spaces stored in the document file or space at
3053 the beginning of paragraphs. This happens if you have
3054 the cursor betwenn to spaces and then save. Or if you
3055 cut and paste and the selection have a space at the
3056 beginning and then save right after the paste. I am
3057 sure none of these are very hard to fix, but I will
3058 put out 1.1.4pre2 with FIX_DOUBLE_SPACE defined so
3059 that I can get some feedback. (Lgb)
3062 // If old_cursor.pos() == 0 and old_cursor.pos()(1) == LineSeparator
3063 // delete the LineSeparator.
3066 // If old_cursor.pos() == 1 and old_cursor.pos()(0) == LineSeparator
3067 // delete the LineSeparator.
3070 // If the pos around the old_cursor were spaces, delete one of them.
3071 if (old_cursor.par() != cursor.par() || old_cursor.pos() != cursor.pos()) {
3072 // Only if the cursor has really moved
3074 if (old_cursor.pos() > 0
3075 && old_cursor.pos() < old_cursor.par()->Last()
3076 && old_cursor.par()->IsLineSeparator(old_cursor.pos())
3077 && old_cursor.par()->IsLineSeparator(old_cursor.pos() - 1)) {
3078 old_cursor.par()->Erase(old_cursor.pos() - 1);
3079 RedoParagraphs(bview, old_cursor, old_cursor.par()->Next());
3081 if (old_cursor.par() == cursor.par() &&
3082 cursor.pos() > old_cursor.pos()) {
3083 SetCursorIntern(bview, cursor.par(),
3086 SetCursorIntern(bview, cursor.par(),
3092 // Do not delete empty paragraphs with keepempty set.
3093 if ((textclasslist.Style(bview->buffer()->params.textclass,
3094 old_cursor.par()->GetLayout())).keepempty)
3097 LyXCursor tmpcursor;
3099 if (old_cursor.par() != cursor.par()) {
3100 if ((old_cursor.par()->Last() == 0
3101 || (old_cursor.par()->Last() == 1
3102 && old_cursor.par()->IsLineSeparator(0)))
3104 && old_cursor.par()->FirstPhysicalPar()
3105 == old_cursor.par()->LastPhysicalPar()
3108 // ok, we will delete anything
3110 // make sure that you do not delete any environments
3113 old_cursor.par()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE &&
3114 !(old_cursor.row()->previous()
3115 && old_cursor.row()->previous()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
3116 && !(old_cursor.row()->next()
3117 && old_cursor.row()->next()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE))
3118 || (old_cursor.par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
3119 && ((old_cursor.row()->previous()
3120 && old_cursor.row()->previous()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
3121 || (old_cursor.row()->next()
3122 && old_cursor.row()->next()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE))
3125 status = LyXText::NEED_MORE_REFRESH;
3128 if (old_cursor.row()->previous()) {
3129 refresh_row = old_cursor.row()->previous();
3130 refresh_y = old_cursor.y() - old_cursor.row()->baseline() - refresh_row->height();
3132 cursor = old_cursor; // that undo can restore the right cursor position
3133 LyXParagraph * endpar = old_cursor.par()->next;
3134 if (endpar && endpar->GetDepth()) {
3135 while (endpar && endpar->GetDepth()) {
3137 endpar = endpar->LastPhysicalPar()->Next();
3139 endpar = endpar->Next();
3143 SetUndo(bview->buffer(), Undo::DELETE,
3144 old_cursor.par()->previous,
3149 RemoveRow(old_cursor.row());
3150 if (OwnerParagraph() == old_cursor.par()) {
3151 OwnerParagraph(OwnerParagraph()->next);
3154 delete old_cursor.par();
3156 /* Breakagain the next par. Needed
3157 * because of the parindent that
3158 * can occur or dissappear. The
3159 * next row can change its height,
3160 * if there is another layout before */
3161 if (refresh_row->next()) {
3162 BreakAgain(bview, refresh_row->next());
3163 UpdateCounters(bview, refresh_row);
3165 SetHeightOfRow(bview, refresh_row);
3167 refresh_row = old_cursor.row()->next();
3168 refresh_y = old_cursor.y() - old_cursor.row()->baseline();
3171 cursor = old_cursor; // that undo can restore the right cursor position
3172 LyXParagraph * endpar = old_cursor.par()->next;
3173 if (endpar && endpar->GetDepth()) {
3174 while (endpar && endpar->GetDepth()) {
3176 endpar = endpar->LastPhysicalPar()->Next();
3178 endpar = endpar->Next();
3182 SetUndo(bview->buffer(), Undo::DELETE,
3183 old_cursor.par()->previous,
3188 RemoveRow(old_cursor.row());
3190 if (OwnerParagraph() == old_cursor.par()) {
3191 OwnerParagraph(OwnerParagraph()->next);
3193 delete old_cursor.par();
3195 /* Breakagain the next par. Needed
3196 because of the parindent that can
3197 occur or dissappear.
3198 The next row can change its height,
3199 if there is another layout before
3202 BreakAgain(bview, refresh_row);
3203 UpdateCounters(bview, refresh_row->previous());
3209 SetCursorIntern(bview, cursor.par(), cursor.pos());
3211 if (sel_cursor.par() == old_cursor.par()
3212 && sel_cursor.pos() == sel_cursor.pos()) {
3213 // correct selection
3214 sel_cursor = cursor;
3221 if (old_cursor.par()->StripLeadingSpaces(bview->buffer()->params.textclass)) {
3222 RedoParagraphs(bview, old_cursor, old_cursor.par()->Next());
3224 SetCursorIntern(bview, cursor.par(), cursor.pos());
3225 sel_cursor = cursor;
3232 LyXParagraph * LyXText::GetParFromID(int id)
3234 LyXParagraph * result = FirstParagraph();
3235 while (result && result->id() != id)
3236 result = result->next;
3242 bool LyXText::TextUndo(BufferView * bview)
3246 // returns false if no undo possible
3247 Undo * undo = bview->buffer()->undostack.pop();
3251 bview->buffer()->redostack
3252 .push(CreateUndo(bview->buffer(), undo->kind,
3253 GetParFromID(undo->number_of_before_par),
3254 GetParFromID(undo->number_of_behind_par)));
3256 return TextHandleUndo(bview, undo);
3260 bool LyXText::TextRedo(BufferView * bview)
3264 // returns false if no redo possible
3265 Undo * undo = bview->buffer()->redostack.pop();
3269 bview->buffer()->undostack
3270 .push(CreateUndo(bview->buffer(), undo->kind,
3271 GetParFromID(undo->number_of_before_par),
3272 GetParFromID(undo->number_of_behind_par)));
3274 return TextHandleUndo(bview, undo);
3278 bool LyXText::TextHandleUndo(BufferView * bview, Undo * undo)
3282 // returns false if no undo possible
3283 bool result = false;
3285 LyXParagraph * before =
3286 GetParFromID(undo->number_of_before_par);
3287 LyXParagraph * behind =
3288 GetParFromID(undo->number_of_behind_par);
3289 LyXParagraph * tmppar;
3290 LyXParagraph * tmppar2;
3291 LyXParagraph * endpar;
3292 LyXParagraph * tmppar5;
3294 // if there's no before take the beginning
3295 // of the document for redoing
3297 SetCursorIntern(bview, FirstParagraph(), 0);
3299 // replace the paragraphs with the undo informations
3301 LyXParagraph * tmppar3 = undo->par;
3302 undo->par = 0; // otherwise the undo destructor would delete the paragraph
3303 LyXParagraph * tmppar4 = tmppar3;
3305 while (tmppar4->next)
3306 tmppar4 = tmppar4->next;
3307 } // get last undo par
3309 // now remove the old text if there is any
3310 if (before != behind || (!behind && !before)){
3312 tmppar5 = before->next;
3314 tmppar5 = OwnerParagraph();
3316 while (tmppar5 && tmppar5 != behind){
3318 tmppar5 = tmppar5->next;
3319 // a memory optimization for edit: Only layout information
3320 // is stored in the undo. So restore the text informations.
3321 if (undo->kind == Undo::EDIT) {
3322 tmppar2->setContentsFromPar(tmppar);
3323 tmppar->clearContents();
3324 tmppar2 = tmppar2->next;
3329 // put the new stuff in the list if there is one
3332 before->next = tmppar3;
3334 OwnerParagraph(tmppar3);
3335 tmppar3->previous = before;
3338 OwnerParagraph(behind);
3341 tmppar4->next = behind;
3343 behind->previous = tmppar4;
3347 // Set the cursor for redoing
3350 SetCursorIntern(bview, before->FirstSelfrowPar(), 0);
3352 SetCursorIntern(bview, before, 0);
3355 // check wether before points to a closed float and open it if necessary
3356 if (before && before->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE
3357 && before->next && before->next->footnoteflag != LyXParagraph::NO_FOOTNOTE){
3359 while (tmppar4->previous &&
3360 tmppar4->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
3361 tmppar4 = tmppar4->previous;
3362 while (tmppar4 && tmppar4->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3363 tmppar4->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
3364 tmppar4 = tmppar4->next;
3371 // open a cosed footnote at the end if necessary
3372 if (behind && behind->previous &&
3373 behind->previous->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
3374 behind->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3375 while (behind && behind->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3376 behind->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
3377 behind = behind->next;
3382 // calculate the endpar for redoing the paragraphs.
3385 if (behind->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
3386 endpar = behind->LastPhysicalPar()->Next();
3388 endpar = behind->NextAfterFootnote()->LastPhysicalPar()->Next();
3390 endpar = behind->Next();
3395 tmppar = GetParFromID(undo->number_of_cursor_par);
3396 RedoParagraphs(bview, cursor, endpar);
3398 SetCursorIntern(bview, tmppar, undo->cursor_pos);
3399 UpdateCounters(bview, cursor.row());
3409 void LyXText::FinishUndo()
3413 // makes sure the next operation will be stored
3414 undo_finished = true;
3418 void LyXText::FreezeUndo()
3422 // this is dangerous and for internal use only
3427 void LyXText::UnFreezeUndo()
3431 // this is dangerous and for internal use only
3432 undo_frozen = false;
3436 void LyXText::SetUndo(Buffer * buf, Undo::undo_kind kind,
3437 LyXParagraph const * before,
3438 LyXParagraph const * behind) const
3443 buf->undostack.push(CreateUndo(buf, kind, before, behind));
3444 buf->redostack.clear();
3448 void LyXText::SetRedo(Buffer * buf, Undo::undo_kind kind,
3449 LyXParagraph const * before, LyXParagraph const * behind)
3453 buf->redostack.push(CreateUndo(buf, kind, before, behind));
3457 Undo * LyXText::CreateUndo(Buffer * buf, Undo::undo_kind kind,
3458 LyXParagraph const * before,
3459 LyXParagraph const * behind) const
3464 int before_number = -1;
3465 int behind_number = -1;
3467 before_number = before->id();
3469 behind_number = behind->id();
3470 // Undo::EDIT and Undo::FINISH are
3471 // always finished. (no overlapping there)
3472 // overlapping only with insert and delete inside one paragraph:
3473 // Nobody wants all removed character
3474 // appear one by one when undoing.
3475 // EDIT is special since only layout information, not the
3476 // contents of a paragaph are stored.
3477 if (!undo_finished && (kind != Undo::EDIT) && (kind != Undo::FINISH)){
3478 // check wether storing is needed
3479 if (!buf->undostack.empty() &&
3480 buf->undostack.top()->kind == kind &&
3481 buf->undostack.top()->number_of_before_par == before_number &&
3482 buf->undostack.top()->number_of_behind_par == behind_number ){
3487 // create a new Undo
3488 LyXParagraph * undopar;
3489 LyXParagraph * tmppar;
3490 LyXParagraph * tmppar2;
3492 LyXParagraph * start = 0;
3493 LyXParagraph * end = 0;
3496 start = before->next;
3498 start = FirstParagraph();
3500 end = behind->previous;
3502 end = FirstParagraph();
3507 if (start && end && (start != end->next) &&
3508 ((before != behind) || (!before && !behind)))
3511 tmppar2 = tmppar->Clone();
3512 tmppar2->id(tmppar->id());
3514 // a memory optimization: Just store the layout information
3516 if (kind == Undo::EDIT){
3517 //tmppar2->text.clear();
3518 tmppar2->clearContents();
3523 while (tmppar != end && tmppar->next) {
3524 tmppar = tmppar->next;
3525 tmppar2->next = tmppar->Clone();
3526 tmppar2->next->id(tmppar->id());
3527 // a memory optimization: Just store the layout
3528 // information when only edit
3529 if (kind == Undo::EDIT){
3530 //tmppar2->next->text.clear();
3531 tmppar2->clearContents();
3533 tmppar2->next->previous = tmppar2;
3534 tmppar2 = tmppar2->next;
3538 undopar = 0; // nothing to replace (undo of delete maybe)
3541 int cursor_par = cursor.par()->ParFromPos(cursor.pos())->id();
3542 int cursor_pos = cursor.par()->PositionInParFromPos(cursor.pos());
3544 int cursor_par = cursor.par()->id();
3545 int cursor_pos = cursor.pos();
3548 Undo * undo = new Undo(kind,
3549 before_number, behind_number,
3550 cursor_par, cursor_pos,
3553 undo_finished = false;
3558 void LyXText::SetCursorParUndo(Buffer * buf)
3562 SetUndo(buf, Undo::FINISH,
3564 cursor.par()->ParFromPos(cursor.pos())->previous,
3565 cursor.par()->ParFromPos(cursor.pos())->next
3567 cursor.par()->previous,
3574 void LyXText::toggleAppendix(BufferView * bview)
3577 LyXParagraph * par = cursor.par()->FirstPhysicalPar();
3579 LyXParagraph * par = cursor.par();
3581 bool start = !par->start_of_appendix;
3583 // ensure that we have only one start_of_appendix in this document
3584 LyXParagraph * tmp = FirstParagraph();
3585 for (; tmp; tmp = tmp->next)
3586 tmp->start_of_appendix = 0;
3587 par->start_of_appendix = start;
3589 // we can set the refreshing parameters now
3590 status = LyXText::NEED_MORE_REFRESH;
3592 refresh_row = 0; // not needed for full update
3593 UpdateCounters(bview, 0);
3594 SetCursor(bview, cursor.par(), cursor.pos());
3598 LyXParagraph * LyXText::OwnerParagraph() const
3601 return inset_owner->par;
3603 return bv_owner->buffer()->paragraph;
3607 LyXParagraph * LyXText::OwnerParagraph(LyXParagraph * p) const
3610 inset_owner->par = p;
3612 bv_owner->buffer()->paragraph = p;