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"
54 LyXText::LyXText(BufferView * bv)
62 LyXText::LyXText(InsetText * inset)
72 the_locking_inset = 0;
80 status = LyXText::UNCHANGED;
81 // set cursor at the very top position
82 selection = true; /* these setting is necessary
83 because of the delete-empty-
84 paragraph mechanism in
87 LyXParagraph * par = OwnerParagraph();
88 current_font = GetFont(bv_owner->buffer(), par, 0);
90 InsertParagraph(bv_owner, par, lastrow);
93 SetCursor(bv_owner, firstrow->par(), 0);
95 current_font = LyXFont(LyXFont::ALL_SANE);
101 // no rebreak necessary
104 undo_finished = true;
107 // Default layouttype for copy environment type
111 // Dump all rowinformation:
112 Row * tmprow = firstrow;
113 lyxerr << "Baseline Paragraph Pos Height Ascent Fill\n";
115 lyxerr << tmprow->baseline() << '\t'
116 << tmprow->par << '\t'
117 << tmprow->pos() << '\t'
118 << tmprow->height << '\t'
119 << tmprow->ascent_of_text << '\t'
120 << tmprow->fill << '\n';
121 tmprow = tmprow->next();
128 void LyXText::init(BufferView * bview)
133 LyXParagraph * par = OwnerParagraph();
134 current_font = GetFont(bview->buffer(), par, 0);
136 InsertParagraph(bview, par, lastrow);
139 SetCursorIntern(bview, firstrow->par(), 0);
142 // Dump all rowinformation:
143 Row * tmprow = firstrow;
144 lyxerr << "Width = " << width << endl;
145 lyxerr << "Baseline Paragraph Pos Height Ascent Fill\n";
147 lyxerr << tmprow->baseline() << '\t'
148 << tmprow->par() << '\t'
149 << tmprow->pos() << '\t'
150 << tmprow->height() << '\t'
151 << tmprow->ascent_of_text() << '\t'
152 << tmprow->fill() << '\n';
153 tmprow = tmprow->next();
161 // Delete all rows, this does not touch the paragraphs!
162 Row * tmprow = firstrow;
164 tmprow = firstrow->next();
171 // Gets the fully instantiated font at a given position in a paragraph
172 // Basically the same routine as LyXParagraph::getFont() in paragraph.C.
173 // The difference is that this one is used for displaying, and thus we
174 // are allowed to make cosmetic improvements. For instance make footnotes
176 // If position is -1, we get the layout font of the paragraph.
177 // If position is -2, we get the font of the manual label of the paragraph.
178 LyXFont const LyXText::GetFont(Buffer const * buf, LyXParagraph * par,
179 LyXParagraph::size_type pos) const
181 LyXLayout const & layout =
182 textclasslist.Style(buf->params.textclass, par->GetLayout());
184 char par_depth = par->GetDepth();
185 // We specialize the 95% common case:
188 par->footnoteflag == LyXParagraph::NO_FOOTNOTE &&
193 if (layout.labeltype == LABEL_MANUAL
194 && pos < BeginningOfMainBody(buf, par)) {
196 LyXFont f = par->GetFontSettings(buf->params,
198 return f.realize(layout.reslabelfont);
200 LyXFont f = par->GetFontSettings(buf->params, pos);
201 return f.realize(layout.resfont);
206 // process layoutfont for pos == -1 and labelfont for pos < -1
208 return layout.resfont;
210 return layout.reslabelfont;
214 // The uncommon case need not be optimized as much
216 LyXFont layoutfont, tmpfont;
220 if (pos < BeginningOfMainBody(buf, par)) {
222 layoutfont = layout.labelfont;
225 layoutfont = layout.font;
227 tmpfont = par->GetFontSettings(buf->params, pos);
228 tmpfont.realize(layoutfont);
231 // process layoutfont for pos == -1 and labelfont for pos < -1
233 tmpfont = layout.font;
235 tmpfont = layout.labelfont;
238 // Resolve against environment font information
239 while (par && par_depth && !tmpfont.resolved()) {
240 par = par->DepthHook(par_depth - 1);
242 tmpfont.realize(textclasslist.
243 Style(buf->params.textclass,
244 par->GetLayout()).font);
245 par_depth = par->GetDepth();
249 tmpfont.realize(textclasslist.TextClass(buf->params.textclass).defaultfont());
252 // Cosmetic improvement: If this is an open footnote, make the font
254 if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
255 && par->footnotekind == LyXParagraph::FOOTNOTE) {
263 void LyXText::SetCharFont(Buffer const * buf, LyXParagraph * par,
264 LyXParagraph::size_type pos,
268 // Let the insets convert their font
269 if (par->GetChar(pos) == LyXParagraph::META_INSET) {
270 if (par->GetInset(pos))
271 font = par->GetInset(pos)->ConvertFont(font);
274 LyXLayout const & layout =
275 textclasslist.Style(buf->params.textclass,
278 // Get concrete layout font to reduce against
281 if (pos < BeginningOfMainBody(buf, par))
282 layoutfont = layout.labelfont;
284 layoutfont = layout.font;
286 // Realize against environment font information
287 if (par->GetDepth()){
288 LyXParagraph * tp = par;
289 while (!layoutfont.resolved() && tp && tp->GetDepth()) {
290 tp = tp->DepthHook(tp->GetDepth()-1);
292 layoutfont.realize(textclasslist.
293 Style(buf->params.textclass,
294 tp->GetLayout()).font);
298 layoutfont.realize(textclasslist.TextClass(buf->params.textclass).defaultfont());
301 if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
302 && par->footnotekind == LyXParagraph::FOOTNOTE) {
303 layoutfont.decSize();
306 // Now, reduce font against full layout font
307 font.reduce(layoutfont);
309 par->SetFont(pos, font);
313 /* inserts a new row behind the specified row, increments
314 * the touched counters */
315 void LyXText::InsertRow(Row * row, LyXParagraph * par,
316 LyXParagraph::size_type pos) const
318 Row * tmprow = new Row;
321 tmprow->next(firstrow);
324 tmprow->previous(row);
325 tmprow->next(row->next());
330 tmprow->next()->previous(tmprow);
332 if (tmprow->previous())
333 tmprow->previous()->next(tmprow);
341 ++number_of_rows; // one more row
345 // removes the row and reset the touched counters
346 void LyXText::RemoveRow(Row * row) const
348 /* this must not happen before the currentrow for clear reasons.
349 so the trick is just to set the current row onto the previous
352 GetRow(row->par(), row->pos(), unused_y);
355 row->next()->previous(row->previous());
356 if (!row->previous()) {
357 firstrow = row->next();
359 row->previous()->next(row->next());
362 lastrow = row->previous();
364 height -= row->height(); // the text becomes smaller
367 --number_of_rows; // one row less
371 // remove all following rows of the paragraph of the specified row.
372 void LyXText::RemoveParagraph(Row * row) const
374 LyXParagraph * tmppar = row->par();
378 while (row && row->par() == tmppar) {
379 tmprow = row->next();
386 // insert the specified paragraph behind the specified row
387 void LyXText::InsertParagraph(BufferView * bview, LyXParagraph * par,
390 InsertRow(row, par, 0); /* insert a new row, starting
393 SetCounter(bview->buffer(), par); // set the counters
395 // and now append the whole paragraph behind the new row
398 AppendParagraph(bview, firstrow);
400 row->next()->height(0);
401 AppendParagraph(bview, row->next());
407 void LyXText::ToggleFootnote(BufferView * bview)
409 LyXParagraph * par = cursor.par()->ParFromPos(cursor.pos());
411 && par->next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
413 bview->owner()->getMiniBuffer()->Set(_("Opened float"));
415 bview->owner()->getMiniBuffer()->Set(_("Closed float"));
416 CloseFootnote(bview);
423 void LyXText::OpenStuff(BufferView * bview)
425 if (cursor.pos() == 0 && cursor.par()->bibkey){
426 cursor.par()->bibkey->Edit(bview, 0, 0, 0);
427 } else if (cursor.pos() < cursor.par()->Last()
428 && cursor.par()->GetChar(cursor.pos()) == LyXParagraph::META_INSET
429 && cursor.par()->GetInset(cursor.pos())->Editable()) {
430 bview->owner()->getMiniBuffer()
431 ->Set(cursor.par()->GetInset(cursor.pos())->EditMessage());
432 if (cursor.par()->GetInset(cursor.pos())->Editable() != Inset::HIGHLY_EDITABLE)
433 SetCursorParUndo(bview->buffer());
434 cursor.par()->GetInset(cursor.pos())->Edit(bview, 0, 0, 0);
438 ToggleFootnote(bview);
446 void LyXText::CloseFootnote(BufferView * bview)
448 LyXParagraph * tmppar;
449 LyXParagraph * par = cursor.par()->ParFromPos(cursor.pos());
451 // if the cursor is not in an open footnote, or
452 // there is no open footnote in this paragraph, just return.
453 if (cursor.par()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE) {
456 par->next->footnoteflag != LyXParagraph::OPEN_FOOTNOTE) {
457 bview->owner()->getMiniBuffer()
458 ->Set(_("Nothing to do"));
462 // ok, move the cursor right before the footnote
463 // just a little faster than using CursorRight()
465 cursor.par()->ParFromPos(cursor.pos()) != par;) {
466 cursor.pos(cursor.pos() + 1);
469 // now the cursor is at the beginning of the physical par
470 SetCursor(bview, cursor.par(),
472 cursor.par()->ParFromPos(cursor.pos())->size());
474 /* we are in a footnote, so let us move at the beginning */
475 /* this is just faster than using just CursorLeft() */
477 tmppar = cursor.par();
478 while (tmppar->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
479 // just a little bit faster than movin the cursor
480 tmppar = tmppar->Previous();
482 SetCursor(bview, tmppar, tmppar->Last());
485 // the cursor must be exactly before the footnote
486 par = cursor.par()->ParFromPos(cursor.pos());
488 status = LyXText::NEED_MORE_REFRESH;
489 refresh_row = cursor.row();
490 refresh_y = cursor.y() - cursor.row()->baseline();
492 tmppar = cursor.par();
493 LyXParagraph * endpar = par->NextAfterFootnote()->Next();
494 Row * row = cursor.row();
496 tmppar->CloseFootnote(cursor.pos());
498 while (tmppar != endpar) {
499 RemoveRow(row->next());
501 tmppar = row->next()->par();
506 AppendParagraph(bview, cursor.row());
508 SetCursor(bview, cursor.par(), cursor.pos());
512 if (cursor.row()->next())
513 SetHeightOfRow(bview, cursor.row()->next());
518 /* used in setlayout */
519 // Asger is not sure we want to do this...
520 void LyXText::MakeFontEntriesLayoutSpecific(Buffer const * buf,
524 LyXLayout const & layout =
525 textclasslist.Style(buf->params.textclass, par->GetLayout());
527 LyXFont layoutfont, tmpfont;
528 for (LyXParagraph::size_type pos = 0;
529 pos < par->Last(); ++pos) {
530 if (pos < BeginningOfMainBody(buf, par))
531 layoutfont = layout.labelfont;
533 layoutfont = layout.font;
535 tmpfont = par->GetFontSettings(buf->params, pos);
536 tmpfont.reduce(layoutfont);
537 par->SetFont(pos, tmpfont);
542 LyXParagraph * LyXText::SetLayout(BufferView * bview,
543 LyXCursor & cur, LyXCursor & sstart_cur,
544 LyXCursor & send_cur,
545 LyXTextClass::size_type layout)
548 LyXParagraph * endpar = send_cur.par()->LastPhysicalPar()->Next();
550 LyXParagraph * endpar = send_cur.par()->Next();
552 LyXParagraph * undoendpar = endpar;
554 if (endpar && endpar->GetDepth()) {
555 while (endpar && endpar->GetDepth()) {
557 endpar = endpar->LastPhysicalPar()->Next();
559 endpar = endpar->Next();
564 endpar = endpar->Next(); // because of parindents etc.
567 SetUndo(bview->buffer(), Undo::EDIT,
569 sstart_cur.par()->ParFromPos(sstart_cur.pos())->previous,
571 sstart_cur.par()->previous,
575 /* ok we have a selection. This is always between sstart_cur
576 * and sel_end cursor */
579 LyXLayout const & lyxlayout =
580 textclasslist.Style(bview->buffer()->params.textclass, layout);
582 while (cur.par() != send_cur.par()) {
584 if (cur.par()->footnoteflag == sstart_cur.par()->footnoteflag) {
586 cur.par()->SetLayout(bview->buffer()->params, layout);
587 MakeFontEntriesLayoutSpecific(bview->buffer(), cur.par());
589 LyXParagraph * fppar = cur.par()->FirstPhysicalPar();
591 LyXParagraph * fppar = cur.par();
593 fppar->added_space_top = lyxlayout.fill_top ?
594 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
595 fppar->added_space_bottom = lyxlayout.fill_bottom ?
596 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
597 if (lyxlayout.margintype == MARGIN_MANUAL)
598 cur.par()->SetLabelWidthString(lyxlayout.labelstring());
599 if (lyxlayout.labeltype != LABEL_BIBLIO
601 delete fppar->bibkey;
607 cur.par(cur.par()->Next());
610 if (cur.par()->footnoteflag == sstart_cur.par()->footnoteflag) {
612 cur.par()->SetLayout(bview->buffer()->params, layout);
613 MakeFontEntriesLayoutSpecific(bview->buffer(), cur.par());
615 LyXParagraph * fppar = cur.par()->FirstPhysicalPar();
617 LyXParagraph * fppar = cur.par();
619 fppar->added_space_top = lyxlayout.fill_top ?
620 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
621 fppar->added_space_bottom = lyxlayout.fill_bottom ?
622 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE);
623 if (lyxlayout.margintype == MARGIN_MANUAL)
624 cur.par()->SetLabelWidthString(lyxlayout.labelstring());
625 if (lyxlayout.labeltype != LABEL_BIBLIO
627 delete fppar->bibkey;
636 // set layout over selection and make a total rebreak of those paragraphs
637 void LyXText::SetLayout(BufferView * bview, LyXTextClass::size_type layout)
639 LyXCursor tmpcursor = cursor; /* store the current cursor */
641 // if there is no selection just set the layout
642 // of the current paragraph */
644 sel_start_cursor = cursor; // dummy selection
645 sel_end_cursor = cursor;
648 endpar = SetLayout(bview, cursor, sel_start_cursor,
649 sel_end_cursor, layout);
650 RedoParagraphs(bview, sel_start_cursor, endpar);
652 // we have to reset the selection, because the
653 // geometry could have changed
654 SetCursor(bview, sel_start_cursor.par(),
655 sel_start_cursor.pos(), false);
657 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos(),
659 UpdateCounters(bview, cursor.row());
662 SetCursor(bview, tmpcursor.par(), tmpcursor.pos(), true);
666 // increment depth over selection and
667 // make a total rebreak of those paragraphs
668 void LyXText::IncDepth(BufferView * bview)
670 // If there is no selection, just use the current paragraph
672 sel_start_cursor = cursor; // dummy selection
673 sel_end_cursor = cursor;
676 // We end at the next paragraph with depth 0
677 LyXParagraph * endpar =
679 sel_end_cursor.par()->LastPhysicalPar()->Next();
681 sel_end_cursor.par()->Next();
683 LyXParagraph * undoendpar = endpar;
685 if (endpar && endpar->GetDepth()) {
686 while (endpar && endpar->GetDepth()) {
688 endpar = endpar->LastPhysicalPar()->Next();
690 endpar = endpar->Next();
696 endpar = endpar->Next(); // because of parindents etc.
699 SetUndo(bview->buffer(), Undo::EDIT,
702 .par()->ParFromPos(sel_start_cursor.pos())->previous,
704 sel_start_cursor.par()->previous,
708 LyXCursor tmpcursor = cursor; // store the current cursor
710 // ok we have a selection. This is always between sel_start_cursor
711 // and sel_end cursor
712 cursor = sel_start_cursor;
714 bool anything_changed = false;
717 // NOTE: you can't change the depth of a bibliography entry
720 cursor.par()->footnoteflag ==
721 sel_start_cursor.par()->footnoteflag &&
723 textclasslist.Style(bview->buffer()->params.textclass,
724 cursor.par()->GetLayout()
725 ).labeltype != LABEL_BIBLIO) {
726 LyXParagraph * prev =
728 cursor.par()->FirstPhysicalPar()->Previous();
730 cursor.par()->Previous();
733 && (prev->GetDepth() - cursor.par()->GetDepth() > 0
734 || (prev->GetDepth() == cursor.par()->GetDepth()
735 && textclasslist.Style(bview->buffer()->params.textclass,
736 prev->GetLayout()).isEnvironment()))) {
738 cursor.par()->FirstPhysicalPar()->depth++;
740 cursor.par()->depth++;
742 anything_changed = true;
745 if (cursor.par() == sel_end_cursor.par())
747 cursor.par(cursor.par()->Next());
750 // if nothing changed set all depth to 0
751 if (!anything_changed) {
752 cursor = sel_start_cursor;
753 while (cursor.par() != sel_end_cursor.par()) {
755 cursor.par()->FirstPhysicalPar()->depth = 0;
757 cursor.par()->depth = 0;
759 cursor.par(cursor.par()->Next());
762 if (cursor.par()->footnoteflag == sel_start_cursor.par()->footnoteflag)
763 cursor.par()->FirstPhysicalPar()->depth = 0;
765 cursor.par()->depth = 0;
769 RedoParagraphs(bview, sel_start_cursor, endpar);
771 // we have to reset the selection, because the
772 // geometry could have changed
773 SetCursor(bview, sel_start_cursor.par(),
774 sel_start_cursor.pos());
776 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
777 UpdateCounters(bview, cursor.row());
780 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
784 // decrement depth over selection and
785 // make a total rebreak of those paragraphs
786 void LyXText::DecDepth(BufferView * bview)
788 // if there is no selection just set the layout
789 // of the current paragraph
791 sel_start_cursor = cursor; // dummy selection
792 sel_end_cursor = cursor;
795 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
797 LyXParagraph * endpar = sel_end_cursor.par()->Next();
799 LyXParagraph * undoendpar = endpar;
801 if (endpar && endpar->GetDepth()) {
802 while (endpar && endpar->GetDepth()) {
804 endpar = endpar->LastPhysicalPar()->Next();
806 endpar = endpar->Next();
812 endpar = endpar->Next(); // because of parindents etc.
815 SetUndo(bview->buffer(), Undo::EDIT,
818 .par()->ParFromPos(sel_start_cursor.pos())->previous,
820 sel_start_cursor.par()->previous,
824 LyXCursor tmpcursor = cursor; // store the current cursor
826 // ok we have a selection. This is always between sel_start_cursor
827 // and sel_end cursor
828 cursor = sel_start_cursor;
832 if (cursor.par()->footnoteflag ==
833 sel_start_cursor.par()->footnoteflag) {
834 if (cursor.par()->FirstPhysicalPar()->depth)
835 cursor.par()->FirstPhysicalPar()->depth--;
838 if (cursor.par()->depth)
839 cursor.par()->depth--;
841 if (cursor.par() == sel_end_cursor.par())
843 cursor.par(cursor.par()->Next());
846 RedoParagraphs(bview, sel_start_cursor, endpar);
848 // we have to reset the selection, because the
849 // geometry could have changed
850 SetCursor(bview, sel_start_cursor.par(),
851 sel_start_cursor.pos());
853 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
854 UpdateCounters(bview, cursor.row());
857 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
861 // set font over selection and make a total rebreak of those paragraphs
862 void LyXText::SetFont(BufferView * bview, LyXFont const & font, bool toggleall)
864 // if there is no selection just set the current_font
866 // Determine basis font
868 if (cursor.pos() < BeginningOfMainBody(bview->buffer(),
870 layoutfont = GetFont(bview->buffer(), cursor.par(),-2);
872 layoutfont = GetFont(bview->buffer(), cursor.par(),-1);
873 // Update current font
874 real_current_font.update(font,
875 bview->buffer()->params.language,
878 // Reduce to implicit settings
879 current_font = real_current_font;
880 current_font.reduce(layoutfont);
881 // And resolve it completely
882 real_current_font.realize(layoutfont);
886 LyXCursor tmpcursor = cursor; // store the current cursor
888 // ok we have a selection. This is always between sel_start_cursor
889 // and sel_end cursor
891 SetUndo(bview->buffer(), Undo::EDIT,
893 sel_start_cursor.par()->ParFromPos(sel_start_cursor.pos())->previous,
894 sel_end_cursor.par()->ParFromPos(sel_end_cursor.pos())->next
896 sel_start_cursor.par()->previous,
897 sel_end_cursor.par()->next
900 cursor = sel_start_cursor;
901 while (cursor.par() != sel_end_cursor.par() ||
904 cursor.par()->footnoteflag == sel_start_cursor.par()->footnoteflag &&
906 cursor.pos() < sel_end_cursor.pos()))
908 if (cursor.pos() < cursor.par()->Last()
910 && cursor.par()->footnoteflag
911 == sel_start_cursor.par()->footnoteflag
914 // an open footnote should behave
916 LyXFont newfont = GetFont(bview->buffer(),
917 cursor.par(), cursor.pos());
919 bview->buffer()->params.language,
921 SetCharFont(bview->buffer(),
922 cursor.par(), cursor.pos(), newfont);
923 cursor.pos(cursor.pos() + 1);
926 cursor.par(cursor.par()->Next());
930 RedoParagraphs(bview, sel_start_cursor, sel_end_cursor.par()->Next());
932 // we have to reset the selection, because the
933 // geometry could have changed
934 SetCursor(bview, sel_start_cursor.par(), sel_start_cursor.pos());
936 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
939 SetCursor(bview, tmpcursor.par(), tmpcursor.pos(), true,
940 tmpcursor.boundary());
944 void LyXText::RedoHeightOfParagraph(BufferView * bview, LyXCursor const & cur)
946 Row * tmprow = cur.row();
947 int y = cur.y() - tmprow->baseline();
949 SetHeightOfRow(bview, tmprow);
951 LyXParagraph * first_phys_par = tmprow->par()->FirstPhysicalPar();
953 LyXParagraph * first_phys_par = tmprow->par();
955 // find the first row of the paragraph
956 if (first_phys_par != tmprow->par())
957 while (tmprow->previous()
958 && tmprow->previous()->par() != first_phys_par) {
959 tmprow = tmprow->previous();
960 y -= tmprow->height();
961 SetHeightOfRow(bview, tmprow);
963 while (tmprow->previous() && tmprow->previous()->par() == first_phys_par) {
964 tmprow = tmprow->previous();
965 y -= tmprow->height();
966 SetHeightOfRow(bview, tmprow);
969 // we can set the refreshing parameters now
970 status = LyXText::NEED_MORE_REFRESH;
972 refresh_row = tmprow;
973 SetCursor(bview, cur.par(), cur.pos(), false, cursor.boundary());
977 void LyXText::RedoDrawingOfParagraph(BufferView * bview, LyXCursor const & cur)
979 Row * tmprow = cur.row();
981 int y = cur.y() - tmprow->baseline();
982 SetHeightOfRow(bview, tmprow);
984 LyXParagraph * first_phys_par = tmprow->par()->FirstPhysicalPar();
986 LyXParagraph * first_phys_par = tmprow->par();
988 // find the first row of the paragraph
989 if (first_phys_par != tmprow->par())
990 while (tmprow->previous() && tmprow->previous()->par() != first_phys_par) {
991 tmprow = tmprow->previous();
992 y -= tmprow->height();
994 while (tmprow->previous() && tmprow->previous()->par() == first_phys_par) {
995 tmprow = tmprow->previous();
996 y -= tmprow->height();
999 // we can set the refreshing parameters now
1000 if (status == LyXText::UNCHANGED || y < refresh_y) {
1002 refresh_row = tmprow;
1004 status = LyXText::NEED_MORE_REFRESH;
1005 SetCursor(bview, cur.par(), cur.pos());
1009 /* deletes and inserts again all paragaphs between the cursor
1010 * and the specified par
1011 * This function is needed after SetLayout and SetFont etc. */
1012 void LyXText::RedoParagraphs(BufferView * bview, LyXCursor const & cur,
1013 LyXParagraph const * endpar) const
1016 LyXParagraph * tmppar = 0, * first_phys_par = 0;
1018 Row * tmprow = cur.row();
1020 int y = cur.y() - tmprow->baseline();
1022 if (!tmprow->previous()){
1023 first_phys_par = FirstParagraph(); // a trick/hack for UNDO
1026 first_phys_par = tmprow->par()->FirstPhysicalPar();
1028 first_phys_par = tmprow->par();
1030 // find the first row of the paragraph
1031 if (first_phys_par != tmprow->par())
1032 while (tmprow->previous() &&
1033 (tmprow->previous()->par() != first_phys_par)) {
1034 tmprow = tmprow->previous();
1035 y -= tmprow->height();
1037 while (tmprow->previous()
1038 && tmprow->previous()->par() == first_phys_par) {
1039 tmprow = tmprow->previous();
1040 y -= tmprow->height();
1044 // we can set the refreshing parameters now
1045 status = LyXText::NEED_MORE_REFRESH;
1047 refresh_row = tmprow->previous(); /* the real refresh row will
1048 be deleted, so I store
1049 the previous here */
1052 tmppar = tmprow->next()->par();
1055 while (tmppar != endpar) {
1056 RemoveRow(tmprow->next());
1058 tmppar = tmprow->next()->par();
1063 // remove the first one
1064 tmprow2 = tmprow; /* this is because tmprow->previous()
1066 tmprow = tmprow->previous();
1069 tmppar = first_phys_par;
1073 InsertParagraph(bview, tmppar, tmprow);
1076 while (tmprow->next() && tmprow->next()->par() == tmppar)
1077 tmprow = tmprow->next();
1078 tmppar = tmppar->Next();
1080 } while (tmppar != endpar);
1082 // this is because of layout changes
1084 refresh_y -= refresh_row->height();
1085 SetHeightOfRow(bview, refresh_row);
1087 refresh_row = firstrow;
1089 SetHeightOfRow(bview, refresh_row);
1092 if (tmprow && tmprow->next())
1093 SetHeightOfRow(bview, tmprow->next());
1097 bool LyXText::FullRebreak(BufferView * bview)
1103 if (need_break_row) {
1104 BreakAgain(bview, need_break_row);
1112 /* important for the screen */
1115 /* the cursor set functions have a special mechanism. When they
1116 * realize, that you left an empty paragraph, they will delete it.
1117 * They also delete the corresponding row */
1119 // need the selection cursor:
1120 void LyXText::SetSelection()
1123 last_sel_cursor = sel_cursor;
1124 sel_start_cursor = sel_cursor;
1125 sel_end_cursor = sel_cursor;
1130 // first the toggling area
1131 if (cursor.y() < last_sel_cursor.y()
1132 || (cursor.y() == last_sel_cursor.y()
1133 && cursor.x() < last_sel_cursor.x())) {
1134 toggle_end_cursor = last_sel_cursor;
1135 toggle_cursor = cursor;
1137 toggle_end_cursor = cursor;
1138 toggle_cursor = last_sel_cursor;
1141 last_sel_cursor = cursor;
1143 // and now the whole selection
1145 if (sel_cursor.par() == cursor.par())
1146 if (sel_cursor.pos() < cursor.pos()) {
1147 sel_end_cursor = cursor;
1148 sel_start_cursor = sel_cursor;
1150 sel_end_cursor = sel_cursor;
1151 sel_start_cursor = cursor;
1153 else if (sel_cursor.y() < cursor.y() ||
1154 (sel_cursor.y() == cursor.y() && sel_cursor.x() < cursor.x())) {
1155 sel_end_cursor = cursor;
1156 sel_start_cursor = sel_cursor;
1159 sel_end_cursor = sel_cursor;
1160 sel_start_cursor = cursor;
1163 // a selection with no contents is not a selection
1164 if (sel_start_cursor.par() == sel_end_cursor.par() &&
1165 sel_start_cursor.pos() == sel_end_cursor.pos())
1170 string const LyXText::selectionAsString(Buffer const * buffer) const
1172 if (!selection) return string();
1175 // Special handling if the whole selection is within one paragraph
1176 if (sel_start_cursor.par() == sel_end_cursor.par()) {
1177 result += sel_start_cursor.par()->String(buffer,
1178 sel_start_cursor.pos(),
1179 sel_end_cursor.pos());
1183 // The selection spans more than one paragraph
1185 // First paragraph in selection
1186 result += sel_start_cursor.par()->String(buffer,
1187 sel_start_cursor.pos(),
1188 sel_start_cursor.par()->Last())
1191 // The paragraphs in between (if any)
1192 LyXCursor tmpcur(sel_start_cursor);
1193 tmpcur.par(tmpcur.par()->Next());
1194 while (tmpcur.par() != sel_end_cursor.par()) {
1195 result += tmpcur.par()->String(buffer, 0, tmpcur.par()->Last()) + "\n\n";
1196 tmpcur.par(tmpcur.par()->Next()); // Or NextAfterFootnote??
1199 // Last paragraph in selection
1200 result += sel_end_cursor.par()->String(buffer, 0, sel_end_cursor.pos());
1206 void LyXText::ClearSelection() const
1209 status = LyXText::NEED_MORE_REFRESH;
1215 void LyXText::CursorHome(BufferView * bview) const
1217 SetCursor(bview, cursor.par(), cursor.row()->pos());
1221 void LyXText::CursorEnd(BufferView * bview) const
1223 if (!cursor.row()->next() || cursor.row()->next()->par() != cursor.row()->par())
1224 SetCursor(bview, cursor.par(), RowLast(cursor.row()) + 1);
1226 if (cursor.par()->Last() &&
1227 (cursor.par()->GetChar(RowLast(cursor.row())) == ' '
1228 || cursor.par()->IsNewline(RowLast(cursor.row()))))
1229 SetCursor(bview, cursor.par(), RowLast(cursor.row()));
1231 SetCursor(bview,cursor.par(), RowLast(cursor.row()) + 1);
1236 void LyXText::CursorTop(BufferView * bview) const
1238 while (cursor.par()->Previous())
1239 cursor.par(cursor.par()->Previous());
1240 SetCursor(bview, cursor.par(), 0);
1244 void LyXText::CursorBottom(BufferView * bview) const
1246 while (cursor.par()->Next())
1247 cursor.par(cursor.par()->Next());
1248 SetCursor(bview, cursor.par(), cursor.par()->Last());
1252 /* returns a pointer to the row near the specified y-coordinate
1253 * (relative to the whole text). y is set to the real beginning
1255 Row * LyXText::GetRowNearY(int & y) const
1257 Row * tmprow = firstrow;
1260 while (tmprow->next() && tmpy + tmprow->height() <= y) {
1261 tmpy += tmprow->height();
1262 tmprow = tmprow->next();
1265 y = tmpy; // return the real y
1270 void LyXText::ToggleFree(BufferView * bview,
1271 LyXFont const & font, bool toggleall)
1273 // If the mask is completely neutral, tell user
1274 if (font == LyXFont(LyXFont::ALL_IGNORE)) {
1275 // Could only happen with user style
1276 bview->owner()->getMiniBuffer()
1277 ->Set(_("No font change defined. Use Character under"
1278 " the Layout menu to define font change."));
1282 // Try implicit word selection
1283 // If there is a change in the language the implicit word selection
1285 LyXCursor resetCursor = cursor;
1286 bool implicitSelection = (font.language() == ignore_language
1287 && font.number() == LyXFont::IGNORE)
1288 ? SelectWordWhenUnderCursor(bview) : false;
1291 SetFont(bview, font, toggleall);
1293 /* Implicit selections are cleared afterwards and cursor is set to the
1294 original position. */
1295 if (implicitSelection) {
1297 cursor = resetCursor;
1298 SetCursor(bview, cursor.par(), cursor.pos());
1299 sel_cursor = cursor;
1304 LyXParagraph::size_type
1305 LyXText::BeginningOfMainBody(Buffer const * buf,
1306 LyXParagraph const * par) const
1308 if (textclasslist.Style(buf->params.textclass,
1309 par->GetLayout()).labeltype != LABEL_MANUAL)
1312 return par->BeginningOfMainBody();
1317 /* if there is a selection, reset every environment you can find
1318 * in the selection, otherwise just the environment you are in */
1319 void LyXText::MeltFootnoteEnvironment(BufferView * bview)
1321 LyXParagraph * tmppar, * firsttmppar;
1325 /* is is only allowed, if the cursor is IN an open footnote.
1326 * Otherwise it is too dangerous */
1327 if (cursor.par()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE)
1330 SetUndo(bview->buffer(), Undo::FINISH,
1331 cursor.par()->PreviousBeforeFootnote()->previous,
1332 cursor.par()->NextAfterFootnote()->next);
1334 /* ok, move to the beginning of the footnote. */
1335 while (cursor.par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
1336 cursor.par(cursor.par()->Previous());
1338 SetCursor(bview, cursor.par(), cursor.par()->Last());
1339 /* this is just faster than using CursorLeft(); */
1341 firsttmppar = cursor.par()->ParFromPos(cursor.pos());
1342 tmppar = firsttmppar;
1343 /* tmppar is now the paragraph right before the footnote */
1345 bool first_footnote_par_is_not_empty = tmppar->next->size();
1348 && tmppar->next->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1349 tmppar = tmppar->next; /* I use next instead of Next(),
1350 * because there cannot be any
1351 * footnotes in a footnote
1353 tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE;
1355 /* remember the captions and empty paragraphs */
1356 if ((textclasslist.Style(bview->buffer()->params.textclass,
1357 tmppar->GetLayout())
1358 .labeltype == LABEL_SENSITIVE)
1360 tmppar->SetLayout(bview->buffer()->params, 0);
1363 // now we will paste the ex-footnote, if the layouts allow it
1364 // first restore the layout of the paragraph right behind
1367 tmppar->next->MakeSameLayout(cursor.par());
1370 if (!tmppar->GetLayout()
1372 && (!tmppar->Next()->Last()
1373 || tmppar->Next()->HasSameLayout(tmppar)))) {
1374 if (tmppar->Next()->Last()
1375 && tmppar->Next()->IsLineSeparator(0))
1376 tmppar->Next()->Erase(0);
1377 tmppar->PasteParagraph(bview->buffer()->params);
1380 tmppar = tmppar->Next(); /* make sure tmppar cannot be touched
1381 * by the pasting of the beginning */
1383 /* then the beginning */
1384 /* if there is no space between the text and the footnote, so we insert
1386 * (only if the previous par and the footnotepar are not empty!) */
1387 if (!firsttmppar->next->GetLayout()
1388 || firsttmppar->HasSameLayout(firsttmppar->next)) {
1389 if (firsttmppar->size()
1390 && !firsttmppar->IsSeparator(firsttmppar->size() - 1)
1391 && first_footnote_par_is_not_empty) {
1392 firsttmppar->next->InsertChar(0, ' ');
1394 firsttmppar->PasteParagraph(bview->buffer()->params);
1397 /* now redo the paragaphs */
1398 RedoParagraphs(bview, cursor, tmppar);
1400 SetCursor(bview, cursor.par(), cursor.pos());
1402 /* sometimes it can happen, that there is a counter change */
1403 Row * row = cursor.row();
1404 while (row->next() && row->par() != tmppar && row->next()->par() != tmppar)
1406 UpdateCounters(bview, row);
1414 /* the DTP switches for paragraphs. LyX will store them in the
1415 * first physicla paragraph. When a paragraph is broken, the top settings
1416 * rest, the bottom settings are given to the new one. So I can make shure,
1417 * they do not duplicate themself and you cannnot make dirty things with
1420 void LyXText::SetParagraph(BufferView * bview,
1421 bool line_top, bool line_bottom,
1422 bool pagebreak_top, bool pagebreak_bottom,
1423 VSpace const & space_top,
1424 VSpace const & space_bottom,
1426 string labelwidthstring,
1429 LyXCursor tmpcursor = cursor;
1431 sel_start_cursor = cursor;
1432 sel_end_cursor = cursor;
1435 // make sure that the depth behind the selection are restored, too
1437 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
1439 LyXParagraph * endpar = sel_end_cursor.par()->Next();
1441 LyXParagraph * undoendpar = endpar;
1443 if (endpar && endpar->GetDepth()) {
1444 while (endpar && endpar->GetDepth()) {
1446 endpar = endpar->LastPhysicalPar()->Next();
1448 endpar = endpar->Next();
1450 undoendpar = endpar;
1454 endpar = endpar->Next(); // because of parindents etc.
1457 SetUndo(bview->buffer(), Undo::EDIT,
1460 .par()->ParFromPos(sel_start_cursor.pos())->previous,
1462 sel_start_cursor.par()->previous,
1467 LyXParagraph * tmppar = sel_end_cursor.par();
1469 while (tmppar != sel_start_cursor.par()->FirstPhysicalPar()->Previous()) {
1470 SetCursor(bview, tmppar->FirstPhysicalPar(), 0);
1472 while (tmppar != sel_start_cursor.par()->Previous()) {
1473 SetCursor(bview, tmppar, 0);
1475 status = LyXText::NEED_MORE_REFRESH;
1476 refresh_row = cursor.row();
1477 refresh_y = cursor.y() - cursor.row()->baseline();
1479 if (cursor.par()->footnoteflag ==
1480 sel_start_cursor.par()->footnoteflag) {
1482 cursor.par()->line_top = line_top;
1483 cursor.par()->line_bottom = line_bottom;
1484 cursor.par()->pagebreak_top = pagebreak_top;
1485 cursor.par()->pagebreak_bottom = pagebreak_bottom;
1486 cursor.par()->added_space_top = space_top;
1487 cursor.par()->added_space_bottom = space_bottom;
1488 // does the layout allow the new alignment?
1489 if (align == LYX_ALIGN_LAYOUT)
1490 align = textclasslist
1491 .Style(bview->buffer()->params.textclass,
1492 cursor.par()->GetLayout()).align;
1493 if (align & textclasslist
1494 .Style(bview->buffer()->params.textclass,
1495 cursor.par()->GetLayout()).alignpossible) {
1496 if (align == textclasslist
1497 .Style(bview->buffer()->params.textclass,
1498 cursor.par()->GetLayout()).align)
1499 cursor.par()->align = LYX_ALIGN_LAYOUT;
1501 cursor.par()->align = align;
1503 cursor.par()->SetLabelWidthString(labelwidthstring);
1504 cursor.par()->noindent = noindent;
1508 tmppar = cursor.par()->FirstPhysicalPar()->Previous();
1510 tmppar = cursor.par()->Previous();
1514 RedoParagraphs(bview, sel_start_cursor, endpar);
1517 SetCursor(bview, sel_start_cursor.par(), sel_start_cursor.pos());
1518 sel_cursor = cursor;
1519 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
1521 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
1523 bview->updateInset(inset_owner, true);
1527 void LyXText::SetParagraphExtraOpt(BufferView * bview, int type,
1528 string const & width,
1529 string const & widthp,
1530 int alignment, bool hfill,
1531 bool start_minipage)
1533 LyXCursor tmpcursor = cursor;
1534 LyXParagraph * tmppar;
1536 sel_start_cursor = cursor;
1537 sel_end_cursor = cursor;
1540 // make sure that the depth behind the selection are restored, too
1542 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
1544 LyXParagraph * endpar = sel_end_cursor.par()->Next();
1546 LyXParagraph * undoendpar = endpar;
1548 if (endpar && endpar->GetDepth()) {
1549 while (endpar && endpar->GetDepth()) {
1551 endpar = endpar->LastPhysicalPar()->Next();
1553 endpar = endpar->Next();
1555 undoendpar = endpar;
1559 endpar = endpar->Next(); // because of parindents etc.
1562 SetUndo(bview->buffer(), Undo::EDIT,
1565 .par()->ParFromPos(sel_start_cursor.pos())->previous,
1567 sel_start_cursor.par()->previous,
1571 tmppar = sel_end_cursor.par();
1573 while(tmppar != sel_start_cursor.par()->FirstPhysicalPar()->Previous()) {
1574 SetCursor(bview, tmppar->FirstPhysicalPar(), 0);
1576 while(tmppar != sel_start_cursor.par()->Previous()) {
1577 SetCursor(bview, tmppar, 0);
1579 status = LyXText::NEED_MORE_REFRESH;
1580 refresh_row = cursor.row();
1581 refresh_y = cursor.y() - cursor.row()->baseline();
1583 if (cursor.par()->footnoteflag ==
1584 sel_start_cursor.par()->footnoteflag) {
1586 if (type == LyXParagraph::PEXTRA_NONE) {
1587 if (cursor.par()->pextra_type != LyXParagraph::PEXTRA_NONE) {
1588 cursor.par()->UnsetPExtraType(bview->buffer()->params);
1589 cursor.par()->pextra_type = LyXParagraph::PEXTRA_NONE;
1592 cursor.par()->SetPExtraType(bview->buffer()->params,
1593 type, width, widthp);
1594 cursor.par()->pextra_hfill = hfill;
1595 cursor.par()->pextra_start_minipage = start_minipage;
1596 cursor.par()->pextra_alignment = alignment;
1600 tmppar = cursor.par()->FirstPhysicalPar()->Previous();
1602 tmppar = cursor.par()->Previous();
1605 RedoParagraphs(bview, sel_start_cursor, endpar);
1607 SetCursor(bview, sel_start_cursor.par(), sel_start_cursor.pos());
1608 sel_cursor = cursor;
1609 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
1611 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
1615 char loweralphaCounter(int n)
1617 if (n < 1 || n > 26)
1625 char alphaCounter(int n)
1627 if (n < 1 || n > 26)
1635 char hebrewCounter(int n)
1637 static const char hebrew[22] = {
1638 'à ', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è',
1639 'é', 'ë', 'ì', 'î', 'ð', 'ñ', 'ò', 'ô', 'ö',
1640 '÷', 'ø', 'ù', 'ú'
1642 if (n < 1 || n > 22)
1650 string const romanCounter(int n)
1652 static char const * roman[20] = {
1653 "i", "ii", "iii", "iv", "v",
1654 "vi", "vii", "viii", "ix", "x",
1655 "xi", "xii", "xiii", "xiv", "xv",
1656 "xvi", "xvii", "xviii", "xix", "xx"
1658 if (n < 1 || n > 20)
1665 // set the counter of a paragraph. This includes the labels
1666 void LyXText::SetCounter(Buffer const * buf, LyXParagraph * par) const
1669 // this is only relevant for the beginning of paragraph
1670 par = par->FirstPhysicalPar();
1672 LyXLayout const & layout =
1673 textclasslist.Style(buf->params.textclass,
1676 LyXTextClass const & textclass =
1677 textclasslist.TextClass(buf->params.textclass);
1679 /* copy the prev-counters to this one, unless this is the start of a
1680 footnote or of a bibliography or the very first paragraph */
1683 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1684 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1685 && par->footnotekind == LyXParagraph::FOOTNOTE)
1687 && !(textclasslist.Style(buf->params.textclass,
1688 par->Previous()->GetLayout()
1689 ).labeltype != LABEL_BIBLIO
1690 && layout.labeltype == LABEL_BIBLIO)) {
1691 for (int i = 0; i < 10; ++i) {
1692 par->setCounter(i, par->Previous()->GetFirstCounter(i));
1695 par->appendix = par->Previous()->FirstPhysicalPar()->appendix;
1697 par->appendix = par->Previous()->appendix;
1699 if (!par->appendix && par->start_of_appendix){
1700 par->appendix = true;
1701 for (int i = 0; i < 10; ++i) {
1702 par->setCounter(i, 0);
1706 par->enumdepth = par->Previous()->FirstPhysicalPar()->enumdepth;
1707 par->itemdepth = par->Previous()->FirstPhysicalPar()->itemdepth;
1709 par->enumdepth = par->Previous()->enumdepth;
1710 par->itemdepth = par->Previous()->itemdepth;
1713 for (int i = 0; i < 10; ++i) {
1714 par->setCounter(i, 0);
1716 par->appendix = par->start_of_appendix;
1722 // if this is an open marginnote and this is the first
1723 // entry in the marginnote and the enclosing
1724 // environment is an enum/item then correct for the
1725 // LaTeX behaviour (ARRae)
1726 if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1727 && par->footnotekind == LyXParagraph::MARGIN
1729 && par->Previous()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE
1730 && (par->PreviousBeforeFootnote()
1731 && textclasslist.Style(buf->params.textclass,
1732 par->PreviousBeforeFootnote()->GetLayout()
1733 ).labeltype >= LABEL_COUNTER_ENUMI)) {
1734 // Any itemize or enumerate environment in a marginnote
1735 // that is embedded in an itemize or enumerate
1736 // paragraph is seen by LaTeX as being at a deeper
1737 // level within that enclosing itemization/enumeration
1738 // even if there is a "standard" layout at the start of
1744 /* Maybe we have to increment the enumeration depth.
1745 * BUT, enumeration in a footnote is considered in isolation from its
1746 * surrounding paragraph so don't increment if this is the
1747 * first line of the footnote
1748 * AND, bibliographies can't have their depth changed ie. they
1749 * are always of depth 0
1752 && par->Previous()->GetDepth() < par->GetDepth()
1753 && textclasslist.Style(buf->params.textclass,
1754 par->Previous()->GetLayout()
1755 ).labeltype == LABEL_COUNTER_ENUMI
1756 && par->enumdepth < 3
1758 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1759 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1760 && par->footnotekind == LyXParagraph::FOOTNOTE)
1762 && layout.labeltype != LABEL_BIBLIO) {
1766 /* Maybe we have to decrement the enumeration depth, see note above */
1768 && par->Previous()->GetDepth() > par->GetDepth()
1770 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1771 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1772 && par->footnotekind == LyXParagraph::FOOTNOTE)
1774 && layout.labeltype != LABEL_BIBLIO) {
1775 par->enumdepth = par->DepthHook(par->GetDepth())->enumdepth;
1776 par->setCounter(6 + par->enumdepth,
1777 par->DepthHook(par->GetDepth())->getCounter(6 + par->enumdepth));
1778 /* reset the counters.
1779 * A depth change is like a breaking layout
1781 for (int i = 6 + par->enumdepth + 1; i < 10; ++i)
1782 par->setCounter(i, 0);
1785 if (!par->labelstring.empty()) {
1786 par->labelstring.erase();
1789 if (layout.margintype == MARGIN_MANUAL) {
1790 if (par->labelwidthstring.empty()) {
1791 par->SetLabelWidthString(layout.labelstring());
1794 par->SetLabelWidthString(string());
1797 /* is it a layout that has an automatic label ? */
1798 if (layout.labeltype >= LABEL_COUNTER_CHAPTER) {
1800 int i = layout.labeltype - LABEL_COUNTER_CHAPTER;
1801 if (i >= 0 && i<= buf->params.secnumdepth) {
1802 par->incCounter(i); // increment the counter
1804 // Is there a label? Useful for Chapter layout
1805 if (!par->appendix){
1806 if (!layout.labelstring().empty())
1807 par->labelstring = layout.labelstring();
1809 par->labelstring.erase();
1811 if (!layout.labelstring_appendix().empty())
1812 par->labelstring = layout.labelstring_appendix();
1814 par->labelstring.erase();
1817 std::ostringstream s;
1819 if (!par->appendix) {
1820 switch (2 * LABEL_COUNTER_CHAPTER -
1821 textclass.maxcounter() + i) {
1822 case LABEL_COUNTER_CHAPTER:
1823 s << par->getCounter(i);
1825 case LABEL_COUNTER_SECTION:
1826 s << par->getCounter(i - 1) << '.'
1827 << par->getCounter(i);
1829 case LABEL_COUNTER_SUBSECTION:
1830 s << par->getCounter(i - 2) << '.'
1831 << par->getCounter(i - 1) << '.'
1832 << par->getCounter(i);
1834 case LABEL_COUNTER_SUBSUBSECTION:
1835 s << par->getCounter(i - 3) << '.'
1836 << par->getCounter(i - 2) << '.'
1837 << par->getCounter(i - 1) << '.'
1838 << par->getCounter(i);
1841 case LABEL_COUNTER_PARAGRAPH:
1842 s << par->getCounter(i - 4) << '.'
1843 << par->getCounter(i - 3) << '.'
1844 << par->getCounter(i - 2) << '.'
1845 << par->getCounter(i - 1) << '.'
1846 << par->getCounter(i);
1848 case LABEL_COUNTER_SUBPARAGRAPH:
1849 s << par->getCounter(i - 5) << '.'
1850 << par->getCounter(i - 4) << '.'
1851 << par->getCounter(i - 3) << '.'
1852 << par->getCounter(i - 2) << '.'
1853 << par->getCounter(i - 1) << '.'
1854 << par->getCounter(i);
1858 // Can this ever be reached? And in the
1859 // case it is, how can this be correct?
1861 s << par->getCounter(i) << '.';
1864 } else { // appendix
1865 switch (2 * LABEL_COUNTER_CHAPTER - textclass.maxcounter() + i) {
1866 case LABEL_COUNTER_CHAPTER:
1867 if (par->isRightToLeftPar(buf->params))
1868 s << hebrewCounter(par->getCounter(i));
1870 s << alphaCounter(par->getCounter(i));
1872 case LABEL_COUNTER_SECTION:
1873 if (par->isRightToLeftPar(buf->params))
1874 s << hebrewCounter(par->getCounter(i - 1));
1876 s << alphaCounter(par->getCounter(i - 1));
1879 << par->getCounter(i);
1882 case LABEL_COUNTER_SUBSECTION:
1883 if (par->isRightToLeftPar(buf->params))
1884 s << hebrewCounter(par->getCounter(i - 2));
1886 s << alphaCounter(par->getCounter(i - 2));
1889 << par->getCounter(i-1) << '.'
1890 << par->getCounter(i);
1893 case LABEL_COUNTER_SUBSUBSECTION:
1894 if (par->isRightToLeftPar(buf->params))
1895 s << hebrewCounter(par->getCounter(i-3));
1897 s << alphaCounter(par->getCounter(i-3));
1900 << par->getCounter(i-2) << '.'
1901 << par->getCounter(i-1) << '.'
1902 << par->getCounter(i);
1905 case LABEL_COUNTER_PARAGRAPH:
1906 if (par->isRightToLeftPar(buf->params))
1907 s << hebrewCounter(par->getCounter(i-4));
1909 s << alphaCounter(par->getCounter(i-4));
1912 << par->getCounter(i-3) << '.'
1913 << par->getCounter(i-2) << '.'
1914 << par->getCounter(i-1) << '.'
1915 << par->getCounter(i);
1918 case LABEL_COUNTER_SUBPARAGRAPH:
1919 if (par->isRightToLeftPar(buf->params))
1920 s << hebrewCounter(par->getCounter(i-5));
1922 s << alphaCounter(par->getCounter(i-5));
1925 << par->getCounter(i-4) << '.'
1926 << par->getCounter(i-3) << '.'
1927 << par->getCounter(i-2) << '.'
1928 << par->getCounter(i-1) << '.'
1929 << par->getCounter(i);
1933 // Can this ever be reached? And in the
1934 // case it is, how can this be correct?
1936 s << par->getCounter(i) << '.';
1942 par->labelstring += s.str().c_str();
1943 // We really want to remove the c_str as soon as
1946 for (i++; i < 10; ++i) {
1947 // reset the following counters
1948 par->setCounter(i, 0);
1950 } else if (layout.labeltype < LABEL_COUNTER_ENUMI) {
1951 for (i++; i < 10; ++i) {
1952 // reset the following counters
1953 par->setCounter(i, 0);
1955 } else if (layout.labeltype == LABEL_COUNTER_ENUMI) {
1956 par->incCounter(i + par->enumdepth);
1957 int number = par->getCounter(i + par->enumdepth);
1959 std::ostringstream s;
1961 switch (par->enumdepth) {
1963 if (par->isRightToLeftPar(buf->params))
1965 << hebrewCounter(number)
1969 << loweralphaCounter(number)
1973 if (par->isRightToLeftPar(buf->params))
1974 s << '.' << romanCounter(number);
1976 s << romanCounter(number) << '.';
1979 if (par->isRightToLeftPar(buf->params))
1981 << alphaCounter(number);
1983 s << alphaCounter(number)
1987 if (par->isRightToLeftPar(buf->params))
1994 par->labelstring = s.str().c_str();
1995 // we really want to get rid of that c_str()
1997 for (i += par->enumdepth + 1; i < 10; ++i)
1998 par->setCounter(i, 0); /* reset the following counters */
2001 } else if (layout.labeltype == LABEL_BIBLIO) {// ale970302
2002 int i = LABEL_COUNTER_ENUMI - LABEL_COUNTER_CHAPTER + par->enumdepth;
2004 int number = par->getCounter(i);
2006 InsetCommandParams p( "bibitem" );
2007 par->bibkey = new InsetBibKey(p);
2009 par->bibkey->setCounter(number);
2010 par->labelstring = layout.labelstring();
2012 // In biblio should't be following counters but...
2014 string s = layout.labelstring();
2016 // the caption hack:
2017 if (layout.labeltype == LABEL_SENSITIVE) {
2018 bool isOK (par->InInset() && par->InInset()->owner() &&
2019 (par->InInset()->owner()->LyxCode() == Inset::FLOAT_CODE));
2021 if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2022 && (par->footnotekind == LyXParagraph::FIG
2023 || par->footnotekind == LyXParagraph::WIDE_FIG)) {
2024 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2025 ? ":øåéà " : "Figure:";
2026 } else if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2027 && (par->footnotekind == LyXParagraph::TAB
2028 || par->footnotekind == LyXParagraph::WIDE_TAB)) {
2029 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2030 ? ":äìáè" : "Table:";
2031 } else if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2032 && par->footnotekind == LyXParagraph::ALGORITHM) {
2033 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2034 ? ":Ãúéøåâìà " : "Algorithm:";
2038 InsetFloat * tmp = static_cast<InsetFloat*>(par->InInset()->owner());
2040 = floatList.getType(tmp->type());
2041 // We should get the correct number here too.
2042 s = fl.name() + " #:";
2044 /* par->SetLayout(0);
2045 s = layout->labelstring; */
2046 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2047 ? " :úåòîùî øñç" : "Senseless: ";
2050 par->labelstring = s;
2052 /* reset the enumeration counter. They are always resetted
2053 * when there is any other layout between */
2054 for (int i = 6 + par->enumdepth; i < 10; ++i)
2055 par->setCounter(i, 0);
2060 /* Updates all counters BEHIND the row. Changed paragraphs
2061 * with a dynamic left margin will be rebroken. */
2062 void LyXText::UpdateCounters(BufferView * bview, Row * row) const
2069 if (row->par()->next
2071 && row->par()->next->footnoteflag != LyXParagraph::OPEN_FOOTNOTE
2075 par = row->par()->LastPhysicalPar()->Next();
2077 par = row->par()->Next();
2080 par = row->par()->next;
2085 while (row->par() != par)
2088 SetCounter(bview->buffer(), par);
2090 /* now check for the headline layouts. remember that they
2091 * have a dynamic left margin */
2096 ( textclasslist.Style(bview->buffer()->params.textclass,
2097 par->layout).margintype == MARGIN_DYNAMIC
2098 || textclasslist.Style(bview->buffer()->params.textclass,
2099 par->layout).labeltype == LABEL_SENSITIVE)
2102 /* Rebreak the paragraph */
2103 RemoveParagraph(row);
2104 AppendParagraph(bview, row);
2107 /* think about the damned open footnotes! */
2108 while (par->Next() &&
2109 (par->Next()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
2110 || par->Next()->IsDummy())){
2112 if (par->IsDummy()) {
2113 while (row->par() != par)
2115 RemoveParagraph(row);
2116 AppendParagraph(bview, row);
2122 par = par->LastPhysicalPar()->Next();
2131 /* insets an inset. */
2132 void LyXText::InsertInset(BufferView * bview, Inset * inset)
2134 if (!cursor.par()->InsertInsetAllowed(inset))
2136 SetUndo(bview->buffer(), Undo::INSERT,
2138 cursor.par()->ParFromPos(cursor.pos())->previous,
2139 cursor.par()->ParFromPos(cursor.pos())->next
2141 cursor.par()->previous,
2145 cursor.par()->InsertInset(cursor.pos(), inset);
2146 InsertChar(bview, LyXParagraph::META_INSET); /* just to rebreak and refresh correctly.
2147 * The character will not be inserted a
2150 // If we enter a highly editable inset the cursor should be to before
2151 // the inset. This couldn't happen before as Undo was not handled inside
2152 // inset now after the Undo LyX tries to call inset->Edit(...) again
2153 // and cannot do this as the cursor is behind the inset and GetInset
2154 // does not return the inset!
2155 if (inset->Editable() == Inset::HIGHLY_EDITABLE) {
2156 CursorLeft(bview, true);
2162 void LyXText::copyEnvironmentType()
2164 copylayouttype = cursor.par()->GetLayout();
2168 void LyXText::pasteEnvironmentType(BufferView * bview)
2170 SetLayout(bview, copylayouttype);
2174 void LyXText::CutSelection(BufferView * bview, bool doclear)
2176 // Stuff what we got on the clipboard. Even if there is no selection.
2178 // There is a problem with having the stuffing here in that the
2179 // larger the selection the slower LyX will get. This can be
2180 // solved by running the line below only when the selection has
2181 // finished. The solution used currently just works, to make it
2182 // faster we need to be more clever and probably also have more
2183 // calls to stuffClipboard. (Lgb)
2184 bview->stuffClipboard(selectionAsString(bview->buffer()));
2186 // This doesn't make sense, if there is no selection
2190 // OK, we have a selection. This is always between sel_start_cursor
2191 // and sel_end_cursor
2193 // Check whether there are half footnotes in the selection
2194 if (sel_start_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE
2195 || sel_end_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2196 LyXParagraph * tmppar = sel_start_cursor.par();
2197 while (tmppar != sel_end_cursor.par()){
2198 if (tmppar->footnoteflag != sel_end_cursor.par()->footnoteflag) {
2199 WriteAlert(_("Impossible operation"),
2200 _("Don't know what to do with half floats."),
2204 tmppar = tmppar->Next();
2209 // make sure that the depth behind the selection are restored, too
2211 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
2213 LyXParagraph * endpar = sel_end_cursor.par()->Next();
2215 LyXParagraph * undoendpar = endpar;
2217 if (endpar && endpar->GetDepth()) {
2218 while (endpar && endpar->GetDepth()) {
2220 endpar = endpar->LastPhysicalPar()->Next();
2222 endpar = endpar->Next();
2224 undoendpar = endpar;
2226 } else if (endpar) {
2227 endpar = endpar->Next(); // because of parindents etc.
2230 SetUndo(bview->buffer(), Undo::DELETE,
2233 .par()->ParFromPos(sel_start_cursor.pos())->previous,
2235 sel_start_cursor.par()->previous,
2241 // there are two cases: cut only within one paragraph or
2242 // more than one paragraph
2244 if (sel_start_cursor.par()->ParFromPos(sel_start_cursor.pos())
2245 == sel_end_cursor.par()->ParFromPos(sel_end_cursor.pos()))
2247 if (sel_start_cursor.par() == sel_end_cursor.par())
2250 // only within one paragraph
2251 endpar = sel_start_cursor.par();
2252 int pos = sel_end_cursor.pos();
2253 cap.cutSelection(sel_start_cursor.par(), &endpar,
2254 sel_start_cursor.pos(), pos,
2255 bview->buffer()->params.textclass, doclear);
2256 sel_end_cursor.pos(pos);
2258 endpar = sel_end_cursor.par();
2260 int pos = sel_end_cursor.pos();
2261 cap.cutSelection(sel_start_cursor.par(), &endpar,
2262 sel_start_cursor.pos(), pos,
2263 bview->buffer()->params.textclass, doclear);
2265 sel_end_cursor.par(endpar);
2266 sel_end_cursor.pos(pos);
2267 cursor.pos(sel_end_cursor.pos());
2269 endpar = endpar->Next();
2271 // sometimes necessary
2273 sel_start_cursor.par()->StripLeadingSpaces(bview->buffer()->params.textclass);
2275 RedoParagraphs(bview, sel_start_cursor, endpar);
2278 cursor = sel_start_cursor;
2279 SetCursor(bview, cursor.par(), cursor.pos());
2280 sel_cursor = cursor;
2281 UpdateCounters(bview, cursor.row());
2285 void LyXText::CopySelection(BufferView * bview)
2287 // Stuff what we got on the clipboard. Even if there is no selection.
2289 // There is a problem with having the stuffing here in that the
2290 // larger the selection the slower LyX will get. This can be
2291 // solved by running the line below only when the selection has
2292 // finished. The solution used currently just works, to make it
2293 // faster we need to be more clever and probably also have more
2294 // calls to stuffClipboard. (Lgb)
2295 bview->stuffClipboard(selectionAsString(bview->buffer()));
2297 // this doesnt make sense, if there is no selection
2301 // ok we have a selection. This is always between sel_start_cursor
2302 // and sel_end cursor
2305 /* check wether there are half footnotes in the selection */
2306 if (sel_start_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE
2307 || sel_end_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2308 LyXParagraph * tmppar = sel_start_cursor.par();
2309 while (tmppar != sel_end_cursor.par()) {
2310 if (tmppar->footnoteflag !=
2311 sel_end_cursor.par()->footnoteflag) {
2312 WriteAlert(_("Impossible operation"),
2313 _("Don't know what to do"
2314 " with half floats."),
2318 tmppar = tmppar->Next();
2323 // copy behind a space if there is one
2324 while (sel_start_cursor.par()->Last() > sel_start_cursor.pos()
2325 && sel_start_cursor.par()->IsLineSeparator(sel_start_cursor.pos())
2326 && (sel_start_cursor.par() != sel_end_cursor.par()
2327 || sel_start_cursor.pos() < sel_end_cursor.pos()))
2328 sel_start_cursor.pos(sel_start_cursor.pos() + 1);
2332 cap.copySelection(sel_start_cursor.par(), sel_end_cursor.par(),
2333 sel_start_cursor.pos(), sel_end_cursor.pos(),
2334 bview->buffer()->params.textclass);
2338 void LyXText::PasteSelection(BufferView * bview)
2342 // this does not make sense, if there is nothing to paste
2343 if (!cap.checkPastePossible(cursor.par(), cursor.pos()))
2346 SetUndo(bview->buffer(), Undo::INSERT,
2348 cursor.par()->ParFromPos(cursor.pos())->previous,
2349 cursor.par()->ParFromPos(cursor.pos())->next
2351 cursor.par()->previous,
2356 LyXParagraph * endpar;
2357 LyXParagraph * actpar = cursor.par();
2359 int pos = cursor.pos();
2360 cap.pasteSelection(&actpar, &endpar, pos, bview->buffer()->params.textclass);
2362 RedoParagraphs(bview, cursor, endpar);
2364 SetCursor(bview, cursor.par(), cursor.pos());
2367 sel_cursor = cursor;
2368 SetCursor(bview, actpar, pos);
2370 UpdateCounters(bview, cursor.row());
2374 // returns a pointer to the very first LyXParagraph
2375 LyXParagraph * LyXText::FirstParagraph() const
2377 return OwnerParagraph();
2381 // returns true if the specified string is at the specified position
2382 bool LyXText::IsStringInText(LyXParagraph * par,
2383 LyXParagraph::size_type pos,
2384 string const & str) const
2389 LyXParagraph::size_type i = 0;
2390 while (pos + i < par->Last()
2391 && string::size_type(i) < str.length()
2392 && str[i] == par->GetChar(pos + i)) {
2395 if (str.length() == string::size_type(i))
2401 // sets the selection over the number of characters of string, no check!!
2402 void LyXText::SetSelectionOverString(BufferView * bview, string const & str)
2404 sel_cursor = cursor;
2405 for (int i = 0; str[i]; ++i)
2411 // simple replacing. The font of the first selected character is used
2412 void LyXText::ReplaceSelectionWithString(BufferView * bview,
2415 SetCursorParUndo(bview->buffer());
2418 if (!selection) { // create a dummy selection
2419 sel_end_cursor = cursor;
2420 sel_start_cursor = cursor;
2423 // Get font setting before we cut
2424 LyXParagraph::size_type pos = sel_end_cursor.pos();
2425 LyXFont const font = sel_start_cursor.par()
2426 ->GetFontSettings(bview->buffer()->params,
2427 sel_start_cursor.pos());
2429 // Insert the new string
2430 for (string::const_iterator cit = str.begin(); cit != str.end(); ++cit) {
2431 sel_end_cursor.par()->InsertChar(pos, (*cit), font);
2435 // Cut the selection
2436 CutSelection(bview);
2442 // if the string can be found: return true and set the cursor to
2444 bool LyXText::SearchForward(BufferView * bview, string const & str) const
2446 LyXParagraph * par = cursor.par();
2447 LyXParagraph::size_type pos = cursor.pos();
2448 while (par && !IsStringInText(par, pos, str)) {
2449 if (pos < par->Last() - 1)
2457 SetCursor(bview, par, pos);
2465 bool LyXText::SearchBackward(BufferView * bview, string const & str) const
2467 LyXParagraph * par = cursor.par();
2468 int pos = cursor.pos();
2474 // We skip empty paragraphs (Asger)
2476 par = par->Previous();
2478 pos = par->Last() - 1;
2479 } while (par && pos < 0);
2481 } while (par && !IsStringInText(par, pos, str));
2484 SetCursor(bview, par, pos);
2491 // needed to insert the selection
2492 void LyXText::InsertStringA(BufferView * bview, string const & str)
2494 LyXParagraph * par = cursor.par();
2495 LyXParagraph::size_type pos = cursor.pos();
2496 LyXParagraph::size_type a = 0;
2497 LyXParagraph * endpar = cursor.par()->Next();
2499 SetCursorParUndo(bview->buffer());
2502 textclasslist.Style(bview->buffer()->params.textclass,
2503 cursor.par()->GetLayout()).isEnvironment();
2504 // only to be sure, should not be neccessary
2507 // insert the string, don't insert doublespace
2508 string::size_type i = 0;
2509 while (i < str.length()) {
2510 if (str[i] != '\n') {
2512 && i + 1 < str.length() && str[i + 1] != ' '
2513 && pos && par->GetChar(pos - 1)!= ' ') {
2514 par->InsertChar(pos, ' ', current_font);
2516 } else if (str[i] == ' ') {
2517 InsetSpecialChar * new_inset =
2518 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2519 if (par->InsertInsetAllowed(new_inset)) {
2520 par->InsertInset(pos, new_inset,
2526 } else if (str[i] == '\t') {
2527 for (a = pos; a < (pos / 8 + 1) * 8 ; ++a) {
2528 InsetSpecialChar * new_inset =
2529 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2530 if (par->InsertInsetAllowed(new_inset)) {
2531 par->InsertInset(pos, new_inset,
2538 } else if (str[i] != 13 &&
2539 // Ignore unprintables
2540 (str[i] & 127) >= ' ') {
2541 par->InsertChar(pos, str[i], current_font);
2545 if (!par->size()) { // par is empty
2546 InsetSpecialChar * new_inset =
2547 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2548 if (par->InsertInsetAllowed(new_inset)) {
2549 par->InsertInset(pos,
2557 par->BreakParagraph(bview->buffer()->params, pos, flag);
2564 RedoParagraphs(bview, cursor, endpar);
2565 SetCursor(bview, cursor.par(), cursor.pos());
2566 sel_cursor = cursor;
2567 SetCursor(bview, par, pos);
2572 /* turns double-CR to single CR, others where converted into one blank and 13s
2573 * that are ignored .Double spaces are also converted into one. Spaces at
2574 * the beginning of a paragraph are forbidden. tabs are converted into one
2575 * space. then InsertStringA is called */
2576 void LyXText::InsertStringB(BufferView * bview, string const & s)
2579 string::size_type i = 1;
2580 while (i < str.length()) {
2583 if (str[i] == ' ' && i + 1 < str.length() && str[i + 1] == ' ')
2585 if (str[i] == '\n' && i + 1 < str.length()) {
2586 if (str[i + 1] != '\n') {
2587 if (str[i - 1] != ' ')
2592 while (i + 1 < str.length()
2593 && (str[i + 1] == ' '
2594 || str[i + 1] == '\t'
2595 || str[i + 1] == '\n'
2596 || str[i + 1] == 13)) {
2603 InsertStringA(bview, str);
2607 bool LyXText::GotoNextInset(BufferView * bview,
2608 std::vector<Inset::Code> const & codes,
2609 string const & contents) const
2611 LyXCursor res = cursor;
2614 if (res.pos() < res.par()->Last() - 1) {
2615 res.pos(res.pos() + 1);
2617 res.par(res.par()->Next());
2621 } while (res.par() &&
2622 !(res.par()->GetChar(res.pos()) == LyXParagraph::META_INSET
2623 && (inset = res.par()->GetInset(res.pos())) != 0
2624 && find(codes.begin(), codes.end(), inset->LyxCode())
2626 && (contents.empty() ||
2627 static_cast<InsetCommand *>(res.par()->GetInset(res.pos()))->getContents()
2631 SetCursor(bview, res.par(), res.pos());
2638 void LyXText::CheckParagraph(BufferView * bview, LyXParagraph * par,
2639 LyXParagraph::size_type pos)
2641 LyXCursor tmpcursor;
2644 LyXParagraph::size_type z;
2645 Row * row = GetRow(par, pos, y);
2647 // is there a break one row above
2648 if (row->previous() && row->previous()->par() == row->par()) {
2649 z = NextBreakPoint(bview, row->previous(), workWidth(bview));
2650 if (z >= row->pos()) {
2651 // set the dimensions of the row above
2652 y -= row->previous()->height();
2654 refresh_row = row->previous();
2655 status = LyXText::NEED_MORE_REFRESH;
2657 BreakAgain(bview, row->previous());
2659 // set the cursor again. Otherwise
2660 // dangling pointers are possible
2661 SetCursor(bview, cursor.par(), cursor.pos(),
2662 false, cursor.boundary());
2663 sel_cursor = cursor;
2668 int const tmpheight = row->height();
2669 LyXParagraph::size_type const tmplast = RowLast(row);
2673 BreakAgain(bview, row);
2674 if (row->height() == tmpheight && RowLast(row) == tmplast)
2675 status = LyXText::NEED_VERY_LITTLE_REFRESH;
2677 status = LyXText::NEED_MORE_REFRESH;
2679 // check the special right address boxes
2680 if (textclasslist.Style(bview->buffer()->params.textclass,
2681 par->GetLayout()).margintype
2682 == MARGIN_RIGHT_ADDRESS_BOX) {
2689 RedoDrawingOfParagraph(bview, tmpcursor);
2692 // set the cursor again. Otherwise dangling pointers are possible
2693 // also set the selection
2697 SetCursorIntern(bview, sel_cursor.par(), sel_cursor.pos(),
2698 false, sel_cursor.boundary());
2699 sel_cursor = cursor;
2700 SetCursorIntern(bview, sel_start_cursor.par(),
2701 sel_start_cursor.pos(),
2702 false, sel_start_cursor.boundary());
2703 sel_start_cursor = cursor;
2704 SetCursorIntern(bview, sel_end_cursor.par(),
2705 sel_end_cursor.pos(),
2706 false, sel_end_cursor.boundary());
2707 sel_end_cursor = cursor;
2708 SetCursorIntern(bview, last_sel_cursor.par(),
2709 last_sel_cursor.pos(),
2710 false, last_sel_cursor.boundary());
2711 last_sel_cursor = cursor;
2714 SetCursorIntern(bview, cursor.par(), cursor.pos(),
2715 false, cursor.boundary());
2719 // returns false if inset wasn't found
2720 bool LyXText::UpdateInset(BufferView * bview, Inset * inset)
2722 // first check the current paragraph
2723 int pos = cursor.par()->GetPositionOfInset(inset);
2725 CheckParagraph(bview, cursor.par(), pos);
2729 // check every paragraph
2731 LyXParagraph * par = FirstParagraph();
2734 // make sure the paragraph is open
2735 if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
2737 pos = par->GetPositionOfInset(inset);
2739 CheckParagraph(bview, par, pos);
2752 void LyXText::SetCursor(BufferView * bview, LyXParagraph * par,
2753 LyXParagraph::size_type pos,
2754 bool setfont, bool boundary) const
2756 LyXCursor old_cursor = cursor;
2757 SetCursorIntern(bview, par, pos, setfont, boundary);
2758 DeleteEmptyParagraphMechanism(bview, old_cursor);
2762 void LyXText::SetCursor(BufferView *bview, LyXCursor & cur, LyXParagraph * par,
2763 LyXParagraph::size_type pos, bool boundary) const
2766 // correct the cursor position if impossible
2767 if (pos > par->Last()){
2768 LyXParagraph * tmppar = par->ParFromPos(pos);
2769 pos = par->PositionInParFromPos(pos);
2772 if (par->IsDummy() && par->previous &&
2773 par->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2774 while (par->previous &&
2775 ((par->previous->IsDummy() &&
2776 (par->previous->previous->footnoteflag ==
2777 LyXParagraph::CLOSED_FOOTNOTE)) ||
2778 (par->previous->footnoteflag ==
2779 LyXParagraph::CLOSED_FOOTNOTE))) {
2780 par = par->previous ;
2781 if (par->IsDummy() &&
2782 (par->previous->footnoteflag ==
2783 LyXParagraph::CLOSED_FOOTNOTE))
2784 pos += par->size() + 1;
2786 if (par->previous) {
2787 par = par->previous;
2789 pos += par->size() + 1;
2794 cur.boundary(boundary);
2796 /* get the cursor y position in text */
2798 Row * row = GetRow(par, pos, y);
2799 /* y is now the beginning of the cursor row */
2800 y += row->baseline();
2801 /* y is now the cursor baseline */
2804 /* now get the cursors x position */
2806 float fill_separator, fill_hfill, fill_label_hfill;
2807 PrepareToPrint(bview, row, x, fill_separator, fill_hfill,
2809 LyXParagraph::size_type cursor_vpos = 0;
2810 LyXParagraph::size_type last = RowLastPrintable(row);
2812 if (pos > last + 1) // This shouldn't happen.
2814 else if (pos < row->pos())
2817 if (last < row->pos())
2818 cursor_vpos = row->pos();
2819 else if (pos > last && !boundary)
2820 cursor_vpos = (row->par()->isRightToLeftPar(bview->buffer()->params))
2821 ? row->pos() : last + 1;
2822 else if (pos > row->pos() &&
2823 (pos > last || boundary))
2824 /// Place cursor after char at (logical) position pos - 1
2825 cursor_vpos = (bidi_level(pos - 1) % 2 == 0)
2826 ? log2vis(pos - 1) + 1 : log2vis(pos - 1);
2828 /// Place cursor before char at (logical) position pos
2829 cursor_vpos = (bidi_level(pos) % 2 == 0)
2830 ? log2vis(pos) : log2vis(pos) + 1;
2832 LyXParagraph::size_type main_body =
2833 BeginningOfMainBody(bview->buffer(), row->par());
2834 if ((main_body > 0) &&
2835 ((main_body-1 > last) ||
2836 !row->par()->IsLineSeparator(main_body-1)))
2839 for (LyXParagraph::size_type vpos = row->pos();
2840 vpos < cursor_vpos; ++vpos) {
2841 pos = vis2log(vpos);
2842 if (main_body > 0 && pos == main_body - 1) {
2843 x += fill_label_hfill +
2844 lyxfont::width(textclasslist.Style(
2845 bview->buffer()->params.textclass,
2846 row->par()->GetLayout())
2848 GetFont(bview->buffer(), row->par(), -2));
2849 if (row->par()->IsLineSeparator(main_body-1))
2850 x -= SingleWidth(bview, row->par(),main_body-1);
2852 if (HfillExpansion(bview->buffer(), row, pos)) {
2853 x += SingleWidth(bview, row->par(), pos);
2854 if (pos >= main_body)
2857 x += fill_label_hfill;
2858 } else if (row->par()->IsSeparator(pos)) {
2859 x += SingleWidth(bview, row->par(), pos);
2860 if (pos >= main_body)
2861 x += fill_separator;
2863 x += SingleWidth(bview, row->par(), pos);
2872 void LyXText::SetCursorIntern(BufferView * bview, LyXParagraph * par,
2873 LyXParagraph::size_type pos,
2874 bool setfont, bool boundary) const
2876 SetCursor(bview, cursor, par, pos, boundary);
2878 SetCurrentFont(bview);
2882 void LyXText::SetCurrentFont(BufferView * bview) const
2884 LyXParagraph::size_type pos = cursor.pos();
2885 if (cursor.boundary() && pos > 0)
2889 if (pos == cursor.par()->Last())
2891 else if (cursor.par()->IsSeparator(pos)) {
2892 if (pos > cursor.row()->pos() &&
2893 bidi_level(pos) % 2 ==
2894 bidi_level(pos - 1) % 2)
2896 else if (pos + 1 < cursor.par()->Last())
2902 cursor.par()->GetFontSettings(bview->buffer()->params, pos);
2903 real_current_font = GetFont(bview->buffer(), cursor.par(), pos);
2905 if (cursor.pos() == cursor.par()->Last() &&
2906 IsBoundary(bview->buffer(), cursor.par(), cursor.pos()) &&
2907 !cursor.boundary()) {
2908 Language const * lang =
2909 cursor.par()->getParLanguage(bview->buffer()->params);
2910 current_font.setLanguage(lang);
2911 real_current_font.setLanguage(lang);
2916 void LyXText::SetCursorFromCoordinates(BufferView * bview, int x, int y) const
2918 LyXCursor old_cursor = cursor;
2920 /* get the row first */
2922 Row * row = GetRowNearY(y);
2923 cursor.par(row->par());
2926 int column = GetColumnNearX(bview, row, x, bound);
2927 cursor.pos(row->pos() + column);
2929 cursor.y(y + row->baseline());
2931 cursor.boundary(bound);
2932 SetCurrentFont(bview);
2933 DeleteEmptyParagraphMechanism(bview, old_cursor);
2937 void LyXText::SetCursorFromCoordinates(BufferView * bview, LyXCursor & cur,
2940 /* get the row first */
2942 Row * row = GetRowNearY(y);
2944 int column = GetColumnNearX(bview, row, x, bound);
2946 cur.par(row->par());
2947 cur.pos(row->pos() + column);
2949 cur.y(y + row->baseline());
2951 cur.boundary(bound);
2955 void LyXText::CursorLeft(BufferView * bview, bool internal) const
2957 if (cursor.pos() > 0) {
2958 bool boundary = cursor.boundary();
2959 SetCursor(bview, cursor.par(), cursor.pos() - 1, true, false);
2960 if (!internal && !boundary &&
2961 IsBoundary(bview->buffer(), cursor.par(), cursor.pos() + 1))
2962 SetCursor(bview, cursor.par(), cursor.pos() + 1, true, true);
2963 } else if (cursor.par()->Previous()) { // steps into the above paragraph.
2964 LyXParagraph * par = cursor.par()->Previous();
2965 SetCursor(bview, par, par->Last());
2970 void LyXText::CursorRight(BufferView * bview, bool internal) const
2972 if (!internal && cursor.boundary() &&
2973 !cursor.par()->IsNewline(cursor.pos()))
2974 SetCursor(bview, cursor.par(), cursor.pos(), true, false);
2975 else if (cursor.pos() < cursor.par()->Last()) {
2976 SetCursor(bview, cursor.par(), cursor.pos() + 1, true, false);
2978 IsBoundary(bview->buffer(), cursor.par(), cursor.pos()))
2979 SetCursor(bview, cursor.par(), cursor.pos(), true, true);
2980 } else if (cursor.par()->Next())
2981 SetCursor(bview, cursor.par()->Next(), 0);
2985 void LyXText::CursorUp(BufferView * bview) const
2987 SetCursorFromCoordinates(bview, cursor.x_fix(),
2988 cursor.y() - cursor.row()->baseline() - 1);
2992 void LyXText::CursorDown(BufferView * bview) const
2994 SetCursorFromCoordinates(bview, cursor.x_fix(),
2995 cursor.y() - cursor.row()->baseline()
2996 + cursor.row()->height() + 1);
3000 void LyXText::CursorUpParagraph(BufferView * bview) const
3002 if (cursor.pos() > 0) {
3003 SetCursor(bview, cursor.par(), 0);
3005 else if (cursor.par()->Previous()) {
3006 SetCursor(bview, cursor.par()->Previous(), 0);
3011 void LyXText::CursorDownParagraph(BufferView * bview) const
3013 if (cursor.par()->Next()) {
3014 SetCursor(bview, cursor.par()->Next(), 0);
3016 SetCursor(bview, cursor.par(), cursor.par()->Last());
3021 void LyXText::DeleteEmptyParagraphMechanism(BufferView * bview,
3022 LyXCursor const & old_cursor) const
3024 // Would be wrong to delete anything if we have a selection.
3025 if (selection) return;
3027 // We allow all kinds of "mumbo-jumbo" when freespacing.
3028 if (textclasslist.Style(bview->buffer()->params.textclass,
3029 old_cursor.par()->GetLayout()).free_spacing)
3032 bool deleted = false;
3034 /* Ok I'll put some comments here about what is missing.
3035 I have fixed BackSpace (and thus Delete) to not delete
3036 double-spaces automagically. I have also changed Cut,
3037 Copy and Paste to hopefully do some sensible things.
3038 There are still some small problems that can lead to
3039 double spaces stored in the document file or space at
3040 the beginning of paragraphs. This happens if you have
3041 the cursor betwenn to spaces and then save. Or if you
3042 cut and paste and the selection have a space at the
3043 beginning and then save right after the paste. I am
3044 sure none of these are very hard to fix, but I will
3045 put out 1.1.4pre2 with FIX_DOUBLE_SPACE defined so
3046 that I can get some feedback. (Lgb)
3049 // If old_cursor.pos() == 0 and old_cursor.pos()(1) == LineSeparator
3050 // delete the LineSeparator.
3053 // If old_cursor.pos() == 1 and old_cursor.pos()(0) == LineSeparator
3054 // delete the LineSeparator.
3057 // If the pos around the old_cursor were spaces, delete one of them.
3058 if (old_cursor.par() != cursor.par() || old_cursor.pos() != cursor.pos()) {
3059 // Only if the cursor has really moved
3061 if (old_cursor.pos() > 0
3062 && old_cursor.pos() < old_cursor.par()->Last()
3063 && old_cursor.par()->IsLineSeparator(old_cursor.pos())
3064 && old_cursor.par()->IsLineSeparator(old_cursor.pos() - 1)) {
3065 old_cursor.par()->Erase(old_cursor.pos() - 1);
3066 RedoParagraphs(bview, old_cursor, old_cursor.par()->Next());
3068 if (old_cursor.par() == cursor.par() &&
3069 cursor.pos() > old_cursor.pos()) {
3070 SetCursorIntern(bview, cursor.par(),
3073 SetCursorIntern(bview, cursor.par(),
3079 // Do not delete empty paragraphs with keepempty set.
3080 if ((textclasslist.Style(bview->buffer()->params.textclass,
3081 old_cursor.par()->GetLayout())).keepempty)
3084 LyXCursor tmpcursor;
3086 if (old_cursor.par() != cursor.par()) {
3087 if ((old_cursor.par()->Last() == 0
3088 || (old_cursor.par()->Last() == 1
3089 && old_cursor.par()->IsLineSeparator(0)))
3091 && old_cursor.par()->FirstPhysicalPar()
3092 == old_cursor.par()->LastPhysicalPar()
3095 // ok, we will delete anything
3097 // make sure that you do not delete any environments
3100 old_cursor.par()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE &&
3101 !(old_cursor.row()->previous()
3102 && old_cursor.row()->previous()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
3103 && !(old_cursor.row()->next()
3104 && old_cursor.row()->next()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE))
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))
3112 status = LyXText::NEED_MORE_REFRESH;
3115 if (old_cursor.row()->previous()) {
3116 refresh_row = old_cursor.row()->previous();
3117 refresh_y = old_cursor.y() - old_cursor.row()->baseline() - refresh_row->height();
3119 cursor = old_cursor; // that undo can restore the right cursor position
3120 LyXParagraph * endpar = old_cursor.par()->next;
3121 if (endpar && endpar->GetDepth()) {
3122 while (endpar && endpar->GetDepth()) {
3124 endpar = endpar->LastPhysicalPar()->Next();
3126 endpar = endpar->Next();
3130 SetUndo(bview->buffer(), Undo::DELETE,
3131 old_cursor.par()->previous,
3136 RemoveRow(old_cursor.row());
3137 if (OwnerParagraph() == old_cursor.par()) {
3138 OwnerParagraph(OwnerParagraph()->next);
3141 delete old_cursor.par();
3143 /* Breakagain the next par. Needed
3144 * because of the parindent that
3145 * can occur or dissappear. The
3146 * next row can change its height,
3147 * if there is another layout before */
3148 if (refresh_row->next()) {
3149 BreakAgain(bview, refresh_row->next());
3150 UpdateCounters(bview, refresh_row);
3152 SetHeightOfRow(bview, refresh_row);
3154 refresh_row = old_cursor.row()->next();
3155 refresh_y = old_cursor.y() - old_cursor.row()->baseline();
3158 cursor = old_cursor; // that undo can restore the right cursor position
3159 LyXParagraph * endpar = old_cursor.par()->next;
3160 if (endpar && endpar->GetDepth()) {
3161 while (endpar && endpar->GetDepth()) {
3163 endpar = endpar->LastPhysicalPar()->Next();
3165 endpar = endpar->Next();
3169 SetUndo(bview->buffer(), Undo::DELETE,
3170 old_cursor.par()->previous,
3175 RemoveRow(old_cursor.row());
3177 if (OwnerParagraph() == old_cursor.par()) {
3178 OwnerParagraph(OwnerParagraph()->next);
3180 delete old_cursor.par();
3182 /* Breakagain the next par. Needed
3183 because of the parindent that can
3184 occur or dissappear.
3185 The next row can change its height,
3186 if there is another layout before
3189 BreakAgain(bview, refresh_row);
3190 UpdateCounters(bview, refresh_row->previous());
3196 SetCursorIntern(bview, cursor.par(), cursor.pos());
3198 if (sel_cursor.par() == old_cursor.par()
3199 && sel_cursor.pos() == sel_cursor.pos()) {
3200 // correct selection
3201 sel_cursor = cursor;
3208 if (old_cursor.par()->StripLeadingSpaces(bview->buffer()->params.textclass)) {
3209 RedoParagraphs(bview, old_cursor, old_cursor.par()->Next());
3211 SetCursorIntern(bview, cursor.par(), cursor.pos());
3212 sel_cursor = cursor;
3219 LyXParagraph * LyXText::GetParFromID(int id)
3221 LyXParagraph * result = FirstParagraph();
3222 while (result && result->id() != id)
3223 result = result->next;
3229 bool LyXText::TextUndo(BufferView * bview)
3233 // returns false if no undo possible
3234 Undo * undo = bview->buffer()->undostack.pop();
3238 bview->buffer()->redostack
3239 .push(CreateUndo(bview->buffer(), undo->kind,
3240 GetParFromID(undo->number_of_before_par),
3241 GetParFromID(undo->number_of_behind_par)));
3243 return TextHandleUndo(bview, undo);
3247 bool LyXText::TextRedo(BufferView * bview)
3251 // returns false if no redo possible
3252 Undo * undo = bview->buffer()->redostack.pop();
3256 bview->buffer()->undostack
3257 .push(CreateUndo(bview->buffer(), undo->kind,
3258 GetParFromID(undo->number_of_before_par),
3259 GetParFromID(undo->number_of_behind_par)));
3261 return TextHandleUndo(bview, undo);
3265 bool LyXText::TextHandleUndo(BufferView * bview, Undo * undo)
3269 // returns false if no undo possible
3270 bool result = false;
3272 LyXParagraph * before =
3273 GetParFromID(undo->number_of_before_par);
3274 LyXParagraph * behind =
3275 GetParFromID(undo->number_of_behind_par);
3276 LyXParagraph * tmppar;
3277 LyXParagraph * tmppar2;
3278 LyXParagraph * endpar;
3279 LyXParagraph * tmppar5;
3281 // if there's no before take the beginning
3282 // of the document for redoing
3284 SetCursorIntern(bview, FirstParagraph(), 0);
3286 // replace the paragraphs with the undo informations
3288 LyXParagraph * tmppar3 = undo->par;
3289 undo->par = 0; // otherwise the undo destructor would delete the paragraph
3290 LyXParagraph * tmppar4 = tmppar3;
3292 while (tmppar4->next)
3293 tmppar4 = tmppar4->next;
3294 } // get last undo par
3296 // now remove the old text if there is any
3297 if (before != behind || (!behind && !before)){
3299 tmppar5 = before->next;
3301 tmppar5 = OwnerParagraph();
3303 while (tmppar5 && tmppar5 != behind){
3305 tmppar5 = tmppar5->next;
3306 // a memory optimization for edit: Only layout information
3307 // is stored in the undo. So restore the text informations.
3308 if (undo->kind == Undo::EDIT) {
3309 tmppar2->setContentsFromPar(tmppar);
3310 tmppar->clearContents();
3311 tmppar2 = tmppar2->next;
3316 // put the new stuff in the list if there is one
3319 before->next = tmppar3;
3321 OwnerParagraph(tmppar3);
3322 tmppar3->previous = before;
3325 OwnerParagraph(behind);
3328 tmppar4->next = behind;
3330 behind->previous = tmppar4;
3334 // Set the cursor for redoing
3337 SetCursorIntern(bview, before->FirstSelfrowPar(), 0);
3339 SetCursorIntern(bview, before, 0);
3342 // check wether before points to a closed float and open it if necessary
3343 if (before && before->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE
3344 && before->next && before->next->footnoteflag != LyXParagraph::NO_FOOTNOTE){
3346 while (tmppar4->previous &&
3347 tmppar4->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
3348 tmppar4 = tmppar4->previous;
3349 while (tmppar4 && tmppar4->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3350 tmppar4->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
3351 tmppar4 = tmppar4->next;
3358 // open a cosed footnote at the end if necessary
3359 if (behind && behind->previous &&
3360 behind->previous->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
3361 behind->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3362 while (behind && behind->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3363 behind->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
3364 behind = behind->next;
3369 // calculate the endpar for redoing the paragraphs.
3372 if (behind->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
3373 endpar = behind->LastPhysicalPar()->Next();
3375 endpar = behind->NextAfterFootnote()->LastPhysicalPar()->Next();
3377 endpar = behind->Next();
3382 tmppar = GetParFromID(undo->number_of_cursor_par);
3383 RedoParagraphs(bview, cursor, endpar);
3385 SetCursorIntern(bview, tmppar, undo->cursor_pos);
3386 UpdateCounters(bview, cursor.row());
3396 void LyXText::FinishUndo()
3400 // makes sure the next operation will be stored
3401 undo_finished = true;
3405 void LyXText::FreezeUndo()
3409 // this is dangerous and for internal use only
3414 void LyXText::UnFreezeUndo()
3418 // this is dangerous and for internal use only
3419 undo_frozen = false;
3423 void LyXText::SetUndo(Buffer * buf, Undo::undo_kind kind,
3424 LyXParagraph const * before,
3425 LyXParagraph const * behind) const
3430 buf->undostack.push(CreateUndo(buf, kind, before, behind));
3431 buf->redostack.clear();
3435 void LyXText::SetRedo(Buffer * buf, Undo::undo_kind kind,
3436 LyXParagraph const * before, LyXParagraph const * behind)
3440 buf->redostack.push(CreateUndo(buf, kind, before, behind));
3444 Undo * LyXText::CreateUndo(Buffer * buf, Undo::undo_kind kind,
3445 LyXParagraph const * before,
3446 LyXParagraph const * behind) const
3451 int before_number = -1;
3452 int behind_number = -1;
3454 before_number = before->id();
3456 behind_number = behind->id();
3457 // Undo::EDIT and Undo::FINISH are
3458 // always finished. (no overlapping there)
3459 // overlapping only with insert and delete inside one paragraph:
3460 // Nobody wants all removed character
3461 // appear one by one when undoing.
3462 // EDIT is special since only layout information, not the
3463 // contents of a paragaph are stored.
3464 if (!undo_finished && (kind != Undo::EDIT) && (kind != Undo::FINISH)){
3465 // check wether storing is needed
3466 if (!buf->undostack.empty() &&
3467 buf->undostack.top()->kind == kind &&
3468 buf->undostack.top()->number_of_before_par == before_number &&
3469 buf->undostack.top()->number_of_behind_par == behind_number ){
3474 // create a new Undo
3475 LyXParagraph * undopar;
3476 LyXParagraph * tmppar;
3477 LyXParagraph * tmppar2;
3479 LyXParagraph * start = 0;
3480 LyXParagraph * end = 0;
3483 start = before->next;
3485 start = FirstParagraph();
3487 end = behind->previous;
3489 end = FirstParagraph();
3494 if (start && end && (start != end->next) &&
3495 ((before != behind) || (!before && !behind)))
3498 tmppar2 = tmppar->Clone();
3499 tmppar2->id(tmppar->id());
3501 // a memory optimization: Just store the layout information
3503 if (kind == Undo::EDIT){
3504 //tmppar2->text.clear();
3505 tmppar2->clearContents();
3510 while (tmppar != end && tmppar->next) {
3511 tmppar = tmppar->next;
3512 tmppar2->next = tmppar->Clone();
3513 tmppar2->next->id(tmppar->id());
3514 // a memory optimization: Just store the layout
3515 // information when only edit
3516 if (kind == Undo::EDIT){
3517 //tmppar2->next->text.clear();
3518 tmppar2->clearContents();
3520 tmppar2->next->previous = tmppar2;
3521 tmppar2 = tmppar2->next;
3525 undopar = 0; // nothing to replace (undo of delete maybe)
3528 int cursor_par = cursor.par()->ParFromPos(cursor.pos())->id();
3529 int cursor_pos = cursor.par()->PositionInParFromPos(cursor.pos());
3531 int cursor_par = cursor.par()->id();
3532 int cursor_pos = cursor.pos();
3535 Undo * undo = new Undo(kind,
3536 before_number, behind_number,
3537 cursor_par, cursor_pos,
3540 undo_finished = false;
3545 void LyXText::SetCursorParUndo(Buffer * buf)
3549 SetUndo(buf, Undo::FINISH,
3551 cursor.par()->ParFromPos(cursor.pos())->previous,
3552 cursor.par()->ParFromPos(cursor.pos())->next
3554 cursor.par()->previous,
3561 void LyXText::toggleAppendix(BufferView * bview)
3564 LyXParagraph * par = cursor.par()->FirstPhysicalPar();
3566 LyXParagraph * par = cursor.par();
3568 bool start = !par->start_of_appendix;
3570 // ensure that we have only one start_of_appendix in this document
3571 LyXParagraph * tmp = FirstParagraph();
3572 for (; tmp; tmp = tmp->next)
3573 tmp->start_of_appendix = 0;
3574 par->start_of_appendix = start;
3576 // we can set the refreshing parameters now
3577 status = LyXText::NEED_MORE_REFRESH;
3579 refresh_row = 0; // not needed for full update
3580 UpdateCounters(bview, 0);
3581 SetCursor(bview, cursor.par(), cursor.pos());
3585 LyXParagraph * LyXText::OwnerParagraph() const
3588 return inset_owner->par;
3590 return bv_owner->buffer()->paragraph;
3594 LyXParagraph * LyXText::OwnerParagraph(LyXParagraph * p) const
3597 inset_owner->par = p;
3599 bv_owner->buffer()->paragraph = p;