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)
77 status = LyXText::UNCHANGED;
78 // set cursor at the very top position
79 selection = true; /* these setting is necessary
80 because of the delete-empty-
81 paragraph mechanism in
84 LyXParagraph * par = OwnerParagraph();
85 current_font = GetFont(bv_owner->buffer(), par, 0);
87 InsertParagraph(bv_owner, par, lastrow);
90 SetCursor(bv_owner, firstrow->par(), 0);
92 current_font = LyXFont(LyXFont::ALL_SANE);
98 // no rebreak necessary
101 undo_finished = true;
104 // Default layouttype for copy environment type
108 // Dump all rowinformation:
109 Row * tmprow = firstrow;
110 lyxerr << "Baseline Paragraph Pos Height Ascent Fill\n";
112 lyxerr << tmprow->baseline() << '\t'
113 << tmprow->par << '\t'
114 << tmprow->pos() << '\t'
115 << tmprow->height << '\t'
116 << tmprow->ascent_of_text << '\t'
117 << tmprow->fill << '\n';
118 tmprow = tmprow->next();
125 void LyXText::init(BufferView * bview)
130 LyXParagraph * par = OwnerParagraph();
131 current_font = GetFont(bview->buffer(), par, 0);
133 InsertParagraph(bview, par, lastrow);
136 SetCursorIntern(bview, firstrow->par(), 0);
139 // Dump all rowinformation:
140 Row * tmprow = firstrow;
141 lyxerr << "Width = " << width << endl;
142 lyxerr << "Baseline Paragraph Pos Height Ascent Fill\n";
144 lyxerr << tmprow->baseline() << '\t'
145 << tmprow->par() << '\t'
146 << tmprow->pos() << '\t'
147 << tmprow->height() << '\t'
148 << tmprow->ascent_of_text() << '\t'
149 << tmprow->fill() << '\n';
150 tmprow = tmprow->next();
158 // Delete all rows, this does not touch the paragraphs!
159 Row * tmprow = firstrow;
161 tmprow = firstrow->next();
168 // Gets the fully instantiated font at a given position in a paragraph
169 // Basically the same routine as LyXParagraph::getFont() in paragraph.C.
170 // The difference is that this one is used for displaying, and thus we
171 // are allowed to make cosmetic improvements. For instance make footnotes
173 // If position is -1, we get the layout font of the paragraph.
174 // If position is -2, we get the font of the manual label of the paragraph.
175 LyXFont const LyXText::GetFont(Buffer const * buf, LyXParagraph * par,
176 LyXParagraph::size_type pos) const
178 LyXLayout const & layout =
179 textclasslist.Style(buf->params.textclass, par->GetLayout());
181 char par_depth = par->GetDepth();
182 // We specialize the 95% common case:
185 par->footnoteflag == LyXParagraph::NO_FOOTNOTE &&
190 if (layout.labeltype == LABEL_MANUAL
191 && pos < BeginningOfMainBody(buf, par)) {
193 LyXFont f = par->GetFontSettings(buf->params,
195 return f.realize(layout.reslabelfont);
197 LyXFont f = par->GetFontSettings(buf->params, pos);
198 return f.realize(layout.resfont);
203 // process layoutfont for pos == -1 and labelfont for pos < -1
205 return layout.resfont;
207 return layout.reslabelfont;
211 // The uncommon case need not be optimized as much
213 LyXFont layoutfont, tmpfont;
217 if (pos < BeginningOfMainBody(buf, par)) {
219 layoutfont = layout.labelfont;
222 layoutfont = layout.font;
224 tmpfont = par->GetFontSettings(buf->params, pos);
225 tmpfont.realize(layoutfont);
228 // process layoutfont for pos == -1 and labelfont for pos < -1
230 tmpfont = layout.font;
232 tmpfont = layout.labelfont;
235 // Resolve against environment font information
236 while (par && par_depth && !tmpfont.resolved()) {
237 par = par->DepthHook(par_depth - 1);
239 tmpfont.realize(textclasslist.
240 Style(buf->params.textclass,
241 par->GetLayout()).font);
242 par_depth = par->GetDepth();
246 tmpfont.realize(textclasslist.TextClass(buf->params.textclass).defaultfont());
249 // Cosmetic improvement: If this is an open footnote, make the font
251 if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
252 && par->footnotekind == LyXParagraph::FOOTNOTE) {
260 void LyXText::SetCharFont(Buffer const * buf, LyXParagraph * par,
261 LyXParagraph::size_type pos,
265 // Let the insets convert their font
266 if (par->GetChar(pos) == LyXParagraph::META_INSET) {
267 if (par->GetInset(pos))
268 font = par->GetInset(pos)->ConvertFont(font);
271 LyXLayout const & layout =
272 textclasslist.Style(buf->params.textclass,
275 // Get concrete layout font to reduce against
278 if (pos < BeginningOfMainBody(buf, par))
279 layoutfont = layout.labelfont;
281 layoutfont = layout.font;
283 // Realize against environment font information
284 if (par->GetDepth()){
285 LyXParagraph * tp = par;
286 while (!layoutfont.resolved() && tp && tp->GetDepth()) {
287 tp = tp->DepthHook(tp->GetDepth()-1);
289 layoutfont.realize(textclasslist.
290 Style(buf->params.textclass,
291 tp->GetLayout()).font);
295 layoutfont.realize(textclasslist.TextClass(buf->params.textclass).defaultfont());
298 if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
299 && par->footnotekind == LyXParagraph::FOOTNOTE) {
300 layoutfont.decSize();
303 // Now, reduce font against full layout font
304 font.reduce(layoutfont);
306 par->SetFont(pos, font);
310 /* inserts a new row behind the specified row, increments
311 * the touched counters */
312 void LyXText::InsertRow(Row * row, LyXParagraph * par,
313 LyXParagraph::size_type pos) const
315 Row * tmprow = new Row;
318 tmprow->next(firstrow);
321 tmprow->previous(row);
322 tmprow->next(row->next());
327 tmprow->next()->previous(tmprow);
329 if (tmprow->previous())
330 tmprow->previous()->next(tmprow);
338 ++number_of_rows; // one more row
342 // removes the row and reset the touched counters
343 void LyXText::RemoveRow(Row * row) const
345 /* this must not happen before the currentrow for clear reasons.
346 so the trick is just to set the current row onto the previous
349 GetRow(row->par(), row->pos(), unused_y);
352 row->next()->previous(row->previous());
353 if (!row->previous()) {
354 firstrow = row->next();
356 row->previous()->next(row->next());
359 lastrow = row->previous();
361 height -= row->height(); // the text becomes smaller
364 --number_of_rows; // one row less
368 // remove all following rows of the paragraph of the specified row.
369 void LyXText::RemoveParagraph(Row * row) const
371 LyXParagraph * tmppar = row->par();
375 while (row && row->par() == tmppar) {
376 tmprow = row->next();
383 // insert the specified paragraph behind the specified row
384 void LyXText::InsertParagraph(BufferView * bview, LyXParagraph * par,
387 InsertRow(row, par, 0); /* insert a new row, starting
390 SetCounter(bview->buffer(), par); // set the counters
392 // and now append the whole paragraph behind the new row
395 AppendParagraph(bview, firstrow);
397 row->next()->height(0);
398 AppendParagraph(bview, row->next());
404 void LyXText::ToggleFootnote(BufferView * bview)
406 LyXParagraph * par = cursor.par()->ParFromPos(cursor.pos());
408 && par->next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
410 bview->owner()->getMiniBuffer()->Set(_("Opened float"));
412 bview->owner()->getMiniBuffer()->Set(_("Closed float"));
413 CloseFootnote(bview);
420 void LyXText::OpenStuff(BufferView * bview)
422 if (cursor.pos() == 0 && cursor.par()->bibkey){
423 cursor.par()->bibkey->Edit(bview, 0, 0, 0);
424 } else if (cursor.pos() < cursor.par()->Last()
425 && cursor.par()->GetChar(cursor.pos()) == LyXParagraph::META_INSET
426 && cursor.par()->GetInset(cursor.pos())->Editable()) {
427 bview->owner()->getMiniBuffer()
428 ->Set(cursor.par()->GetInset(cursor.pos())->EditMessage());
429 if (cursor.par()->GetInset(cursor.pos())->Editable() != Inset::HIGHLY_EDITABLE)
430 SetCursorParUndo(bview->buffer());
431 cursor.par()->GetInset(cursor.pos())->Edit(bview, 0, 0, 0);
435 ToggleFootnote(bview);
443 void LyXText::CloseFootnote(BufferView * bview)
445 LyXParagraph * tmppar;
446 LyXParagraph * par = cursor.par()->ParFromPos(cursor.pos());
448 // if the cursor is not in an open footnote, or
449 // there is no open footnote in this paragraph, just return.
450 if (cursor.par()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE) {
453 par->next->footnoteflag != LyXParagraph::OPEN_FOOTNOTE) {
454 bview->owner()->getMiniBuffer()
455 ->Set(_("Nothing to do"));
459 // ok, move the cursor right before the footnote
460 // just a little faster than using CursorRight()
462 cursor.par()->ParFromPos(cursor.pos()) != par;) {
463 cursor.pos(cursor.pos() + 1);
466 // now the cursor is at the beginning of the physical par
467 SetCursor(bview, cursor.par(),
469 cursor.par()->ParFromPos(cursor.pos())->size());
471 /* we are in a footnote, so let us move at the beginning */
472 /* this is just faster than using just CursorLeft() */
474 tmppar = cursor.par();
475 while (tmppar->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
476 // just a little bit faster than movin the cursor
477 tmppar = tmppar->Previous();
479 SetCursor(bview, tmppar, tmppar->Last());
482 // the cursor must be exactly before the footnote
483 par = cursor.par()->ParFromPos(cursor.pos());
485 status = LyXText::NEED_MORE_REFRESH;
486 refresh_row = cursor.row();
487 refresh_y = cursor.y() - cursor.row()->baseline();
489 tmppar = cursor.par();
490 LyXParagraph * endpar = par->NextAfterFootnote()->Next();
491 Row * row = cursor.row();
493 tmppar->CloseFootnote(cursor.pos());
495 while (tmppar != endpar) {
496 RemoveRow(row->next());
498 tmppar = row->next()->par();
503 AppendParagraph(bview, cursor.row());
505 SetCursor(bview, cursor.par(), cursor.pos());
509 if (cursor.row()->next())
510 SetHeightOfRow(bview, cursor.row()->next());
515 /* used in setlayout */
516 // Asger is not sure we want to do this...
517 void LyXText::MakeFontEntriesLayoutSpecific(Buffer const * buf,
521 LyXLayout const & layout =
522 textclasslist.Style(buf->params.textclass, par->GetLayout());
524 LyXFont layoutfont, tmpfont;
525 for (LyXParagraph::size_type pos = 0;
526 pos < par->Last(); ++pos) {
527 if (pos < BeginningOfMainBody(buf, par))
528 layoutfont = layout.labelfont;
530 layoutfont = layout.font;
532 tmpfont = par->GetFontSettings(buf->params, pos);
533 tmpfont.reduce(layoutfont);
534 par->SetFont(pos, tmpfont);
539 LyXParagraph * LyXText::SetLayout(BufferView * bview,
540 LyXCursor & cur, LyXCursor & sstart_cur,
541 LyXCursor & send_cur,
542 LyXTextClass::size_type layout)
545 LyXParagraph * endpar = send_cur.par()->LastPhysicalPar()->Next();
547 LyXParagraph * endpar = send_cur.par()->Next();
549 LyXParagraph * undoendpar = endpar;
551 if (endpar && endpar->GetDepth()) {
552 while (endpar && endpar->GetDepth()) {
554 endpar = endpar->LastPhysicalPar()->Next();
556 endpar = endpar->Next();
561 endpar = endpar->Next(); // because of parindents etc.
564 SetUndo(bview->buffer(), Undo::EDIT,
566 sstart_cur.par()->ParFromPos(sstart_cur.pos())->previous,
568 sstart_cur.par()->previous,
572 /* ok we have a selection. This is always between sstart_cur
573 * and sel_end cursor */
576 LyXLayout const & lyxlayout =
577 textclasslist.Style(bview->buffer()->params.textclass, layout);
579 while (cur.par() != send_cur.par()) {
581 if (cur.par()->footnoteflag == sstart_cur.par()->footnoteflag) {
583 cur.par()->SetLayout(bview->buffer()->params, layout);
584 MakeFontEntriesLayoutSpecific(bview->buffer(), cur.par());
586 LyXParagraph * fppar = cur.par()->FirstPhysicalPar();
588 LyXParagraph * fppar = cur.par();
590 fppar->added_space_top = lyxlayout.fill_top ?
591 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
592 fppar->added_space_bottom = lyxlayout.fill_bottom ?
593 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
594 if (lyxlayout.margintype == MARGIN_MANUAL)
595 cur.par()->SetLabelWidthString(lyxlayout.labelstring());
596 if (lyxlayout.labeltype != LABEL_BIBLIO
598 delete fppar->bibkey;
604 cur.par(cur.par()->Next());
607 if (cur.par()->footnoteflag == sstart_cur.par()->footnoteflag) {
609 cur.par()->SetLayout(bview->buffer()->params, layout);
610 MakeFontEntriesLayoutSpecific(bview->buffer(), cur.par());
612 LyXParagraph * fppar = cur.par()->FirstPhysicalPar();
614 LyXParagraph * fppar = cur.par();
616 fppar->added_space_top = lyxlayout.fill_top ?
617 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
618 fppar->added_space_bottom = lyxlayout.fill_bottom ?
619 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
620 if (lyxlayout.margintype == MARGIN_MANUAL)
621 cur.par()->SetLabelWidthString(lyxlayout.labelstring());
622 if (lyxlayout.labeltype != LABEL_BIBLIO
624 delete fppar->bibkey;
633 // set layout over selection and make a total rebreak of those paragraphs
634 void LyXText::SetLayout(BufferView * bview, LyXTextClass::size_type layout)
636 LyXCursor tmpcursor = cursor; /* store the current cursor */
638 // if there is no selection just set the layout
639 // of the current paragraph */
641 sel_start_cursor = cursor; // dummy selection
642 sel_end_cursor = cursor;
645 endpar = SetLayout(bview, cursor, sel_start_cursor,
646 sel_end_cursor, layout);
647 RedoParagraphs(bview, sel_start_cursor, endpar);
649 // we have to reset the selection, because the
650 // geometry could have changed
651 SetCursor(bview, sel_start_cursor.par(),
652 sel_start_cursor.pos(), false);
654 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos(),
656 UpdateCounters(bview, cursor.row());
659 SetCursor(bview, tmpcursor.par(), tmpcursor.pos(), true);
663 // increment depth over selection and
664 // make a total rebreak of those paragraphs
665 void LyXText::IncDepth(BufferView * bview)
667 // If there is no selection, just use the current paragraph
669 sel_start_cursor = cursor; // dummy selection
670 sel_end_cursor = cursor;
673 // We end at the next paragraph with depth 0
674 LyXParagraph * endpar =
676 sel_end_cursor.par()->LastPhysicalPar()->Next();
678 sel_end_cursor.par()->Next();
680 LyXParagraph * undoendpar = endpar;
682 if (endpar && endpar->GetDepth()) {
683 while (endpar && endpar->GetDepth()) {
685 endpar = endpar->LastPhysicalPar()->Next();
687 endpar = endpar->Next();
693 endpar = endpar->Next(); // because of parindents etc.
696 SetUndo(bview->buffer(), Undo::EDIT,
699 .par()->ParFromPos(sel_start_cursor.pos())->previous,
701 sel_start_cursor.par()->previous,
705 LyXCursor tmpcursor = cursor; // store the current cursor
707 // ok we have a selection. This is always between sel_start_cursor
708 // and sel_end cursor
709 cursor = sel_start_cursor;
711 bool anything_changed = false;
714 // NOTE: you can't change the depth of a bibliography entry
717 cursor.par()->footnoteflag ==
718 sel_start_cursor.par()->footnoteflag &&
720 textclasslist.Style(bview->buffer()->params.textclass,
721 cursor.par()->GetLayout()
722 ).labeltype != LABEL_BIBLIO) {
723 LyXParagraph * prev =
725 cursor.par()->FirstPhysicalPar()->Previous();
727 cursor.par()->Previous();
730 && (prev->GetDepth() - cursor.par()->GetDepth() > 0
731 || (prev->GetDepth() == cursor.par()->GetDepth()
732 && textclasslist.Style(bview->buffer()->params.textclass,
733 prev->GetLayout()).isEnvironment()))) {
735 cursor.par()->FirstPhysicalPar()->depth++;
737 cursor.par()->depth++;
739 anything_changed = true;
742 if (cursor.par() == sel_end_cursor.par())
744 cursor.par(cursor.par()->Next());
747 // if nothing changed set all depth to 0
748 if (!anything_changed) {
749 cursor = sel_start_cursor;
750 while (cursor.par() != sel_end_cursor.par()) {
752 cursor.par()->FirstPhysicalPar()->depth = 0;
754 cursor.par()->depth = 0;
756 cursor.par(cursor.par()->Next());
759 if (cursor.par()->footnoteflag == sel_start_cursor.par()->footnoteflag)
760 cursor.par()->FirstPhysicalPar()->depth = 0;
762 cursor.par()->depth = 0;
766 RedoParagraphs(bview, sel_start_cursor, endpar);
768 // we have to reset the selection, because the
769 // geometry could have changed
770 SetCursor(bview, sel_start_cursor.par(),
771 sel_start_cursor.pos());
773 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
774 UpdateCounters(bview, cursor.row());
777 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
781 // decrement depth over selection and
782 // make a total rebreak of those paragraphs
783 void LyXText::DecDepth(BufferView * bview)
785 // if there is no selection just set the layout
786 // of the current paragraph
788 sel_start_cursor = cursor; // dummy selection
789 sel_end_cursor = cursor;
792 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
794 LyXParagraph * endpar = sel_end_cursor.par()->Next();
796 LyXParagraph * undoendpar = endpar;
798 if (endpar && endpar->GetDepth()) {
799 while (endpar && endpar->GetDepth()) {
801 endpar = endpar->LastPhysicalPar()->Next();
803 endpar = endpar->Next();
809 endpar = endpar->Next(); // because of parindents etc.
812 SetUndo(bview->buffer(), Undo::EDIT,
815 .par()->ParFromPos(sel_start_cursor.pos())->previous,
817 sel_start_cursor.par()->previous,
821 LyXCursor tmpcursor = cursor; // store the current cursor
823 // ok we have a selection. This is always between sel_start_cursor
824 // and sel_end cursor
825 cursor = sel_start_cursor;
829 if (cursor.par()->footnoteflag ==
830 sel_start_cursor.par()->footnoteflag) {
831 if (cursor.par()->FirstPhysicalPar()->depth)
832 cursor.par()->FirstPhysicalPar()->depth--;
835 if (cursor.par()->depth)
836 cursor.par()->depth--;
838 if (cursor.par() == sel_end_cursor.par())
840 cursor.par(cursor.par()->Next());
843 RedoParagraphs(bview, sel_start_cursor, endpar);
845 // we have to reset the selection, because the
846 // geometry could have changed
847 SetCursor(bview, sel_start_cursor.par(),
848 sel_start_cursor.pos());
850 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
851 UpdateCounters(bview, cursor.row());
854 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
858 // set font over selection and make a total rebreak of those paragraphs
859 void LyXText::SetFont(BufferView * bview, LyXFont const & font, bool toggleall)
861 // if there is no selection just set the current_font
863 // Determine basis font
865 if (cursor.pos() < BeginningOfMainBody(bview->buffer(),
867 layoutfont = GetFont(bview->buffer(), cursor.par(),-2);
869 layoutfont = GetFont(bview->buffer(), cursor.par(),-1);
870 // Update current font
871 real_current_font.update(font,
872 bview->buffer()->params.language_info,
875 // Reduce to implicit settings
876 current_font = real_current_font;
877 current_font.reduce(layoutfont);
878 // And resolve it completely
879 real_current_font.realize(layoutfont);
883 LyXCursor tmpcursor = cursor; // store the current cursor
885 // ok we have a selection. This is always between sel_start_cursor
886 // and sel_end cursor
888 SetUndo(bview->buffer(), Undo::EDIT,
890 sel_start_cursor.par()->ParFromPos(sel_start_cursor.pos())->previous,
891 sel_end_cursor.par()->ParFromPos(sel_end_cursor.pos())->next
893 sel_start_cursor.par()->previous,
894 sel_end_cursor.par()->next
897 cursor = sel_start_cursor;
898 while (cursor.par() != sel_end_cursor.par() ||
901 cursor.par()->footnoteflag == sel_start_cursor.par()->footnoteflag &&
903 cursor.pos() < sel_end_cursor.pos()))
905 if (cursor.pos() < cursor.par()->Last()
907 && cursor.par()->footnoteflag
908 == sel_start_cursor.par()->footnoteflag
911 // an open footnote should behave
913 LyXFont newfont = GetFont(bview->buffer(),
914 cursor.par(), cursor.pos());
916 bview->buffer()->params.language_info,
918 SetCharFont(bview->buffer(),
919 cursor.par(), cursor.pos(), newfont);
920 cursor.pos(cursor.pos() + 1);
923 cursor.par(cursor.par()->Next());
927 RedoParagraphs(bview, sel_start_cursor, sel_end_cursor.par()->Next());
929 // we have to reset the selection, because the
930 // geometry could have changed
931 SetCursor(bview, sel_start_cursor.par(), sel_start_cursor.pos());
933 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
936 SetCursor(bview, tmpcursor.par(), tmpcursor.pos(), true,
937 tmpcursor.boundary());
941 void LyXText::RedoHeightOfParagraph(BufferView * bview, LyXCursor const & cur)
943 Row * tmprow = cur.row();
944 int y = cur.y() - tmprow->baseline();
946 SetHeightOfRow(bview, tmprow);
948 LyXParagraph * first_phys_par = tmprow->par()->FirstPhysicalPar();
950 LyXParagraph * first_phys_par = tmprow->par();
952 // find the first row of the paragraph
953 if (first_phys_par != tmprow->par())
954 while (tmprow->previous()
955 && tmprow->previous()->par() != first_phys_par) {
956 tmprow = tmprow->previous();
957 y -= tmprow->height();
958 SetHeightOfRow(bview, tmprow);
960 while (tmprow->previous() && tmprow->previous()->par() == first_phys_par) {
961 tmprow = tmprow->previous();
962 y -= tmprow->height();
963 SetHeightOfRow(bview, tmprow);
966 // we can set the refreshing parameters now
967 status = LyXText::NEED_MORE_REFRESH;
969 refresh_row = tmprow;
970 SetCursor(bview, cur.par(), cur.pos(), false, cursor.boundary());
974 void LyXText::RedoDrawingOfParagraph(BufferView * bview, LyXCursor const & cur)
976 Row * tmprow = cur.row();
978 int y = cur.y() - tmprow->baseline();
979 SetHeightOfRow(bview, tmprow);
981 LyXParagraph * first_phys_par = tmprow->par()->FirstPhysicalPar();
983 LyXParagraph * first_phys_par = tmprow->par();
985 // find the first row of the paragraph
986 if (first_phys_par != tmprow->par())
987 while (tmprow->previous() && tmprow->previous()->par() != first_phys_par) {
988 tmprow = tmprow->previous();
989 y -= tmprow->height();
991 while (tmprow->previous() && tmprow->previous()->par() == first_phys_par) {
992 tmprow = tmprow->previous();
993 y -= tmprow->height();
996 // we can set the refreshing parameters now
997 if (status == LyXText::UNCHANGED || y < refresh_y) {
999 refresh_row = tmprow;
1001 status = LyXText::NEED_MORE_REFRESH;
1002 SetCursor(bview, cur.par(), cur.pos());
1006 /* deletes and inserts again all paragaphs between the cursor
1007 * and the specified par
1008 * This function is needed after SetLayout and SetFont etc. */
1009 void LyXText::RedoParagraphs(BufferView * bview, LyXCursor const & cur,
1010 LyXParagraph const * endpar) const
1013 LyXParagraph * tmppar = 0, * first_phys_par = 0;
1015 Row * tmprow = cur.row();
1017 int y = cur.y() - tmprow->baseline();
1019 if (!tmprow->previous()){
1020 first_phys_par = FirstParagraph(); // a trick/hack for UNDO
1023 first_phys_par = tmprow->par()->FirstPhysicalPar();
1025 first_phys_par = tmprow->par();
1027 // find the first row of the paragraph
1028 if (first_phys_par != tmprow->par())
1029 while (tmprow->previous() &&
1030 (tmprow->previous()->par() != first_phys_par)) {
1031 tmprow = tmprow->previous();
1032 y -= tmprow->height();
1034 while (tmprow->previous()
1035 && tmprow->previous()->par() == first_phys_par) {
1036 tmprow = tmprow->previous();
1037 y -= tmprow->height();
1041 // we can set the refreshing parameters now
1042 status = LyXText::NEED_MORE_REFRESH;
1044 refresh_row = tmprow->previous(); /* the real refresh row will
1045 be deleted, so I store
1046 the previous here */
1049 tmppar = tmprow->next()->par();
1052 while (tmppar != endpar) {
1053 RemoveRow(tmprow->next());
1055 tmppar = tmprow->next()->par();
1060 // remove the first one
1061 tmprow2 = tmprow; /* this is because tmprow->previous()
1063 tmprow = tmprow->previous();
1066 tmppar = first_phys_par;
1070 InsertParagraph(bview, tmppar, tmprow);
1073 while (tmprow->next() && tmprow->next()->par() == tmppar)
1074 tmprow = tmprow->next();
1075 tmppar = tmppar->Next();
1077 } while (tmppar != endpar);
1079 // this is because of layout changes
1081 refresh_y -= refresh_row->height();
1082 SetHeightOfRow(bview, refresh_row);
1084 refresh_row = firstrow;
1086 SetHeightOfRow(bview, refresh_row);
1089 if (tmprow && tmprow->next())
1090 SetHeightOfRow(bview, tmprow->next());
1094 bool LyXText::FullRebreak(BufferView * bview)
1100 if (need_break_row) {
1101 BreakAgain(bview, need_break_row);
1109 /* important for the screen */
1112 /* the cursor set functions have a special mechanism. When they
1113 * realize, that you left an empty paragraph, they will delete it.
1114 * They also delete the corresponding row */
1116 // need the selection cursor:
1117 void LyXText::SetSelection()
1120 last_sel_cursor = sel_cursor;
1121 sel_start_cursor = sel_cursor;
1122 sel_end_cursor = sel_cursor;
1127 // first the toggling area
1128 if (cursor.y() < last_sel_cursor.y()
1129 || (cursor.y() == last_sel_cursor.y()
1130 && cursor.x() < last_sel_cursor.x())) {
1131 toggle_end_cursor = last_sel_cursor;
1132 toggle_cursor = cursor;
1134 toggle_end_cursor = cursor;
1135 toggle_cursor = last_sel_cursor;
1138 last_sel_cursor = cursor;
1140 // and now the whole selection
1142 if (sel_cursor.par() == cursor.par())
1143 if (sel_cursor.pos() < cursor.pos()) {
1144 sel_end_cursor = cursor;
1145 sel_start_cursor = sel_cursor;
1147 sel_end_cursor = sel_cursor;
1148 sel_start_cursor = cursor;
1150 else if (sel_cursor.y() < cursor.y() ||
1151 (sel_cursor.y() == cursor.y() && sel_cursor.x() < cursor.x())) {
1152 sel_end_cursor = cursor;
1153 sel_start_cursor = sel_cursor;
1156 sel_end_cursor = sel_cursor;
1157 sel_start_cursor = cursor;
1160 // a selection with no contents is not a selection
1161 if (sel_start_cursor.par() == sel_end_cursor.par() &&
1162 sel_start_cursor.pos() == sel_end_cursor.pos())
1167 string const LyXText::selectionAsString(Buffer const * buffer) const
1169 if (!selection) return string();
1172 // Special handling if the whole selection is within one paragraph
1173 if (sel_start_cursor.par() == sel_end_cursor.par()) {
1174 result += sel_start_cursor.par()->String(buffer,
1175 sel_start_cursor.pos(),
1176 sel_end_cursor.pos());
1180 // The selection spans more than one paragraph
1182 // First paragraph in selection
1183 result += sel_start_cursor.par()->String(buffer,
1184 sel_start_cursor.pos(),
1185 sel_start_cursor.par()->Last())
1188 // The paragraphs in between (if any)
1189 LyXCursor tmpcur(sel_start_cursor);
1190 tmpcur.par(tmpcur.par()->Next());
1191 while (tmpcur.par() != sel_end_cursor.par()) {
1192 result += tmpcur.par()->String(buffer, 0, tmpcur.par()->Last()) + "\n\n";
1193 tmpcur.par(tmpcur.par()->Next()); // Or NextAfterFootnote??
1196 // Last paragraph in selection
1197 result += sel_end_cursor.par()->String(buffer, 0, sel_end_cursor.pos());
1203 void LyXText::ClearSelection() const
1210 void LyXText::CursorHome(BufferView * bview) const
1212 SetCursor(bview, cursor.par(), cursor.row()->pos());
1216 void LyXText::CursorEnd(BufferView * bview) const
1218 if (!cursor.row()->next() || cursor.row()->next()->par() != cursor.row()->par())
1219 SetCursor(bview, cursor.par(), RowLast(cursor.row()) + 1);
1221 if (cursor.par()->Last() &&
1222 (cursor.par()->GetChar(RowLast(cursor.row())) == ' '
1223 || cursor.par()->IsNewline(RowLast(cursor.row()))))
1224 SetCursor(bview, cursor.par(), RowLast(cursor.row()));
1226 SetCursor(bview,cursor.par(), RowLast(cursor.row()) + 1);
1231 void LyXText::CursorTop(BufferView * bview) const
1233 while (cursor.par()->Previous())
1234 cursor.par(cursor.par()->Previous());
1235 SetCursor(bview, cursor.par(), 0);
1239 void LyXText::CursorBottom(BufferView * bview) const
1241 while (cursor.par()->Next())
1242 cursor.par(cursor.par()->Next());
1243 SetCursor(bview, cursor.par(), cursor.par()->Last());
1247 /* returns a pointer to the row near the specified y-coordinate
1248 * (relative to the whole text). y is set to the real beginning
1250 Row * LyXText::GetRowNearY(int & y) const
1252 Row * tmprow = firstrow;
1255 while (tmprow->next() && tmpy + tmprow->height() <= y) {
1256 tmpy += tmprow->height();
1257 tmprow = tmprow->next();
1260 y = tmpy; // return the real y
1265 void LyXText::ToggleFree(BufferView * bview,
1266 LyXFont const & font, bool toggleall)
1268 // If the mask is completely neutral, tell user
1269 if (font == LyXFont(LyXFont::ALL_IGNORE)) {
1270 // Could only happen with user style
1271 bview->owner()->getMiniBuffer()
1272 ->Set(_("No font change defined. Use Character under"
1273 " the Layout menu to define font change."));
1277 // Try implicit word selection
1278 // If there is a change in the language the implicit word selection
1280 LyXCursor resetCursor = cursor;
1281 bool implicitSelection = (font.language() == ignore_language)
1282 ? SelectWordWhenUnderCursor(bview) : false;
1285 SetFont(bview, font, toggleall);
1287 /* Implicit selections are cleared afterwards and cursor is set to the
1288 original position. */
1289 if (implicitSelection) {
1291 cursor = resetCursor;
1292 SetCursor(bview, cursor.par(), cursor.pos());
1293 sel_cursor = cursor;
1298 LyXParagraph::size_type
1299 LyXText::BeginningOfMainBody(Buffer const * buf,
1300 LyXParagraph const * par) const
1302 if (textclasslist.Style(buf->params.textclass,
1303 par->GetLayout()).labeltype != LABEL_MANUAL)
1306 return par->BeginningOfMainBody();
1311 /* if there is a selection, reset every environment you can find
1312 * in the selection, otherwise just the environment you are in */
1313 void LyXText::MeltFootnoteEnvironment(BufferView * bview)
1315 LyXParagraph * tmppar, * firsttmppar;
1319 /* is is only allowed, if the cursor is IN an open footnote.
1320 * Otherwise it is too dangerous */
1321 if (cursor.par()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE)
1324 SetUndo(bview->buffer(), Undo::FINISH,
1325 cursor.par()->PreviousBeforeFootnote()->previous,
1326 cursor.par()->NextAfterFootnote()->next);
1328 /* ok, move to the beginning of the footnote. */
1329 while (cursor.par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
1330 cursor.par(cursor.par()->Previous());
1332 SetCursor(bview, cursor.par(), cursor.par()->Last());
1333 /* this is just faster than using CursorLeft(); */
1335 firsttmppar = cursor.par()->ParFromPos(cursor.pos());
1336 tmppar = firsttmppar;
1337 /* tmppar is now the paragraph right before the footnote */
1339 bool first_footnote_par_is_not_empty = tmppar->next->size();
1342 && tmppar->next->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1343 tmppar = tmppar->next; /* I use next instead of Next(),
1344 * because there cannot be any
1345 * footnotes in a footnote
1347 tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE;
1349 /* remember the captions and empty paragraphs */
1350 if ((textclasslist.Style(bview->buffer()->params.textclass,
1351 tmppar->GetLayout())
1352 .labeltype == LABEL_SENSITIVE)
1354 tmppar->SetLayout(bview->buffer()->params, 0);
1357 // now we will paste the ex-footnote, if the layouts allow it
1358 // first restore the layout of the paragraph right behind
1361 tmppar->next->MakeSameLayout(cursor.par());
1364 if (!tmppar->GetLayout()
1366 && (!tmppar->Next()->Last()
1367 || tmppar->Next()->HasSameLayout(tmppar)))) {
1368 if (tmppar->Next()->Last()
1369 && tmppar->Next()->IsLineSeparator(0))
1370 tmppar->Next()->Erase(0);
1371 tmppar->PasteParagraph(bview->buffer()->params);
1374 tmppar = tmppar->Next(); /* make sure tmppar cannot be touched
1375 * by the pasting of the beginning */
1377 /* then the beginning */
1378 /* if there is no space between the text and the footnote, so we insert
1380 * (only if the previous par and the footnotepar are not empty!) */
1381 if (!firsttmppar->next->GetLayout()
1382 || firsttmppar->HasSameLayout(firsttmppar->next)) {
1383 if (firsttmppar->size()
1384 && !firsttmppar->IsSeparator(firsttmppar->size() - 1)
1385 && first_footnote_par_is_not_empty) {
1386 firsttmppar->next->InsertChar(0, ' ');
1388 firsttmppar->PasteParagraph(bview->buffer()->params);
1391 /* now redo the paragaphs */
1392 RedoParagraphs(bview, cursor, tmppar);
1394 SetCursor(bview, cursor.par(), cursor.pos());
1396 /* sometimes it can happen, that there is a counter change */
1397 Row * row = cursor.row();
1398 while (row->next() && row->par() != tmppar && row->next()->par() != tmppar)
1400 UpdateCounters(bview, row);
1408 /* the DTP switches for paragraphs. LyX will store them in the
1409 * first physicla paragraph. When a paragraph is broken, the top settings
1410 * rest, the bottom settings are given to the new one. So I can make shure,
1411 * they do not duplicate themself and you cannnot make dirty things with
1414 void LyXText::SetParagraph(BufferView * bview,
1415 bool line_top, bool line_bottom,
1416 bool pagebreak_top, bool pagebreak_bottom,
1417 VSpace const & space_top,
1418 VSpace const & space_bottom,
1420 string labelwidthstring,
1423 LyXCursor tmpcursor = cursor;
1425 sel_start_cursor = cursor;
1426 sel_end_cursor = cursor;
1429 // make sure that the depth behind the selection are restored, too
1431 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
1433 LyXParagraph * endpar = sel_end_cursor.par()->Next();
1435 LyXParagraph * undoendpar = endpar;
1437 if (endpar && endpar->GetDepth()) {
1438 while (endpar && endpar->GetDepth()) {
1440 endpar = endpar->LastPhysicalPar()->Next();
1442 endpar = endpar->Next();
1444 undoendpar = endpar;
1448 endpar = endpar->Next(); // because of parindents etc.
1451 SetUndo(bview->buffer(), Undo::EDIT,
1454 .par()->ParFromPos(sel_start_cursor.pos())->previous,
1456 sel_start_cursor.par()->previous,
1461 LyXParagraph * tmppar = sel_end_cursor.par();
1463 while (tmppar != sel_start_cursor.par()->FirstPhysicalPar()->Previous()) {
1464 SetCursor(bview, tmppar->FirstPhysicalPar(), 0);
1466 while (tmppar != sel_start_cursor.par()->Previous()) {
1467 SetCursor(bview, tmppar, 0);
1469 status = LyXText::NEED_MORE_REFRESH;
1470 refresh_row = cursor.row();
1471 refresh_y = cursor.y() - cursor.row()->baseline();
1473 if (cursor.par()->footnoteflag ==
1474 sel_start_cursor.par()->footnoteflag) {
1476 cursor.par()->line_top = line_top;
1477 cursor.par()->line_bottom = line_bottom;
1478 cursor.par()->pagebreak_top = pagebreak_top;
1479 cursor.par()->pagebreak_bottom = pagebreak_bottom;
1480 cursor.par()->added_space_top = space_top;
1481 cursor.par()->added_space_bottom = space_bottom;
1482 // does the layout allow the new alignment?
1483 if (align == LYX_ALIGN_LAYOUT)
1484 align = textclasslist
1485 .Style(bview->buffer()->params.textclass,
1486 cursor.par()->GetLayout()).align;
1487 if (align & textclasslist
1488 .Style(bview->buffer()->params.textclass,
1489 cursor.par()->GetLayout()).alignpossible) {
1490 if (align == textclasslist
1491 .Style(bview->buffer()->params.textclass,
1492 cursor.par()->GetLayout()).align)
1493 cursor.par()->align = LYX_ALIGN_LAYOUT;
1495 cursor.par()->align = align;
1497 cursor.par()->SetLabelWidthString(labelwidthstring);
1498 cursor.par()->noindent = noindent;
1502 tmppar = cursor.par()->FirstPhysicalPar()->Previous();
1504 tmppar = cursor.par()->Previous();
1508 RedoParagraphs(bview, sel_start_cursor, endpar);
1511 SetCursor(bview, sel_start_cursor.par(), sel_start_cursor.pos());
1512 sel_cursor = cursor;
1513 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
1515 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
1517 bview->updateInset(inset_owner, true);
1521 void LyXText::SetParagraphExtraOpt(BufferView * bview, int type,
1522 string const & width,
1523 string const & widthp,
1524 int alignment, bool hfill,
1525 bool start_minipage)
1527 LyXCursor tmpcursor = cursor;
1528 LyXParagraph * tmppar;
1530 sel_start_cursor = cursor;
1531 sel_end_cursor = cursor;
1534 // make sure that the depth behind the selection are restored, too
1536 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
1538 LyXParagraph * endpar = sel_end_cursor.par()->Next();
1540 LyXParagraph * undoendpar = endpar;
1542 if (endpar && endpar->GetDepth()) {
1543 while (endpar && endpar->GetDepth()) {
1545 endpar = endpar->LastPhysicalPar()->Next();
1547 endpar = endpar->Next();
1549 undoendpar = endpar;
1553 endpar = endpar->Next(); // because of parindents etc.
1556 SetUndo(bview->buffer(), Undo::EDIT,
1559 .par()->ParFromPos(sel_start_cursor.pos())->previous,
1561 sel_start_cursor.par()->previous,
1565 tmppar = sel_end_cursor.par();
1567 while(tmppar != sel_start_cursor.par()->FirstPhysicalPar()->Previous()) {
1568 SetCursor(bview, tmppar->FirstPhysicalPar(), 0);
1570 while(tmppar != sel_start_cursor.par()->Previous()) {
1571 SetCursor(bview, tmppar, 0);
1573 status = LyXText::NEED_MORE_REFRESH;
1574 refresh_row = cursor.row();
1575 refresh_y = cursor.y() - cursor.row()->baseline();
1577 if (cursor.par()->footnoteflag ==
1578 sel_start_cursor.par()->footnoteflag) {
1580 if (type == LyXParagraph::PEXTRA_NONE) {
1581 if (cursor.par()->pextra_type != LyXParagraph::PEXTRA_NONE) {
1582 cursor.par()->UnsetPExtraType(bview->buffer()->params);
1583 cursor.par()->pextra_type = LyXParagraph::PEXTRA_NONE;
1586 cursor.par()->SetPExtraType(bview->buffer()->params,
1587 type, width, widthp);
1588 cursor.par()->pextra_hfill = hfill;
1589 cursor.par()->pextra_start_minipage = start_minipage;
1590 cursor.par()->pextra_alignment = alignment;
1594 tmppar = cursor.par()->FirstPhysicalPar()->Previous();
1596 tmppar = cursor.par()->Previous();
1599 RedoParagraphs(bview, sel_start_cursor, endpar);
1601 SetCursor(bview, sel_start_cursor.par(), sel_start_cursor.pos());
1602 sel_cursor = cursor;
1603 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
1605 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
1609 char loweralphaCounter(int n)
1611 if (n < 1 || n > 26)
1619 char alphaCounter(int n)
1621 if (n < 1 || n > 26)
1629 char hebrewCounter(int n)
1631 static const char hebrew[22] = {
1632 'à ', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è',
1633 'é', 'ë', 'ì', 'î', 'ð', 'ñ', 'ò', 'ô', 'ö',
1634 '÷', 'ø', 'ù', 'ú'
1636 if (n < 1 || n > 22)
1644 string const romanCounter(int n)
1646 static char const * roman[20] = {
1647 "i", "ii", "iii", "iv", "v",
1648 "vi", "vii", "viii", "ix", "x",
1649 "xi", "xii", "xiii", "xiv", "xv",
1650 "xvi", "xvii", "xviii", "xix", "xx"
1652 if (n < 1 || n > 20)
1659 // set the counter of a paragraph. This includes the labels
1660 void LyXText::SetCounter(Buffer const * buf, LyXParagraph * par) const
1663 // this is only relevant for the beginning of paragraph
1664 par = par->FirstPhysicalPar();
1666 LyXLayout const & layout =
1667 textclasslist.Style(buf->params.textclass,
1670 LyXTextClass const & textclass =
1671 textclasslist.TextClass(buf->params.textclass);
1673 /* copy the prev-counters to this one, unless this is the start of a
1674 footnote or of a bibliography or the very first paragraph */
1677 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1678 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1679 && par->footnotekind == LyXParagraph::FOOTNOTE)
1681 && !(textclasslist.Style(buf->params.textclass,
1682 par->Previous()->GetLayout()
1683 ).labeltype != LABEL_BIBLIO
1684 && layout.labeltype == LABEL_BIBLIO)) {
1685 for (int i = 0; i < 10; ++i) {
1686 par->setCounter(i, par->Previous()->GetFirstCounter(i));
1689 par->appendix = par->Previous()->FirstPhysicalPar()->appendix;
1691 par->appendix = par->Previous()->appendix;
1693 if (!par->appendix && par->start_of_appendix){
1694 par->appendix = true;
1695 for (int i = 0; i < 10; ++i) {
1696 par->setCounter(i, 0);
1700 par->enumdepth = par->Previous()->FirstPhysicalPar()->enumdepth;
1701 par->itemdepth = par->Previous()->FirstPhysicalPar()->itemdepth;
1703 par->enumdepth = par->Previous()->enumdepth;
1704 par->itemdepth = par->Previous()->itemdepth;
1707 for (int i = 0; i < 10; ++i) {
1708 par->setCounter(i, 0);
1710 par->appendix = par->start_of_appendix;
1716 // if this is an open marginnote and this is the first
1717 // entry in the marginnote and the enclosing
1718 // environment is an enum/item then correct for the
1719 // LaTeX behaviour (ARRae)
1720 if(par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1721 && par->footnotekind == LyXParagraph::MARGIN
1723 && par->Previous()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE
1724 && (par->PreviousBeforeFootnote()
1725 && textclasslist.Style(buf->params.textclass,
1726 par->PreviousBeforeFootnote()->GetLayout()
1727 ).labeltype >= LABEL_COUNTER_ENUMI)) {
1728 // Any itemize or enumerate environment in a marginnote
1729 // that is embedded in an itemize or enumerate
1730 // paragraph is seen by LaTeX as being at a deeper
1731 // level within that enclosing itemization/enumeration
1732 // even if there is a "standard" layout at the start of
1738 /* Maybe we have to increment the enumeration depth.
1739 * BUT, enumeration in a footnote is considered in isolation from its
1740 * surrounding paragraph so don't increment if this is the
1741 * first line of the footnote
1742 * AND, bibliographies can't have their depth changed ie. they
1743 * are always of depth 0
1746 && par->Previous()->GetDepth() < par->GetDepth()
1747 && textclasslist.Style(buf->params.textclass,
1748 par->Previous()->GetLayout()
1749 ).labeltype == LABEL_COUNTER_ENUMI
1750 && par->enumdepth < 3
1752 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1753 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1754 && par->footnotekind == LyXParagraph::FOOTNOTE)
1756 && layout.labeltype != LABEL_BIBLIO) {
1760 /* Maybe we have to decrement the enumeration depth, see note above */
1762 && par->Previous()->GetDepth() > par->GetDepth()
1764 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1765 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1766 && par->footnotekind == LyXParagraph::FOOTNOTE)
1768 && layout.labeltype != LABEL_BIBLIO) {
1769 par->enumdepth = par->DepthHook(par->GetDepth())->enumdepth;
1770 par->setCounter(6 + par->enumdepth,
1771 par->DepthHook(par->GetDepth())->getCounter(6 + par->enumdepth));
1772 /* reset the counters.
1773 * A depth change is like a breaking layout
1775 for (int i = 6 + par->enumdepth + 1; i < 10; ++i)
1776 par->setCounter(i, 0);
1779 if (!par->labelstring.empty()) {
1780 par->labelstring.erase();
1783 if (layout.margintype == MARGIN_MANUAL) {
1784 if (par->labelwidthstring.empty()) {
1785 par->SetLabelWidthString(layout.labelstring());
1788 par->SetLabelWidthString(string());
1791 /* is it a layout that has an automatic label ? */
1792 if (layout.labeltype >= LABEL_COUNTER_CHAPTER) {
1794 int i = layout.labeltype - LABEL_COUNTER_CHAPTER;
1795 if (i >= 0 && i<= buf->params.secnumdepth) {
1796 par->incCounter(i); // increment the counter
1798 // Is there a label? Useful for Chapter layout
1799 if (!par->appendix){
1800 if (!layout.labelstring().empty())
1801 par->labelstring = layout.labelstring();
1803 par->labelstring.erase();
1805 if (!layout.labelstring_appendix().empty())
1806 par->labelstring = layout.labelstring_appendix();
1808 par->labelstring.erase();
1811 std::ostringstream s;
1813 if (!par->appendix) {
1814 switch (2 * LABEL_COUNTER_CHAPTER -
1815 textclass.maxcounter() + i) {
1816 case LABEL_COUNTER_CHAPTER:
1817 s << par->getCounter(i);
1819 case LABEL_COUNTER_SECTION:
1820 s << par->getCounter(i - 1) << '.'
1821 << par->getCounter(i);
1823 case LABEL_COUNTER_SUBSECTION:
1824 s << par->getCounter(i - 2) << '.'
1825 << par->getCounter(i - 1) << '.'
1826 << par->getCounter(i);
1828 case LABEL_COUNTER_SUBSUBSECTION:
1829 s << par->getCounter(i - 3) << '.'
1830 << par->getCounter(i - 2) << '.'
1831 << par->getCounter(i - 1) << '.'
1832 << par->getCounter(i);
1835 case LABEL_COUNTER_PARAGRAPH:
1836 s << par->getCounter(i - 4) << '.'
1837 << par->getCounter(i - 3) << '.'
1838 << par->getCounter(i - 2) << '.'
1839 << par->getCounter(i - 1) << '.'
1840 << par->getCounter(i);
1842 case LABEL_COUNTER_SUBPARAGRAPH:
1843 s << par->getCounter(i - 5) << '.'
1844 << par->getCounter(i - 4) << '.'
1845 << par->getCounter(i - 3) << '.'
1846 << par->getCounter(i - 2) << '.'
1847 << par->getCounter(i - 1) << '.'
1848 << par->getCounter(i);
1852 // Can this ever be reached? And in the
1853 // case it is, how can this be correct?
1855 s << par->getCounter(i) << '.';
1858 } else { // appendix
1859 switch (2 * LABEL_COUNTER_CHAPTER - textclass.maxcounter() + i) {
1860 case LABEL_COUNTER_CHAPTER:
1861 if (par->isRightToLeftPar(buf->params))
1862 s << hebrewCounter(par->getCounter(i));
1864 s << alphaCounter(par->getCounter(i));
1866 case LABEL_COUNTER_SECTION:
1867 if (par->isRightToLeftPar(buf->params))
1868 s << hebrewCounter(par->getCounter(i - 1));
1870 s << alphaCounter(par->getCounter(i - 1));
1873 << par->getCounter(i);
1876 case LABEL_COUNTER_SUBSECTION:
1877 if (par->isRightToLeftPar(buf->params))
1878 s << hebrewCounter(par->getCounter(i - 2));
1880 s << alphaCounter(par->getCounter(i - 2));
1883 << par->getCounter(i-1) << '.'
1884 << par->getCounter(i);
1887 case LABEL_COUNTER_SUBSUBSECTION:
1888 if (par->isRightToLeftPar(buf->params))
1889 s << hebrewCounter(par->getCounter(i-3));
1891 s << alphaCounter(par->getCounter(i-3));
1894 << par->getCounter(i-2) << '.'
1895 << par->getCounter(i-1) << '.'
1896 << par->getCounter(i);
1899 case LABEL_COUNTER_PARAGRAPH:
1900 if (par->isRightToLeftPar(buf->params))
1901 s << hebrewCounter(par->getCounter(i-4));
1903 s << alphaCounter(par->getCounter(i-4));
1906 << par->getCounter(i-3) << '.'
1907 << par->getCounter(i-2) << '.'
1908 << par->getCounter(i-1) << '.'
1909 << par->getCounter(i);
1912 case LABEL_COUNTER_SUBPARAGRAPH:
1913 if (par->isRightToLeftPar(buf->params))
1914 s << hebrewCounter(par->getCounter(i-5));
1916 s << alphaCounter(par->getCounter(i-5));
1919 << par->getCounter(i-4) << '.'
1920 << par->getCounter(i-3) << '.'
1921 << par->getCounter(i-2) << '.'
1922 << par->getCounter(i-1) << '.'
1923 << par->getCounter(i);
1927 // Can this ever be reached? And in the
1928 // case it is, how can this be correct?
1930 s << par->getCounter(i) << '.';
1936 par->labelstring += s.str().c_str();
1937 // We really want to remove the c_str as soon as
1940 for (i++; i < 10; ++i) {
1941 // reset the following counters
1942 par->setCounter(i, 0);
1944 } else if (layout.labeltype < LABEL_COUNTER_ENUMI) {
1945 for (i++; i < 10; ++i) {
1946 // reset the following counters
1947 par->setCounter(i, 0);
1949 } else if (layout.labeltype == LABEL_COUNTER_ENUMI) {
1950 par->incCounter(i + par->enumdepth);
1951 int number = par->getCounter(i + par->enumdepth);
1953 std::ostringstream s;
1955 switch (par->enumdepth) {
1957 if (par->isRightToLeftPar(buf->params))
1959 << hebrewCounter(number)
1963 << loweralphaCounter(number)
1967 if (par->isRightToLeftPar(buf->params))
1968 s << '.' << romanCounter(number);
1970 s << romanCounter(number) << '.';
1973 if (par->isRightToLeftPar(buf->params))
1975 << alphaCounter(number);
1977 s << alphaCounter(number)
1981 if (par->isRightToLeftPar(buf->params))
1988 par->labelstring = s.str().c_str();
1989 // we really want to get rid of that c_str()
1991 for (i += par->enumdepth + 1; i < 10; ++i)
1992 par->setCounter(i, 0); /* reset the following counters */
1995 } else if (layout.labeltype == LABEL_BIBLIO) {// ale970302
1996 int i = LABEL_COUNTER_ENUMI - LABEL_COUNTER_CHAPTER + par->enumdepth;
1998 int number = par->getCounter(i);
2000 InsetCommandParams p( "bibitem" );
2001 par->bibkey = new InsetBibKey(p);
2003 par->bibkey->setCounter(number);
2004 par->labelstring = layout.labelstring();
2006 // In biblio should't be following counters but...
2008 string s = layout.labelstring();
2010 // the caption hack:
2011 if (layout.labeltype == LABEL_SENSITIVE) {
2012 bool isOK (par->InInset() && par->InInset()->owner() &&
2013 (par->InInset()->owner()->LyxCode() == Inset::FLOAT_CODE));
2015 if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2016 && (par->footnotekind == LyXParagraph::FIG
2017 || par->footnotekind == LyXParagraph::WIDE_FIG)) {
2018 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2019 ? ":øåéà " : "Figure:";
2020 } else if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2021 && (par->footnotekind == LyXParagraph::TAB
2022 || par->footnotekind == LyXParagraph::WIDE_TAB)) {
2023 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2024 ? ":äìáè" : "Table:";
2025 } else if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2026 && par->footnotekind == LyXParagraph::ALGORITHM) {
2027 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2028 ? ":Ãúéøåâìà " : "Algorithm:";
2032 InsetFloat * tmp = static_cast<InsetFloat*>(par->InInset()->owner());
2034 = floatList.getType(tmp->type());
2035 // We should get the correct number here too.
2036 s = fl.name + " #:";
2038 /* par->SetLayout(0);
2039 s = layout->labelstring; */
2040 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2041 ? " :úåòîùî øñç" : "Senseless: ";
2044 par->labelstring = s;
2046 /* reset the enumeration counter. They are always resetted
2047 * when there is any other layout between */
2048 for (int i = 6 + par->enumdepth; i < 10; ++i)
2049 par->setCounter(i, 0);
2054 /* Updates all counters BEHIND the row. Changed paragraphs
2055 * with a dynamic left margin will be rebroken. */
2056 void LyXText::UpdateCounters(BufferView * bview, Row * row) const
2063 if (row->par()->next
2065 && row->par()->next->footnoteflag != LyXParagraph::OPEN_FOOTNOTE
2069 par = row->par()->LastPhysicalPar()->Next();
2071 par = row->par()->Next();
2074 par = row->par()->next;
2079 while (row->par() != par)
2082 SetCounter(bview->buffer(), par);
2084 /* now check for the headline layouts. remember that they
2085 * have a dynamic left margin */
2090 ( textclasslist.Style(bview->buffer()->params.textclass,
2091 par->layout).margintype == MARGIN_DYNAMIC
2092 || textclasslist.Style(bview->buffer()->params.textclass,
2093 par->layout).labeltype == LABEL_SENSITIVE)
2096 /* Rebreak the paragraph */
2097 RemoveParagraph(row);
2098 AppendParagraph(bview, row);
2101 /* think about the damned open footnotes! */
2102 while (par->Next() &&
2103 (par->Next()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
2104 || par->Next()->IsDummy())){
2106 if (par->IsDummy()) {
2107 while (row->par() != par)
2109 RemoveParagraph(row);
2110 AppendParagraph(bview, row);
2116 par = par->LastPhysicalPar()->Next();
2125 /* insets an inset. */
2126 void LyXText::InsertInset(BufferView * bview, Inset * inset)
2128 if (!cursor.par()->InsertInsetAllowed(inset))
2130 SetUndo(bview->buffer(), Undo::INSERT,
2132 cursor.par()->ParFromPos(cursor.pos())->previous,
2133 cursor.par()->ParFromPos(cursor.pos())->next
2135 cursor.par()->previous,
2139 cursor.par()->InsertInset(cursor.pos(), inset);
2140 InsertChar(bview, LyXParagraph::META_INSET); /* just to rebreak and refresh correctly.
2141 * The character will not be inserted a
2144 // if we enter a text-inset the cursor should be to the left side
2145 // of it! This couldn't happen before as Undo was not handled inside
2146 // inset now after the Undo LyX tries to call inset->Edit(...) again
2147 // and cannot do this as the cursor is behind the inset and GetInset
2148 // does not return the inset!
2149 if (inset->IsTextInset()) {
2150 if (cursor.par()->isRightToLeftPar(bview->buffer()->params))
2159 void LyXText::copyEnvironmentType()
2161 copylayouttype = cursor.par()->GetLayout();
2165 void LyXText::pasteEnvironmentType(BufferView * bview)
2167 SetLayout(bview, copylayouttype);
2171 void LyXText::CutSelection(BufferView * bview, bool doclear)
2173 // Stuff what we got on the clipboard. Even if there is no selection.
2175 // There is a problem with having the stuffing here in that the
2176 // larger the selection the slower LyX will get. This can be
2177 // solved by running the line below only when the selection has
2178 // finished. The solution used currently just works, to make it
2179 // faster we need to be more clever and probably also have more
2180 // calls to stuffClipboard. (Lgb)
2181 bview->stuffClipboard(selectionAsString(bview->buffer()));
2183 // This doesn't make sense, if there is no selection
2187 // OK, we have a selection. This is always between sel_start_cursor
2188 // and sel_end cursor
2190 // Check whether there are half footnotes in the selection
2191 if (sel_start_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE
2192 || sel_end_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2193 LyXParagraph * tmppar = sel_start_cursor.par();
2194 while (tmppar != sel_end_cursor.par()){
2195 if (tmppar->footnoteflag != sel_end_cursor.par()->footnoteflag) {
2196 WriteAlert(_("Impossible operation"),
2197 _("Don't know what to do with half floats."),
2201 tmppar = tmppar->Next();
2206 // make sure that the depth behind the selection are restored, too
2208 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
2210 LyXParagraph * endpar = sel_end_cursor.par()->Next();
2212 LyXParagraph * undoendpar = endpar;
2214 if (endpar && endpar->GetDepth()) {
2215 while (endpar && endpar->GetDepth()) {
2217 endpar = endpar->LastPhysicalPar()->Next();
2219 endpar = endpar->Next();
2221 undoendpar = endpar;
2223 } else if (endpar) {
2224 endpar = endpar->Next(); // because of parindents etc.
2227 SetUndo(bview->buffer(), Undo::DELETE,
2230 .par()->ParFromPos(sel_start_cursor.pos())->previous,
2232 sel_start_cursor.par()->previous,
2238 // there are two cases: cut only within one paragraph or
2239 // more than one paragraph
2241 if (sel_start_cursor.par()->ParFromPos(sel_start_cursor.pos())
2242 == sel_end_cursor.par()->ParFromPos(sel_end_cursor.pos()))
2244 if (sel_start_cursor.par() == sel_end_cursor.par())
2247 // only within one paragraph
2248 endpar = sel_start_cursor.par();
2249 int pos = sel_end_cursor.pos();
2250 cap.cutSelection(sel_start_cursor.par(), &endpar,
2251 sel_start_cursor.pos(), pos,
2252 bview->buffer()->params.textclass, doclear);
2253 sel_end_cursor.pos(pos);
2255 endpar = sel_end_cursor.par();
2257 int pos = sel_end_cursor.pos();
2258 cap.cutSelection(sel_start_cursor.par(), &endpar,
2259 sel_start_cursor.pos(), pos,
2260 bview->buffer()->params.textclass, doclear);
2262 sel_end_cursor.par(endpar);
2263 sel_end_cursor.pos(pos);
2264 cursor.pos(sel_end_cursor.pos());
2266 endpar = endpar->Next();
2268 // sometimes necessary
2270 sel_start_cursor.par()->StripLeadingSpaces(bview->buffer()->params.textclass);
2272 RedoParagraphs(bview, sel_start_cursor, endpar);
2275 cursor = sel_start_cursor;
2276 SetCursor(bview, cursor.par(), cursor.pos());
2277 sel_cursor = cursor;
2278 UpdateCounters(bview, cursor.row());
2282 void LyXText::CopySelection(BufferView * bview)
2284 // Stuff what we got on the clipboard. Even if there is no selection.
2286 // There is a problem with having the stuffing here in that the
2287 // larger the selection the slower LyX will get. This can be
2288 // solved by running the line below only when the selection has
2289 // finished. The solution used currently just works, to make it
2290 // faster we need to be more clever and probably also have more
2291 // calls to stuffClipboard. (Lgb)
2292 bview->stuffClipboard(selectionAsString(bview->buffer()));
2294 // this doesnt make sense, if there is no selection
2298 // ok we have a selection. This is always between sel_start_cursor
2299 // and sel_end cursor
2302 /* check wether there are half footnotes in the selection */
2303 if (sel_start_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE
2304 || sel_end_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2305 LyXParagraph * tmppar = sel_start_cursor.par();
2306 while (tmppar != sel_end_cursor.par()) {
2307 if (tmppar->footnoteflag !=
2308 sel_end_cursor.par()->footnoteflag) {
2309 WriteAlert(_("Impossible operation"),
2310 _("Don't know what to do"
2311 " with half floats."),
2315 tmppar = tmppar->Next();
2320 // copy behind a space if there is one
2321 while (sel_start_cursor.par()->Last() > sel_start_cursor.pos()
2322 && sel_start_cursor.par()->IsLineSeparator(sel_start_cursor.pos())
2323 && (sel_start_cursor.par() != sel_end_cursor.par()
2324 || sel_start_cursor.pos() < sel_end_cursor.pos()))
2325 sel_start_cursor.pos(sel_start_cursor.pos() + 1);
2329 cap.copySelection(sel_start_cursor.par(), sel_end_cursor.par(),
2330 sel_start_cursor.pos(), sel_end_cursor.pos(),
2331 bview->buffer()->params.textclass);
2335 void LyXText::PasteSelection(BufferView * bview)
2339 // this does not make sense, if there is nothing to paste
2340 if (!cap.checkPastePossible(cursor.par(), cursor.pos()))
2343 SetUndo(bview->buffer(), Undo::INSERT,
2345 cursor.par()->ParFromPos(cursor.pos())->previous,
2346 cursor.par()->ParFromPos(cursor.pos())->next
2348 cursor.par()->previous,
2353 LyXParagraph * endpar;
2354 LyXParagraph * actpar = cursor.par();
2356 int pos = cursor.pos();
2357 cap.pasteSelection(&actpar, &endpar, pos, bview->buffer()->params.textclass);
2359 RedoParagraphs(bview, cursor, endpar);
2361 SetCursor(bview, cursor.par(), cursor.pos());
2364 sel_cursor = cursor;
2365 SetCursor(bview, actpar, pos);
2367 UpdateCounters(bview, cursor.row());
2371 // returns a pointer to the very first LyXParagraph
2372 LyXParagraph * LyXText::FirstParagraph() const
2374 return OwnerParagraph();
2378 // returns true if the specified string is at the specified position
2379 bool LyXText::IsStringInText(LyXParagraph * par,
2380 LyXParagraph::size_type pos,
2381 string const & str) const
2384 LyXParagraph::size_type i = 0;
2385 while (pos + i < par->Last()
2386 && string::size_type(i) < str.length()
2387 && str[i] == par->GetChar(pos + i)) {
2390 if (str.length() == string::size_type(i))
2397 // sets the selection over the number of characters of string, no check!!
2398 void LyXText::SetSelectionOverString(BufferView * bview, string const & str)
2400 sel_cursor = cursor;
2401 for (int i = 0; str[i]; ++i)
2407 // simple replacing. The font of the first selected character is used
2408 void LyXText::ReplaceSelectionWithString(BufferView * bview,
2411 SetCursorParUndo(bview->buffer());
2414 if (!selection) { // create a dummy selection
2415 sel_end_cursor = cursor;
2416 sel_start_cursor = cursor;
2419 // Get font setting before we cut
2420 LyXParagraph::size_type pos = sel_end_cursor.pos();
2421 LyXFont const font = sel_start_cursor.par()
2422 ->GetFontSettings(bview->buffer()->params,
2423 sel_start_cursor.pos());
2425 // Insert the new string
2426 for (string::const_iterator cit = str.begin(); cit != str.end(); ++cit) {
2427 sel_end_cursor.par()->InsertChar(pos, (*cit), font);
2431 // Cut the selection
2432 CutSelection(bview);
2438 // if the string can be found: return true and set the cursor to
2440 bool LyXText::SearchForward(BufferView * bview, string const & str) const
2442 LyXParagraph * par = cursor.par();
2443 LyXParagraph::size_type pos = cursor.pos();
2444 while (par && !IsStringInText(par, pos, str)) {
2445 if (pos < par->Last() - 1)
2453 SetCursor(bview, par, pos);
2461 bool LyXText::SearchBackward(BufferView * bview, string const & str) const
2463 LyXParagraph * par = cursor.par();
2464 int pos = cursor.pos();
2470 // We skip empty paragraphs (Asger)
2472 par = par->Previous();
2474 pos = par->Last() - 1;
2475 } while (par && pos < 0);
2477 } while (par && !IsStringInText(par, pos, str));
2480 SetCursor(bview, par, pos);
2487 // needed to insert the selection
2488 void LyXText::InsertStringA(BufferView * bview, string const & str)
2490 LyXParagraph * par = cursor.par();
2491 LyXParagraph::size_type pos = cursor.pos();
2492 LyXParagraph::size_type a = 0;
2493 LyXParagraph * endpar = cursor.par()->Next();
2495 SetCursorParUndo(bview->buffer());
2498 textclasslist.Style(bview->buffer()->params.textclass,
2499 cursor.par()->GetLayout()).isEnvironment();
2500 // only to be sure, should not be neccessary
2503 // insert the string, don't insert doublespace
2504 string::size_type i = 0;
2505 while (i < str.length()) {
2506 if (str[i] != '\n') {
2508 && i + 1 < str.length() && str[i + 1] != ' '
2509 && pos && par->GetChar(pos - 1)!= ' ') {
2510 par->InsertChar(pos, ' ', current_font);
2512 } else if (str[i] == ' ') {
2513 InsetSpecialChar * new_inset =
2514 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2515 if (par->InsertInsetAllowed(new_inset)) {
2516 par->InsertInset(pos, new_inset,
2522 } else if (str[i] == '\t') {
2523 for (a = pos; a < (pos / 8 + 1) * 8 ; ++a) {
2524 InsetSpecialChar * new_inset =
2525 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2526 if (par->InsertInsetAllowed(new_inset)) {
2527 par->InsertInset(pos, new_inset,
2534 } else if (str[i] != 13 &&
2535 // Ignore unprintables
2536 (str[i] & 127) >= ' ') {
2537 par->InsertChar(pos, str[i], current_font);
2541 if (!par->size()) { // par is empty
2542 InsetSpecialChar * new_inset =
2543 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2544 if (par->InsertInsetAllowed(new_inset)) {
2545 par->InsertInset(pos,
2553 par->BreakParagraph(bview->buffer()->params, pos, flag);
2560 RedoParagraphs(bview, cursor, endpar);
2561 SetCursor(bview, cursor.par(), cursor.pos());
2562 sel_cursor = cursor;
2563 SetCursor(bview, par, pos);
2568 /* turns double-CR to single CR, others where converted into one blank and 13s
2569 * that are ignored .Double spaces are also converted into one. Spaces at
2570 * the beginning of a paragraph are forbidden. tabs are converted into one
2571 * space. then InsertStringA is called */
2572 void LyXText::InsertStringB(BufferView * bview, string const & s)
2575 string::size_type i = 1;
2576 while (i < str.length()) {
2579 if (str[i] == ' ' && i + 1 < str.length() && str[i + 1] == ' ')
2581 if (str[i] == '\n' && i + 1 < str.length()) {
2582 if (str[i + 1] != '\n') {
2583 if (str[i - 1] != ' ')
2588 while (i + 1 < str.length()
2589 && (str[i + 1] == ' '
2590 || str[i + 1] == '\t'
2591 || str[i + 1] == '\n'
2592 || str[i + 1] == 13)) {
2599 InsertStringA(bview, str);
2603 bool LyXText::GotoNextError(BufferView * bview) const
2605 LyXCursor res = cursor;
2607 if (res.pos() < res.par()->Last() - 1) {
2608 res.pos(res.pos() + 1);
2610 res.par(res.par()->Next());
2614 } while (res.par() &&
2615 !(res.par()->GetChar(res.pos()) == LyXParagraph::META_INSET
2616 && res.par()->GetInset(res.pos())->AutoDelete()));
2619 SetCursor(bview, res.par(), res.pos());
2626 bool LyXText::GotoNextNote(BufferView * bview) const
2628 LyXCursor res = cursor;
2630 if (res.pos() < res.par()->Last() - 1) {
2631 res.pos(res.pos() + 1);
2633 res.par(res.par()->Next());
2637 } while (res.par() &&
2638 !(res.par()->GetChar(res.pos()) == LyXParagraph::META_INSET
2639 && res.par()->GetInset(res.pos())->LyxCode() == Inset::IGNORE_CODE));
2642 SetCursor(bview, res.par(), res.pos());
2649 void LyXText::CheckParagraph(BufferView * bview, LyXParagraph * par,
2650 LyXParagraph::size_type pos)
2652 LyXCursor tmpcursor;
2655 LyXParagraph::size_type z;
2656 Row * row = GetRow(par, pos, y);
2658 // is there a break one row above
2659 if (row->previous() && row->previous()->par() == row->par()) {
2660 z = NextBreakPoint(bview, row->previous(), workWidth(bview));
2661 if ( z >= row->pos()) {
2662 // set the dimensions of the row above
2663 y -= row->previous()->height();
2665 refresh_row = row->previous();
2666 status = LyXText::NEED_MORE_REFRESH;
2668 BreakAgain(bview, row->previous());
2670 // set the cursor again. Otherwise
2671 // dangling pointers are possible
2672 SetCursor(bview, cursor.par(), cursor.pos());
2673 sel_cursor = cursor;
2678 int const tmpheight = row->height();
2679 LyXParagraph::size_type const tmplast = RowLast(row);
2683 BreakAgain(bview, row);
2684 if (row->height() == tmpheight && RowLast(row) == tmplast)
2685 status = LyXText::NEED_VERY_LITTLE_REFRESH;
2687 status = LyXText::NEED_MORE_REFRESH;
2689 // check the special right address boxes
2690 if (textclasslist.Style(bview->buffer()->params.textclass,
2691 par->GetLayout()).margintype
2692 == MARGIN_RIGHT_ADDRESS_BOX) {
2699 RedoDrawingOfParagraph(bview, tmpcursor);
2702 // set the cursor again. Otherwise dangling pointers are possible
2703 // also set the selection
2707 SetCursorIntern(bview, sel_cursor.par(), sel_cursor.pos());
2708 sel_cursor = cursor;
2709 SetCursorIntern(bview, sel_start_cursor.par(),
2710 sel_start_cursor.pos());
2711 sel_start_cursor = cursor;
2712 SetCursorIntern(bview, sel_end_cursor.par(),
2713 sel_end_cursor.pos());
2714 sel_end_cursor = cursor;
2715 SetCursorIntern(bview, last_sel_cursor.par(),
2716 last_sel_cursor.pos());
2717 last_sel_cursor = cursor;
2720 SetCursorIntern(bview, cursor.par(), cursor.pos());
2724 // returns false if inset wasn't found
2725 bool LyXText::UpdateInset(BufferView * bview, Inset * inset)
2727 // first check the current paragraph
2728 int pos = cursor.par()->GetPositionOfInset(inset);
2730 CheckParagraph(bview, cursor.par(), pos);
2734 // check every paragraph
2736 LyXParagraph * par = FirstParagraph();
2739 // make sure the paragraph is open
2740 if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
2742 pos = par->GetPositionOfInset(inset);
2744 CheckParagraph(bview, par, pos);
2757 void LyXText::SetCursor(BufferView * bview, LyXParagraph * par,
2758 LyXParagraph::size_type pos,
2759 bool setfont, bool boundary) const
2761 LyXCursor old_cursor = cursor;
2762 SetCursorIntern(bview, par, pos, setfont, boundary);
2763 DeleteEmptyParagraphMechanism(bview, old_cursor);
2767 void LyXText::SetCursor(BufferView *bview, LyXCursor & cur, LyXParagraph * par,
2768 LyXParagraph::size_type pos, bool boundary) const
2771 // correct the cursor position if impossible
2772 if (pos > par->Last()){
2773 LyXParagraph * tmppar = par->ParFromPos(pos);
2774 pos = par->PositionInParFromPos(pos);
2777 if (par->IsDummy() && par->previous &&
2778 par->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2779 while (par->previous &&
2780 ((par->previous->IsDummy() &&
2781 (par->previous->previous->footnoteflag ==
2782 LyXParagraph::CLOSED_FOOTNOTE)) ||
2783 (par->previous->footnoteflag ==
2784 LyXParagraph::CLOSED_FOOTNOTE))) {
2785 par = par->previous ;
2786 if (par->IsDummy() &&
2787 (par->previous->footnoteflag ==
2788 LyXParagraph::CLOSED_FOOTNOTE))
2789 pos += par->size() + 1;
2791 if (par->previous) {
2792 par = par->previous;
2794 pos += par->size() + 1;
2799 cur.boundary(boundary);
2801 /* get the cursor y position in text */
2803 Row * row = GetRow(par, pos, y);
2804 /* y is now the beginning of the cursor row */
2805 y += row->baseline();
2806 /* y is now the cursor baseline */
2809 /* now get the cursors x position */
2811 float fill_separator, fill_hfill, fill_label_hfill;
2812 PrepareToPrint(bview, row, x, fill_separator, fill_hfill,
2814 LyXParagraph::size_type cursor_vpos = 0;
2815 LyXParagraph::size_type last = RowLastPrintable(row);
2817 if (pos > last + 1) // This shouldn't happen.
2819 else if (pos < row->pos())
2822 if (last < row->pos())
2823 cursor_vpos = row->pos();
2824 else if (pos > last && !boundary)
2825 cursor_vpos = (row->par()->isRightToLeftPar(bview->buffer()->params))
2826 ? row->pos() : last + 1;
2827 else if (pos > row->pos() &&
2828 (pos > last || boundary))
2829 /// Place cursor after char at (logical) position pos - 1
2830 cursor_vpos = (bidi_level(pos - 1) % 2 == 0)
2831 ? log2vis(pos - 1) + 1 : log2vis(pos - 1);
2833 /// Place cursor before char at (logical) position pos
2834 cursor_vpos = (bidi_level(pos) % 2 == 0)
2835 ? log2vis(pos) : log2vis(pos) + 1;
2837 LyXParagraph::size_type main_body =
2838 BeginningOfMainBody(bview->buffer(), row->par());
2839 if ((main_body > 0) &&
2840 ((main_body-1 > last) ||
2841 !row->par()->IsLineSeparator(main_body-1)))
2844 for (LyXParagraph::size_type vpos = row->pos();
2845 vpos < cursor_vpos; ++vpos) {
2846 pos = vis2log(vpos);
2847 if (main_body > 0 && pos == main_body - 1) {
2848 x += fill_label_hfill +
2849 lyxfont::width(textclasslist.Style(
2850 bview->buffer()->params.textclass,
2851 row->par()->GetLayout())
2853 GetFont(bview->buffer(), row->par(), -2));
2854 if (row->par()->IsLineSeparator(main_body-1))
2855 x -= SingleWidth(bview, row->par(),main_body-1);
2857 if (HfillExpansion(bview->buffer(), row, pos)) {
2858 x += SingleWidth(bview, row->par(), pos);
2859 if (pos >= main_body)
2862 x += fill_label_hfill;
2863 } else if (row->par()->IsSeparator(pos)) {
2864 x += SingleWidth(bview, row->par(), pos);
2865 if (pos >= main_body)
2866 x += fill_separator;
2868 x += SingleWidth(bview, row->par(), pos);
2877 void LyXText::SetCursorIntern(BufferView * bview, LyXParagraph * par,
2878 LyXParagraph::size_type pos,
2879 bool setfont, bool boundary) const
2881 SetCursor(bview, cursor, par, pos, boundary);
2883 SetCurrentFont(bview);
2887 void LyXText::SetCurrentFont(BufferView * bview) const
2889 LyXParagraph::size_type pos = cursor.pos();
2890 if (cursor.boundary() && pos > 0)
2894 if (pos == cursor.par()->Last())
2896 else if (cursor.par()->IsSeparator(pos)) {
2897 if (pos > cursor.row()->pos() &&
2898 bidi_level(pos) % 2 ==
2899 bidi_level(pos - 1) % 2)
2901 else if (pos + 1 < cursor.par()->Last())
2907 cursor.par()->GetFontSettings(bview->buffer()->params, pos);
2908 real_current_font = GetFont(bview->buffer(), cursor.par(), pos);
2910 if (cursor.pos() == cursor.par()->Last() &&
2911 IsBoundary(bview->buffer(), cursor.par(), cursor.pos()) &&
2912 !cursor.boundary()) {
2913 Language const * lang =
2914 cursor.par()->getParLanguage(bview->buffer()->params);
2915 current_font.setLanguage(lang);
2916 real_current_font.setLanguage(lang);
2921 void LyXText::SetCursorFromCoordinates(BufferView * bview, int x, int y) const
2923 LyXCursor old_cursor = cursor;
2925 /* get the row first */
2927 Row * row = GetRowNearY(y);
2928 cursor.par(row->par());
2931 int column = GetColumnNearX(bview, row, x, bound);
2932 cursor.pos(row->pos() + column);
2934 cursor.y(y + row->baseline());
2936 cursor.boundary(bound);
2937 SetCurrentFont(bview);
2938 DeleteEmptyParagraphMechanism(bview, old_cursor);
2942 void LyXText::SetCursorFromCoordinates(BufferView * bview, LyXCursor & cur,
2945 /* get the row first */
2947 Row * row = GetRowNearY(y);
2949 int column = GetColumnNearX(bview, row, x, bound);
2951 cur.par(row->par());
2952 cur.pos(row->pos() + column);
2954 cur.y(y + row->baseline());
2956 cur.boundary(bound);
2960 void LyXText::CursorLeft(BufferView * bview, bool internal) const
2962 if (cursor.pos() > 0) {
2963 bool boundary = cursor.boundary();
2964 SetCursor(bview, cursor.par(), cursor.pos() - 1, true, false);
2965 if (!internal && !boundary &&
2966 IsBoundary(bview->buffer(), cursor.par(), cursor.pos() + 1))
2967 SetCursor(bview, cursor.par(), cursor.pos() + 1, true, true);
2968 } else if (cursor.par()->Previous()) { // steps into the above paragraph.
2969 LyXParagraph * par = cursor.par()->Previous();
2970 SetCursor(bview, par, par->Last());
2975 void LyXText::CursorRight(BufferView * bview, bool internal) const
2977 if (!internal && cursor.boundary() &&
2978 !cursor.par()->IsNewline(cursor.pos()))
2979 SetCursor(bview, cursor.par(), cursor.pos(), true, false);
2980 else if (cursor.pos() < cursor.par()->Last()) {
2981 SetCursor(bview, cursor.par(), cursor.pos() + 1, true, false);
2983 IsBoundary(bview->buffer(), cursor.par(), cursor.pos()))
2984 SetCursor(bview, cursor.par(), cursor.pos(), true, true);
2985 } else if (cursor.par()->Next())
2986 SetCursor(bview, cursor.par()->Next(), 0);
2990 void LyXText::CursorUp(BufferView * bview) const
2992 SetCursorFromCoordinates(bview, cursor.x_fix(),
2993 cursor.y() - cursor.row()->baseline() - 1);
2997 void LyXText::CursorDown(BufferView * bview) const
2999 SetCursorFromCoordinates(bview, cursor.x_fix(),
3000 cursor.y() - cursor.row()->baseline()
3001 + cursor.row()->height() + 1);
3005 void LyXText::CursorUpParagraph(BufferView * bview) const
3007 if (cursor.pos() > 0) {
3008 SetCursor(bview, cursor.par(), 0);
3010 else if (cursor.par()->Previous()) {
3011 SetCursor(bview, cursor.par()->Previous(), 0);
3016 void LyXText::CursorDownParagraph(BufferView * bview) const
3018 if (cursor.par()->Next()) {
3019 SetCursor(bview, cursor.par()->Next(), 0);
3021 SetCursor(bview, cursor.par(), cursor.par()->Last());
3026 void LyXText::DeleteEmptyParagraphMechanism(BufferView * bview,
3027 LyXCursor const & old_cursor) const
3029 // Would be wrong to delete anything if we have a selection.
3030 if (selection) return;
3032 // We allow all kinds of "mumbo-jumbo" when freespacing.
3033 if (textclasslist.Style(bview->buffer()->params.textclass,
3034 old_cursor.par()->GetLayout()).free_spacing)
3037 bool deleted = false;
3039 /* Ok I'll put some comments here about what is missing.
3040 I have fixed BackSpace (and thus Delete) to not delete
3041 double-spaces automagically. I have also changed Cut,
3042 Copy and Paste to hopefully do some sensible things.
3043 There are still some small problems that can lead to
3044 double spaces stored in the document file or space at
3045 the beginning of paragraphs. This happens if you have
3046 the cursor betwenn to spaces and then save. Or if you
3047 cut and paste and the selection have a space at the
3048 beginning and then save right after the paste. I am
3049 sure none of these are very hard to fix, but I will
3050 put out 1.1.4pre2 with FIX_DOUBLE_SPACE defined so
3051 that I can get some feedback. (Lgb)
3054 // If old_cursor.pos() == 0 and old_cursor.pos()(1) == LineSeparator
3055 // delete the LineSeparator.
3058 // If old_cursor.pos() == 1 and old_cursor.pos()(0) == LineSeparator
3059 // delete the LineSeparator.
3062 // If the pos around the old_cursor were spaces, delete one of them.
3063 if (old_cursor.par() != cursor.par() || old_cursor.pos() != cursor.pos()) {
3064 // Only if the cursor has really moved
3066 if (old_cursor.pos() > 0
3067 && old_cursor.pos() < old_cursor.par()->Last()
3068 && old_cursor.par()->IsLineSeparator(old_cursor.pos())
3069 && old_cursor.par()->IsLineSeparator(old_cursor.pos() - 1)) {
3070 old_cursor.par()->Erase(old_cursor.pos() - 1);
3071 RedoParagraphs(bview, old_cursor, old_cursor.par()->Next());
3073 if (old_cursor.par() == cursor.par() &&
3074 cursor.pos() > old_cursor.pos()) {
3075 SetCursorIntern(bview, cursor.par(),
3078 SetCursorIntern(bview, cursor.par(),
3084 // Do not delete empty paragraphs with keepempty set.
3085 if ((textclasslist.Style(bview->buffer()->params.textclass,
3086 old_cursor.par()->GetLayout())).keepempty)
3089 LyXCursor tmpcursor;
3091 if (old_cursor.par() != cursor.par()) {
3092 if ( (old_cursor.par()->Last() == 0
3093 || (old_cursor.par()->Last() == 1
3094 && old_cursor.par()->IsLineSeparator(0)))
3096 && old_cursor.par()->FirstPhysicalPar()
3097 == old_cursor.par()->LastPhysicalPar()
3100 // ok, we will delete anything
3102 // make sure that you do not delete any environments
3105 old_cursor.par()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE &&
3106 !(old_cursor.row()->previous()
3107 && old_cursor.row()->previous()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
3108 && !(old_cursor.row()->next()
3109 && old_cursor.row()->next()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE))
3110 || (old_cursor.par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
3111 && ((old_cursor.row()->previous()
3112 && old_cursor.row()->previous()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
3113 || (old_cursor.row()->next()
3114 && old_cursor.row()->next()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE))
3117 status = LyXText::NEED_MORE_REFRESH;
3120 if (old_cursor.row()->previous()) {
3121 refresh_row = old_cursor.row()->previous();
3122 refresh_y = old_cursor.y() - old_cursor.row()->baseline() - refresh_row->height();
3124 cursor = old_cursor; // that undo can restore the right cursor position
3125 LyXParagraph * endpar = old_cursor.par()->next;
3126 if (endpar && endpar->GetDepth()) {
3127 while (endpar && endpar->GetDepth()) {
3129 endpar = endpar->LastPhysicalPar()->Next();
3131 endpar = endpar->Next();
3135 SetUndo(bview->buffer(), Undo::DELETE,
3136 old_cursor.par()->previous,
3141 RemoveRow(old_cursor.row());
3142 if (OwnerParagraph() == old_cursor.par()) {
3143 OwnerParagraph(OwnerParagraph()->next);
3146 delete old_cursor.par();
3148 /* Breakagain the next par. Needed
3149 * because of the parindent that
3150 * can occur or dissappear. The
3151 * next row can change its height,
3152 * if there is another layout before */
3153 if (refresh_row->next()) {
3154 BreakAgain(bview, refresh_row->next());
3155 UpdateCounters(bview, refresh_row);
3157 SetHeightOfRow(bview, refresh_row);
3159 refresh_row = old_cursor.row()->next();
3160 refresh_y = old_cursor.y() - old_cursor.row()->baseline();
3163 cursor = old_cursor; // that undo can restore the right cursor position
3164 LyXParagraph * endpar = old_cursor.par()->next;
3165 if (endpar && endpar->GetDepth()) {
3166 while (endpar && endpar->GetDepth()) {
3168 endpar = endpar->LastPhysicalPar()->Next();
3170 endpar = endpar->Next();
3174 SetUndo(bview->buffer(), Undo::DELETE,
3175 old_cursor.par()->previous,
3180 RemoveRow(old_cursor.row());
3182 if (OwnerParagraph() == old_cursor.par()) {
3183 OwnerParagraph(OwnerParagraph()->next);
3185 delete old_cursor.par();
3187 /* Breakagain the next par. Needed
3188 because of the parindent that can
3189 occur or dissappear.
3190 The next row can change its height,
3191 if there is another layout before
3194 BreakAgain(bview, refresh_row);
3195 UpdateCounters(bview, refresh_row->previous());
3201 SetCursorIntern(bview, cursor.par(), cursor.pos());
3203 if (sel_cursor.par() == old_cursor.par()
3204 && sel_cursor.pos() == sel_cursor.pos()) {
3205 // correct selection
3206 sel_cursor = cursor;
3213 if (old_cursor.par()->StripLeadingSpaces(bview->buffer()->params.textclass)) {
3214 RedoParagraphs(bview, old_cursor, old_cursor.par()->Next());
3216 SetCursorIntern(bview, cursor.par(), cursor.pos());
3217 sel_cursor = cursor;
3224 LyXParagraph * LyXText::GetParFromID(int id)
3226 LyXParagraph * result = FirstParagraph();
3227 while (result && result->id() != id)
3228 result = result->next;
3234 bool LyXText::TextUndo(BufferView * bview)
3238 // returns false if no undo possible
3239 Undo * undo = bview->buffer()->undostack.pop();
3243 bview->buffer()->redostack
3244 .push(CreateUndo(bview->buffer(), undo->kind,
3245 GetParFromID(undo->number_of_before_par),
3246 GetParFromID(undo->number_of_behind_par)));
3248 return TextHandleUndo(bview, undo);
3252 bool LyXText::TextRedo(BufferView * bview)
3256 // returns false if no redo possible
3257 Undo * undo = bview->buffer()->redostack.pop();
3261 bview->buffer()->undostack
3262 .push(CreateUndo(bview->buffer(), undo->kind,
3263 GetParFromID(undo->number_of_before_par),
3264 GetParFromID(undo->number_of_behind_par)));
3266 return TextHandleUndo(bview, undo);
3270 bool LyXText::TextHandleUndo(BufferView * bview, Undo * undo)
3274 // returns false if no undo possible
3275 bool result = false;
3277 LyXParagraph * before =
3278 GetParFromID(undo->number_of_before_par);
3279 LyXParagraph * behind =
3280 GetParFromID(undo->number_of_behind_par);
3281 LyXParagraph * tmppar;
3282 LyXParagraph * tmppar2;
3283 LyXParagraph * endpar;
3284 LyXParagraph * tmppar5;
3286 // if there's no before take the beginning
3287 // of the document for redoing
3289 SetCursorIntern(bview, FirstParagraph(), 0);
3291 // replace the paragraphs with the undo informations
3293 LyXParagraph * tmppar3 = undo->par;
3294 undo->par = 0; // otherwise the undo destructor would delete the paragraph
3295 LyXParagraph * tmppar4 = tmppar3;
3297 while (tmppar4->next)
3298 tmppar4 = tmppar4->next;
3299 } // get last undo par
3301 // now remove the old text if there is any
3302 if (before != behind || (!behind && !before)){
3304 tmppar5 = before->next;
3306 tmppar5 = OwnerParagraph();
3308 while (tmppar5 && tmppar5 != behind){
3310 tmppar5 = tmppar5->next;
3311 // a memory optimization for edit: Only layout information
3312 // is stored in the undo. So restore the text informations.
3313 if (undo->kind == Undo::EDIT) {
3314 tmppar2->setContentsFromPar(tmppar);
3315 tmppar->clearContents();
3316 tmppar2 = tmppar2->next;
3321 // put the new stuff in the list if there is one
3324 before->next = tmppar3;
3326 OwnerParagraph(tmppar3);
3327 tmppar3->previous = before;
3330 OwnerParagraph(behind);
3333 tmppar4->next = behind;
3335 behind->previous = tmppar4;
3339 // Set the cursor for redoing
3342 SetCursorIntern(bview, before->FirstSelfrowPar(), 0);
3344 SetCursorIntern(bview, before, 0);
3347 // check wether before points to a closed float and open it if necessary
3348 if (before && before->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE
3349 && before->next && before->next->footnoteflag != LyXParagraph::NO_FOOTNOTE){
3351 while (tmppar4->previous &&
3352 tmppar4->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
3353 tmppar4 = tmppar4->previous;
3354 while (tmppar4 && tmppar4->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3355 tmppar4->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
3356 tmppar4 = tmppar4->next;
3363 // open a cosed footnote at the end if necessary
3364 if (behind && behind->previous &&
3365 behind->previous->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
3366 behind->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3367 while (behind && behind->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3368 behind->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
3369 behind = behind->next;
3374 // calculate the endpar for redoing the paragraphs.
3377 if (behind->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
3378 endpar = behind->LastPhysicalPar()->Next();
3380 endpar = behind->NextAfterFootnote()->LastPhysicalPar()->Next();
3382 endpar = behind->Next();
3387 tmppar = GetParFromID(undo->number_of_cursor_par);
3388 RedoParagraphs(bview, cursor, endpar);
3390 SetCursorIntern(bview, tmppar, undo->cursor_pos);
3391 UpdateCounters(bview, cursor.row());
3401 void LyXText::FinishUndo()
3405 // makes sure the next operation will be stored
3406 undo_finished = true;
3410 void LyXText::FreezeUndo()
3414 // this is dangerous and for internal use only
3419 void LyXText::UnFreezeUndo()
3423 // this is dangerous and for internal use only
3424 undo_frozen = false;
3428 void LyXText::SetUndo(Buffer * buf, Undo::undo_kind kind,
3429 LyXParagraph const * before,
3430 LyXParagraph const * behind) const
3435 buf->undostack.push(CreateUndo(buf, kind, before, behind));
3436 buf->redostack.clear();
3440 void LyXText::SetRedo(Buffer * buf, Undo::undo_kind kind,
3441 LyXParagraph const * before, LyXParagraph const * behind)
3445 buf->redostack.push(CreateUndo(buf, kind, before, behind));
3449 Undo * LyXText::CreateUndo(Buffer * buf, Undo::undo_kind kind,
3450 LyXParagraph const * before,
3451 LyXParagraph const * behind) const
3456 int before_number = -1;
3457 int behind_number = -1;
3459 before_number = before->id();
3461 behind_number = behind->id();
3462 // Undo::EDIT and Undo::FINISH are
3463 // always finished. (no overlapping there)
3464 // overlapping only with insert and delete inside one paragraph:
3465 // Nobody wants all removed character
3466 // appear one by one when undoing.
3467 // EDIT is special since only layout information, not the
3468 // contents of a paragaph are stored.
3469 if (!undo_finished && (kind != Undo::EDIT) && (kind != Undo::FINISH)){
3470 // check wether storing is needed
3471 if (!buf->undostack.empty() &&
3472 buf->undostack.top()->kind == kind &&
3473 buf->undostack.top()->number_of_before_par == before_number &&
3474 buf->undostack.top()->number_of_behind_par == behind_number ){
3479 // create a new Undo
3480 LyXParagraph * undopar;
3481 LyXParagraph * tmppar;
3482 LyXParagraph * tmppar2;
3484 LyXParagraph * start = 0;
3485 LyXParagraph * end = 0;
3488 start = before->next;
3490 start = FirstParagraph();
3492 end = behind->previous;
3494 end = FirstParagraph();
3500 && start != end->next
3501 && (before != behind || (!before && !behind))) {
3503 tmppar2 = tmppar->Clone();
3504 tmppar2->id(tmppar->id());
3506 // a memory optimization: Just store the layout information
3508 if (kind == Undo::EDIT){
3509 //tmppar2->text.clear();
3510 tmppar2->clearContents();
3515 while (tmppar != end && tmppar->next) {
3516 tmppar = tmppar->next;
3517 tmppar2->next = tmppar->Clone();
3518 tmppar2->next->id(tmppar->id());
3519 // a memory optimization: Just store the layout
3520 // information when only edit
3521 if (kind == Undo::EDIT){
3522 //tmppar2->next->text.clear();
3523 tmppar2->clearContents();
3525 tmppar2->next->previous = tmppar2;
3526 tmppar2 = tmppar2->next;
3530 undopar = 0; // nothing to replace (undo of delete maybe)
3533 int cursor_par = cursor.par()->ParFromPos(cursor.pos())->id();
3534 int cursor_pos = cursor.par()->PositionInParFromPos(cursor.pos());
3536 int cursor_par = cursor.par()->id();
3537 int cursor_pos = cursor.pos();
3540 Undo * undo = new Undo(kind,
3541 before_number, behind_number,
3542 cursor_par, cursor_pos,
3545 undo_finished = false;
3550 void LyXText::SetCursorParUndo(Buffer * buf)
3554 SetUndo(buf, Undo::FINISH,
3556 cursor.par()->ParFromPos(cursor.pos())->previous,
3557 cursor.par()->ParFromPos(cursor.pos())->next
3559 cursor.par()->previous,
3566 void LyXText::toggleAppendix(BufferView * bview)
3569 LyXParagraph * par = cursor.par()->FirstPhysicalPar();
3571 LyXParagraph * par = cursor.par();
3573 bool start = !par->start_of_appendix;
3575 // ensure that we have only one start_of_appendix in this document
3576 LyXParagraph * tmp = FirstParagraph();
3577 for (; tmp; tmp = tmp->next)
3578 tmp->start_of_appendix = 0;
3579 par->start_of_appendix = start;
3581 // we can set the refreshing parameters now
3582 status = LyXText::NEED_MORE_REFRESH;
3584 refresh_row = 0; // not needed for full update
3585 UpdateCounters(bview, 0);
3586 SetCursor(bview, cursor.par(), cursor.pos());
3590 LyXParagraph * LyXText::OwnerParagraph() const
3593 return inset_owner->par;
3595 return bv_owner->buffer()->paragraph;
3599 LyXParagraph * LyXText::OwnerParagraph(LyXParagraph * p) const
3602 inset_owner->par = p;
3604 bv_owner->buffer()->paragraph = p;