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->params.spaceTop(lyxlayout.fill_top ?
594 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE));
595 fppar->params.spaceBottom(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->params.spaceTop(lyxlayout.fill_top ?
620 VSpace(VSpace::VFILL) : VSpace(VSpace::NONE));
621 fppar->params.spaceBottom(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());
660 ClearSelection(bview);
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()->params.depth(cursor.par()->FirstPhysicalPar()->params.depth() + 1);
740 cursor.par()->params.depth(cursor.par()->params.depth() + 1);
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()->params.depth(0);
757 cursor.par()->params.depth(0);
759 cursor.par(cursor.par()->Next());
762 if (cursor.par()->footnoteflag == sel_start_cursor.par()->footnoteflag)
763 cursor.par()->FirstPhysicalPar()->params.depth(0);
765 cursor.par()->params.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());
778 ClearSelection(bview);
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()->params.depth())
835 cursor.par()->FirstPhysicalPar()->params.depth(cursor.par()->FirstPhysicalPar()->params.depth() - 1);
838 if (cursor.par()->params.depth())
839 cursor.par()->params.depth(cursor.par()->params.depth() - 1);
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());
855 ClearSelection(bview);
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());
937 ClearSelection(bview);
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(BufferView * bview)
1122 const bool lsel = selection;
1125 last_sel_cursor = sel_cursor;
1126 sel_start_cursor = sel_cursor;
1127 sel_end_cursor = sel_cursor;
1132 // first the toggling area
1133 if (cursor.y() < last_sel_cursor.y()
1134 || (cursor.y() == last_sel_cursor.y()
1135 && cursor.x() < last_sel_cursor.x())) {
1136 toggle_end_cursor = last_sel_cursor;
1137 toggle_cursor = cursor;
1139 toggle_end_cursor = cursor;
1140 toggle_cursor = last_sel_cursor;
1143 last_sel_cursor = cursor;
1145 // and now the whole selection
1147 if (sel_cursor.par() == cursor.par())
1148 if (sel_cursor.pos() < cursor.pos()) {
1149 sel_end_cursor = cursor;
1150 sel_start_cursor = sel_cursor;
1152 sel_end_cursor = sel_cursor;
1153 sel_start_cursor = cursor;
1155 else if (sel_cursor.y() < cursor.y() ||
1156 (sel_cursor.y() == cursor.y() && sel_cursor.x() < cursor.x())) {
1157 sel_end_cursor = cursor;
1158 sel_start_cursor = sel_cursor;
1161 sel_end_cursor = sel_cursor;
1162 sel_start_cursor = cursor;
1165 // a selection with no contents is not a selection
1166 if (sel_start_cursor.par() == sel_end_cursor.par() &&
1167 sel_start_cursor.pos() == sel_end_cursor.pos())
1170 if (inset_owner && (selection || lsel))
1171 inset_owner->SetUpdateStatus(bview, InsetText::SELECTION);
1175 string const LyXText::selectionAsString(Buffer const * buffer) const
1177 if (!selection) return string();
1180 // Special handling if the whole selection is within one paragraph
1181 if (sel_start_cursor.par() == sel_end_cursor.par()) {
1182 result += sel_start_cursor.par()->String(buffer,
1183 sel_start_cursor.pos(),
1184 sel_end_cursor.pos());
1188 // The selection spans more than one paragraph
1190 // First paragraph in selection
1191 result += sel_start_cursor.par()->String(buffer,
1192 sel_start_cursor.pos(),
1193 sel_start_cursor.par()->Last())
1196 // The paragraphs in between (if any)
1197 LyXCursor tmpcur(sel_start_cursor);
1198 tmpcur.par(tmpcur.par()->Next());
1199 while (tmpcur.par() != sel_end_cursor.par()) {
1200 result += tmpcur.par()->String(buffer, 0, tmpcur.par()->Last()) + "\n\n";
1201 tmpcur.par(tmpcur.par()->Next()); // Or NextAfterFootnote??
1204 // Last paragraph in selection
1205 result += sel_end_cursor.par()->String(buffer, 0, sel_end_cursor.pos());
1211 void LyXText::ClearSelection(BufferView * /*bview*/) const
1218 void LyXText::CursorHome(BufferView * bview) const
1220 SetCursor(bview, cursor.par(), cursor.row()->pos());
1224 void LyXText::CursorEnd(BufferView * bview) const
1226 if (!cursor.row()->next() || cursor.row()->next()->par() != cursor.row()->par())
1227 SetCursor(bview, cursor.par(), RowLast(cursor.row()) + 1);
1229 if (cursor.par()->Last() &&
1230 (cursor.par()->GetChar(RowLast(cursor.row())) == ' '
1231 || cursor.par()->IsNewline(RowLast(cursor.row()))))
1232 SetCursor(bview, cursor.par(), RowLast(cursor.row()));
1234 SetCursor(bview,cursor.par(), RowLast(cursor.row()) + 1);
1239 void LyXText::CursorTop(BufferView * bview) const
1241 while (cursor.par()->Previous())
1242 cursor.par(cursor.par()->Previous());
1243 SetCursor(bview, cursor.par(), 0);
1247 void LyXText::CursorBottom(BufferView * bview) const
1249 while (cursor.par()->Next())
1250 cursor.par(cursor.par()->Next());
1251 SetCursor(bview, cursor.par(), cursor.par()->Last());
1255 /* returns a pointer to the row near the specified y-coordinate
1256 * (relative to the whole text). y is set to the real beginning
1258 Row * LyXText::GetRowNearY(int & y) const
1260 Row * tmprow = firstrow;
1263 while (tmprow->next() && tmpy + tmprow->height() <= y) {
1264 tmpy += tmprow->height();
1265 tmprow = tmprow->next();
1268 y = tmpy; // return the real y
1273 void LyXText::ToggleFree(BufferView * bview,
1274 LyXFont const & font, bool toggleall)
1276 // If the mask is completely neutral, tell user
1277 if (font == LyXFont(LyXFont::ALL_IGNORE)) {
1278 // Could only happen with user style
1279 bview->owner()->getMiniBuffer()
1280 ->Set(_("No font change defined. Use Character under"
1281 " the Layout menu to define font change."));
1285 // Try implicit word selection
1286 // If there is a change in the language the implicit word selection
1288 LyXCursor resetCursor = cursor;
1289 bool implicitSelection = (font.language() == ignore_language
1290 && font.number() == LyXFont::IGNORE)
1291 ? SelectWordWhenUnderCursor(bview) : false;
1294 SetFont(bview, font, toggleall);
1296 /* Implicit selections are cleared afterwards and cursor is set to the
1297 original position. */
1298 if (implicitSelection) {
1299 ClearSelection(bview);
1300 cursor = resetCursor;
1301 SetCursor(bview, cursor.par(), cursor.pos());
1302 sel_cursor = cursor;
1305 inset_owner->SetUpdateStatus(bview, InsetText::CURSOR_PAR);
1309 LyXParagraph::size_type
1310 LyXText::BeginningOfMainBody(Buffer const * buf,
1311 LyXParagraph const * par) const
1313 if (textclasslist.Style(buf->params.textclass,
1314 par->GetLayout()).labeltype != LABEL_MANUAL)
1317 return par->BeginningOfMainBody();
1322 /* if there is a selection, reset every environment you can find
1323 * in the selection, otherwise just the environment you are in */
1324 void LyXText::MeltFootnoteEnvironment(BufferView * bview)
1326 LyXParagraph * tmppar, * firsttmppar;
1328 ClearSelection(bview);
1330 /* is is only allowed, if the cursor is IN an open footnote.
1331 * Otherwise it is too dangerous */
1332 if (cursor.par()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE)
1335 SetUndo(bview->buffer(), Undo::FINISH,
1336 cursor.par()->PreviousBeforeFootnote()->previous,
1337 cursor.par()->NextAfterFootnote()->next);
1339 /* ok, move to the beginning of the footnote. */
1340 while (cursor.par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
1341 cursor.par(cursor.par()->Previous());
1343 SetCursor(bview, cursor.par(), cursor.par()->Last());
1344 /* this is just faster than using CursorLeft(); */
1346 firsttmppar = cursor.par()->ParFromPos(cursor.pos());
1347 tmppar = firsttmppar;
1348 /* tmppar is now the paragraph right before the footnote */
1350 bool first_footnote_par_is_not_empty = tmppar->next->size();
1353 && tmppar->next->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1354 tmppar = tmppar->next; /* I use next instead of Next(),
1355 * because there cannot be any
1356 * footnotes in a footnote
1358 tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE;
1360 /* remember the captions and empty paragraphs */
1361 if ((textclasslist.Style(bview->buffer()->params.textclass,
1362 tmppar->GetLayout())
1363 .labeltype == LABEL_SENSITIVE)
1365 tmppar->SetLayout(bview->buffer()->params, 0);
1368 // now we will paste the ex-footnote, if the layouts allow it
1369 // first restore the layout of the paragraph right behind
1372 tmppar->next->MakeSameLayout(cursor.par());
1375 if (!tmppar->GetLayout()
1377 && (!tmppar->Next()->Last()
1378 || tmppar->Next()->HasSameLayout(tmppar)))) {
1379 if (tmppar->Next()->Last()
1380 && tmppar->Next()->IsLineSeparator(0))
1381 tmppar->Next()->Erase(0);
1382 tmppar->PasteParagraph(bview->buffer()->params);
1385 tmppar = tmppar->Next(); /* make sure tmppar cannot be touched
1386 * by the pasting of the beginning */
1388 /* then the beginning */
1389 /* if there is no space between the text and the footnote, so we insert
1391 * (only if the previous par and the footnotepar are not empty!) */
1392 if (!firsttmppar->next->GetLayout()
1393 || firsttmppar->HasSameLayout(firsttmppar->next)) {
1394 if (firsttmppar->size()
1395 && !firsttmppar->IsSeparator(firsttmppar->size() - 1)
1396 && first_footnote_par_is_not_empty) {
1397 firsttmppar->next->InsertChar(0, ' ');
1399 firsttmppar->PasteParagraph(bview->buffer()->params);
1402 /* now redo the paragaphs */
1403 RedoParagraphs(bview, cursor, tmppar);
1405 SetCursor(bview, cursor.par(), cursor.pos());
1407 /* sometimes it can happen, that there is a counter change */
1408 Row * row = cursor.row();
1409 while (row->next() && row->par() != tmppar && row->next()->par() != tmppar)
1411 UpdateCounters(bview, row);
1414 ClearSelection(bview);
1419 /* the DTP switches for paragraphs. LyX will store them in the
1420 * first physicla paragraph. When a paragraph is broken, the top settings
1421 * rest, the bottom settings are given to the new one. So I can make shure,
1422 * they do not duplicate themself and you cannnot make dirty things with
1425 void LyXText::SetParagraph(BufferView * bview,
1426 bool line_top, bool line_bottom,
1427 bool pagebreak_top, bool pagebreak_bottom,
1428 VSpace const & space_top,
1429 VSpace const & space_bottom,
1431 string labelwidthstring,
1434 LyXCursor tmpcursor = cursor;
1436 sel_start_cursor = cursor;
1437 sel_end_cursor = cursor;
1440 // make sure that the depth behind the selection are restored, too
1442 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
1444 LyXParagraph * endpar = sel_end_cursor.par()->Next();
1446 LyXParagraph * undoendpar = endpar;
1448 if (endpar && endpar->GetDepth()) {
1449 while (endpar && endpar->GetDepth()) {
1451 endpar = endpar->LastPhysicalPar()->Next();
1453 endpar = endpar->Next();
1455 undoendpar = endpar;
1459 endpar = endpar->Next(); // because of parindents etc.
1462 SetUndo(bview->buffer(), Undo::EDIT,
1465 .par()->ParFromPos(sel_start_cursor.pos())->previous,
1467 sel_start_cursor.par()->previous,
1472 LyXParagraph * tmppar = sel_end_cursor.par();
1474 while (tmppar != sel_start_cursor.par()->FirstPhysicalPar()->Previous()) {
1475 SetCursor(bview, tmppar->FirstPhysicalPar(), 0);
1477 while (tmppar != sel_start_cursor.par()->Previous()) {
1478 SetCursor(bview, tmppar, 0);
1480 status = LyXText::NEED_MORE_REFRESH;
1481 refresh_row = cursor.row();
1482 refresh_y = cursor.y() - cursor.row()->baseline();
1484 if (cursor.par()->footnoteflag ==
1485 sel_start_cursor.par()->footnoteflag) {
1487 cursor.par()->params.lineTop(line_top);
1488 cursor.par()->params.lineBottom(line_bottom);
1489 cursor.par()->params.pagebreakTop(pagebreak_top);
1490 cursor.par()->params.pagebreakBottom(pagebreak_bottom);
1491 cursor.par()->params.spaceTop(space_top);
1492 cursor.par()->params.spaceBottom(space_bottom);
1493 // does the layout allow the new alignment?
1494 if (align == LYX_ALIGN_LAYOUT)
1495 align = textclasslist
1496 .Style(bview->buffer()->params.textclass,
1497 cursor.par()->GetLayout()).align;
1498 if (align & textclasslist
1499 .Style(bview->buffer()->params.textclass,
1500 cursor.par()->GetLayout()).alignpossible) {
1501 if (align == textclasslist
1502 .Style(bview->buffer()->params.textclass,
1503 cursor.par()->GetLayout()).align)
1504 cursor.par()->params.align(LYX_ALIGN_LAYOUT);
1506 cursor.par()->params.align(align);
1508 cursor.par()->SetLabelWidthString(labelwidthstring);
1509 cursor.par()->params.noindent(noindent);
1513 tmppar = cursor.par()->FirstPhysicalPar()->Previous();
1515 tmppar = cursor.par()->Previous();
1519 RedoParagraphs(bview, sel_start_cursor, endpar);
1521 ClearSelection(bview);
1522 SetCursor(bview, sel_start_cursor.par(), sel_start_cursor.pos());
1523 sel_cursor = cursor;
1524 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
1525 SetSelection(bview);
1526 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
1528 bview->updateInset(inset_owner, true);
1532 void LyXText::SetParagraphExtraOpt(BufferView * bview, int type,
1533 string const & width,
1534 string const & widthp,
1535 int alignment, bool hfill,
1536 bool start_minipage)
1538 LyXCursor tmpcursor = cursor;
1539 LyXParagraph * tmppar;
1541 sel_start_cursor = cursor;
1542 sel_end_cursor = cursor;
1545 // make sure that the depth behind the selection are restored, too
1547 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
1549 LyXParagraph * endpar = sel_end_cursor.par()->Next();
1551 LyXParagraph * undoendpar = endpar;
1553 if (endpar && endpar->GetDepth()) {
1554 while (endpar && endpar->GetDepth()) {
1556 endpar = endpar->LastPhysicalPar()->Next();
1558 endpar = endpar->Next();
1560 undoendpar = endpar;
1564 endpar = endpar->Next(); // because of parindents etc.
1567 SetUndo(bview->buffer(), Undo::EDIT,
1570 .par()->ParFromPos(sel_start_cursor.pos())->previous,
1572 sel_start_cursor.par()->previous,
1576 tmppar = sel_end_cursor.par();
1578 while(tmppar != sel_start_cursor.par()->FirstPhysicalPar()->Previous()) {
1579 SetCursor(bview, tmppar->FirstPhysicalPar(), 0);
1581 while(tmppar != sel_start_cursor.par()->Previous()) {
1582 SetCursor(bview, tmppar, 0);
1584 status = LyXText::NEED_MORE_REFRESH;
1585 refresh_row = cursor.row();
1586 refresh_y = cursor.y() - cursor.row()->baseline();
1588 if (cursor.par()->footnoteflag ==
1589 sel_start_cursor.par()->footnoteflag) {
1591 if (type == LyXParagraph::PEXTRA_NONE) {
1592 if (cursor.par()->params.pextraType() != LyXParagraph::PEXTRA_NONE) {
1593 cursor.par()->UnsetPExtraType(bview->buffer()->params);
1594 cursor.par()->params.pextraType(LyXParagraph::PEXTRA_NONE);
1597 cursor.par()->SetPExtraType(bview->buffer()->params,
1598 type, width, widthp);
1599 cursor.par()->params.pextraHfill(hfill);
1600 cursor.par()->params.pextraStartMinipage(start_minipage);
1601 cursor.par()->params.pextraAlignment(alignment);
1605 tmppar = cursor.par()->FirstPhysicalPar()->Previous();
1607 tmppar = cursor.par()->Previous();
1610 RedoParagraphs(bview, sel_start_cursor, endpar);
1611 ClearSelection(bview);
1612 SetCursor(bview, sel_start_cursor.par(), sel_start_cursor.pos());
1613 sel_cursor = cursor;
1614 SetCursor(bview, sel_end_cursor.par(), sel_end_cursor.pos());
1615 SetSelection(bview);
1616 SetCursor(bview, tmpcursor.par(), tmpcursor.pos());
1620 char loweralphaCounter(int n)
1622 if (n < 1 || n > 26)
1630 char alphaCounter(int n)
1632 if (n < 1 || n > 26)
1640 char hebrewCounter(int n)
1642 static const char hebrew[22] = {
1643 'à ', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è',
1644 'é', 'ë', 'ì', 'î', 'ð', 'ñ', 'ò', 'ô', 'ö',
1645 '÷', 'ø', 'ù', 'ú'
1647 if (n < 1 || n > 22)
1655 string const romanCounter(int n)
1657 static char const * roman[20] = {
1658 "i", "ii", "iii", "iv", "v",
1659 "vi", "vii", "viii", "ix", "x",
1660 "xi", "xii", "xiii", "xiv", "xv",
1661 "xvi", "xvii", "xviii", "xix", "xx"
1663 if (n < 1 || n > 20)
1670 // set the counter of a paragraph. This includes the labels
1671 void LyXText::SetCounter(Buffer const * buf, LyXParagraph * par) const
1674 // this is only relevant for the beginning of paragraph
1675 par = par->FirstPhysicalPar();
1677 LyXLayout const & layout =
1678 textclasslist.Style(buf->params.textclass,
1681 LyXTextClass const & textclass =
1682 textclasslist.TextClass(buf->params.textclass);
1684 /* copy the prev-counters to this one, unless this is the start of a
1685 footnote or of a bibliography or the very first paragraph */
1688 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1689 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1690 && par->footnotekind == LyXParagraph::FOOTNOTE)
1692 && !(textclasslist.Style(buf->params.textclass,
1693 par->Previous()->GetLayout()
1694 ).labeltype != LABEL_BIBLIO
1695 && layout.labeltype == LABEL_BIBLIO)) {
1696 for (int i = 0; i < 10; ++i) {
1697 par->setCounter(i, par->Previous()->GetFirstCounter(i));
1700 par->params.appendix(par->Previous()->FirstPhysicalPar()->params.appendix());
1702 par->params.appendix(par->Previous()->params.appendix());
1704 if (!par->params.appendix() && par->params.startOfAppendix()) {
1705 par->params.appendix(true);
1706 for (int i = 0; i < 10; ++i) {
1707 par->setCounter(i, 0);
1711 par->enumdepth = par->Previous()->FirstPhysicalPar()->enumdepth;
1712 par->itemdepth = par->Previous()->FirstPhysicalPar()->itemdepth;
1714 par->enumdepth = par->Previous()->enumdepth;
1715 par->itemdepth = par->Previous()->itemdepth;
1718 for (int i = 0; i < 10; ++i) {
1719 par->setCounter(i, 0);
1721 par->params.appendix(par->params.startOfAppendix());
1727 // if this is an open marginnote and this is the first
1728 // entry in the marginnote and the enclosing
1729 // environment is an enum/item then correct for the
1730 // LaTeX behaviour (ARRae)
1731 if (par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1732 && par->footnotekind == LyXParagraph::MARGIN
1734 && par->Previous()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE
1735 && (par->PreviousBeforeFootnote()
1736 && textclasslist.Style(buf->params.textclass,
1737 par->PreviousBeforeFootnote()->GetLayout()
1738 ).labeltype >= LABEL_COUNTER_ENUMI)) {
1739 // Any itemize or enumerate environment in a marginnote
1740 // that is embedded in an itemize or enumerate
1741 // paragraph is seen by LaTeX as being at a deeper
1742 // level within that enclosing itemization/enumeration
1743 // even if there is a "standard" layout at the start of
1749 /* Maybe we have to increment the enumeration depth.
1750 * BUT, enumeration in a footnote is considered in isolation from its
1751 * surrounding paragraph so don't increment if this is the
1752 * first line of the footnote
1753 * AND, bibliographies can't have their depth changed ie. they
1754 * are always of depth 0
1757 && par->Previous()->GetDepth() < par->GetDepth()
1758 && textclasslist.Style(buf->params.textclass,
1759 par->Previous()->GetLayout()
1760 ).labeltype == LABEL_COUNTER_ENUMI
1761 && par->enumdepth < 3
1763 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1764 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1765 && par->footnotekind == LyXParagraph::FOOTNOTE)
1767 && layout.labeltype != LABEL_BIBLIO) {
1771 /* Maybe we have to decrement the enumeration depth, see note above */
1773 && par->Previous()->GetDepth() > par->GetDepth()
1775 && !(par->Previous()->footnoteflag == LyXParagraph::NO_FOOTNOTE
1776 && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
1777 && par->footnotekind == LyXParagraph::FOOTNOTE)
1779 && layout.labeltype != LABEL_BIBLIO) {
1780 par->enumdepth = par->DepthHook(par->GetDepth())->enumdepth;
1781 par->setCounter(6 + par->enumdepth,
1782 par->DepthHook(par->GetDepth())->getCounter(6 + par->enumdepth));
1783 /* reset the counters.
1784 * A depth change is like a breaking layout
1786 for (int i = 6 + par->enumdepth + 1; i < 10; ++i)
1787 par->setCounter(i, 0);
1790 if (!par->params.labelString().empty()) {
1791 par->params.labelString(string());
1794 if (layout.margintype == MARGIN_MANUAL) {
1795 if (par->params.labelWidthString().empty()) {
1796 par->SetLabelWidthString(layout.labelstring());
1799 par->SetLabelWidthString(string());
1802 /* is it a layout that has an automatic label ? */
1803 if (layout.labeltype >= LABEL_COUNTER_CHAPTER) {
1805 int i = layout.labeltype - LABEL_COUNTER_CHAPTER;
1806 if (i >= 0 && i<= buf->params.secnumdepth) {
1807 par->incCounter(i); // increment the counter
1809 // Is there a label? Useful for Chapter layout
1810 if (!par->params.appendix()) {
1811 if (!layout.labelstring().empty())
1812 par->params.labelString(layout.labelstring());
1814 par->params.labelString(string());
1816 if (!layout.labelstring_appendix().empty())
1817 par->params.labelString(layout.labelstring_appendix());
1819 par->params.labelString(string());
1822 std::ostringstream s;
1824 if (!par->params.appendix()) {
1825 switch (2 * LABEL_COUNTER_CHAPTER -
1826 textclass.maxcounter() + i) {
1827 case LABEL_COUNTER_CHAPTER:
1828 s << par->getCounter(i);
1830 case LABEL_COUNTER_SECTION:
1831 s << par->getCounter(i - 1) << '.'
1832 << par->getCounter(i);
1834 case LABEL_COUNTER_SUBSECTION:
1835 s << par->getCounter(i - 2) << '.'
1836 << par->getCounter(i - 1) << '.'
1837 << par->getCounter(i);
1839 case LABEL_COUNTER_SUBSUBSECTION:
1840 s << par->getCounter(i - 3) << '.'
1841 << par->getCounter(i - 2) << '.'
1842 << par->getCounter(i - 1) << '.'
1843 << par->getCounter(i);
1846 case LABEL_COUNTER_PARAGRAPH:
1847 s << par->getCounter(i - 4) << '.'
1848 << par->getCounter(i - 3) << '.'
1849 << par->getCounter(i - 2) << '.'
1850 << par->getCounter(i - 1) << '.'
1851 << par->getCounter(i);
1853 case LABEL_COUNTER_SUBPARAGRAPH:
1854 s << par->getCounter(i - 5) << '.'
1855 << par->getCounter(i - 4) << '.'
1856 << par->getCounter(i - 3) << '.'
1857 << par->getCounter(i - 2) << '.'
1858 << par->getCounter(i - 1) << '.'
1859 << par->getCounter(i);
1863 // Can this ever be reached? And in the
1864 // case it is, how can this be correct?
1866 s << par->getCounter(i) << '.';
1869 } else { // appendix
1870 switch (2 * LABEL_COUNTER_CHAPTER - textclass.maxcounter() + i) {
1871 case LABEL_COUNTER_CHAPTER:
1872 if (par->isRightToLeftPar(buf->params))
1873 s << hebrewCounter(par->getCounter(i));
1875 s << alphaCounter(par->getCounter(i));
1877 case LABEL_COUNTER_SECTION:
1878 if (par->isRightToLeftPar(buf->params))
1879 s << hebrewCounter(par->getCounter(i - 1));
1881 s << alphaCounter(par->getCounter(i - 1));
1884 << par->getCounter(i);
1887 case LABEL_COUNTER_SUBSECTION:
1888 if (par->isRightToLeftPar(buf->params))
1889 s << hebrewCounter(par->getCounter(i - 2));
1891 s << alphaCounter(par->getCounter(i - 2));
1894 << par->getCounter(i-1) << '.'
1895 << par->getCounter(i);
1898 case LABEL_COUNTER_SUBSUBSECTION:
1899 if (par->isRightToLeftPar(buf->params))
1900 s << hebrewCounter(par->getCounter(i-3));
1902 s << alphaCounter(par->getCounter(i-3));
1905 << par->getCounter(i-2) << '.'
1906 << par->getCounter(i-1) << '.'
1907 << par->getCounter(i);
1910 case LABEL_COUNTER_PARAGRAPH:
1911 if (par->isRightToLeftPar(buf->params))
1912 s << hebrewCounter(par->getCounter(i-4));
1914 s << alphaCounter(par->getCounter(i-4));
1917 << par->getCounter(i-3) << '.'
1918 << par->getCounter(i-2) << '.'
1919 << par->getCounter(i-1) << '.'
1920 << par->getCounter(i);
1923 case LABEL_COUNTER_SUBPARAGRAPH:
1924 if (par->isRightToLeftPar(buf->params))
1925 s << hebrewCounter(par->getCounter(i-5));
1927 s << alphaCounter(par->getCounter(i-5));
1930 << par->getCounter(i-4) << '.'
1931 << par->getCounter(i-3) << '.'
1932 << par->getCounter(i-2) << '.'
1933 << par->getCounter(i-1) << '.'
1934 << par->getCounter(i);
1938 // Can this ever be reached? And in the
1939 // case it is, how can this be correct?
1941 s << par->getCounter(i) << '.';
1947 par->params.labelString(par->params.labelString() +s.str().c_str());
1948 // We really want to remove the c_str as soon as
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 for (i++; i < 10; ++i) {
1957 // reset the following counters
1958 par->setCounter(i, 0);
1960 } else if (layout.labeltype == LABEL_COUNTER_ENUMI) {
1961 par->incCounter(i + par->enumdepth);
1962 int number = par->getCounter(i + par->enumdepth);
1964 std::ostringstream s;
1966 switch (par->enumdepth) {
1968 if (par->isRightToLeftPar(buf->params))
1970 << hebrewCounter(number)
1974 << loweralphaCounter(number)
1978 if (par->isRightToLeftPar(buf->params))
1979 s << '.' << romanCounter(number);
1981 s << romanCounter(number) << '.';
1984 if (par->isRightToLeftPar(buf->params))
1986 << alphaCounter(number);
1988 s << alphaCounter(number)
1992 if (par->isRightToLeftPar(buf->params))
1999 par->params.labelString(s.str().c_str());
2000 // we really want to get rid of that c_str()
2002 for (i += par->enumdepth + 1; i < 10; ++i)
2003 par->setCounter(i, 0); /* reset the following counters */
2006 } else if (layout.labeltype == LABEL_BIBLIO) {// ale970302
2007 int i = LABEL_COUNTER_ENUMI - LABEL_COUNTER_CHAPTER + par->enumdepth;
2009 int number = par->getCounter(i);
2011 InsetCommandParams p( "bibitem" );
2012 par->bibkey = new InsetBibKey(p);
2014 par->bibkey->setCounter(number);
2015 par->params.labelString(layout.labelstring());
2017 // In biblio should't be following counters but...
2019 string s = layout.labelstring();
2021 // the caption hack:
2022 if (layout.labeltype == LABEL_SENSITIVE) {
2023 bool isOK (par->InInset() && par->InInset()->owner() &&
2024 (par->InInset()->owner()->LyxCode() == Inset::FLOAT_CODE));
2026 if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2027 && (par->footnotekind == LyXParagraph::FIG
2028 || par->footnotekind == LyXParagraph::WIDE_FIG)) {
2029 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2030 ? ":øåéà " : "Figure:";
2031 } else if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2032 && (par->footnotekind == LyXParagraph::TAB
2033 || par->footnotekind == LyXParagraph::WIDE_TAB)) {
2034 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2035 ? ":äìáè" : "Table:";
2036 } else if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2037 && par->footnotekind == LyXParagraph::ALGORITHM) {
2038 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2039 ? ":Ãúéøåâìà " : "Algorithm:";
2043 InsetFloat * tmp = static_cast<InsetFloat*>(par->InInset()->owner());
2045 = floatList.getType(tmp->type());
2046 // We should get the correct number here too.
2047 s = fl.name() + " #:";
2049 /* par->SetLayout(0);
2050 s = layout->labelstring; */
2051 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
2052 ? " :úåòîùî øñç" : "Senseless: ";
2055 par->params.labelString(s);
2057 /* reset the enumeration counter. They are always resetted
2058 * when there is any other layout between */
2059 for (int i = 6 + par->enumdepth; i < 10; ++i)
2060 par->setCounter(i, 0);
2065 /* Updates all counters BEHIND the row. Changed paragraphs
2066 * with a dynamic left margin will be rebroken. */
2067 void LyXText::UpdateCounters(BufferView * bview, Row * row) const
2074 if (row->par()->next
2076 && row->par()->next->footnoteflag != LyXParagraph::OPEN_FOOTNOTE
2080 par = row->par()->LastPhysicalPar()->Next();
2082 par = row->par()->Next();
2085 par = row->par()->next;
2090 while (row->par() != par)
2093 SetCounter(bview->buffer(), par);
2095 /* now check for the headline layouts. remember that they
2096 * have a dynamic left margin */
2101 ( textclasslist.Style(bview->buffer()->params.textclass,
2102 par->layout).margintype == MARGIN_DYNAMIC
2103 || textclasslist.Style(bview->buffer()->params.textclass,
2104 par->layout).labeltype == LABEL_SENSITIVE)
2107 /* Rebreak the paragraph */
2108 RemoveParagraph(row);
2109 AppendParagraph(bview, row);
2112 /* think about the damned open footnotes! */
2113 while (par->Next() &&
2114 (par->Next()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
2115 || par->Next()->IsDummy())){
2117 if (par->IsDummy()) {
2118 while (row->par() != par)
2120 RemoveParagraph(row);
2121 AppendParagraph(bview, row);
2127 par = par->LastPhysicalPar()->Next();
2136 /* insets an inset. */
2137 void LyXText::InsertInset(BufferView * bview, Inset * inset)
2139 if (!cursor.par()->InsertInsetAllowed(inset))
2141 SetUndo(bview->buffer(), Undo::INSERT,
2143 cursor.par()->ParFromPos(cursor.pos())->previous,
2144 cursor.par()->ParFromPos(cursor.pos())->next
2146 cursor.par()->previous,
2150 cursor.par()->InsertInset(cursor.pos(), inset);
2151 InsertChar(bview, LyXParagraph::META_INSET); /* just to rebreak and refresh correctly.
2152 * The character will not be inserted a
2155 // If we enter a highly editable inset the cursor should be to before
2156 // the inset. This couldn't happen before as Undo was not handled inside
2157 // inset now after the Undo LyX tries to call inset->Edit(...) again
2158 // and cannot do this as the cursor is behind the inset and GetInset
2159 // does not return the inset!
2160 if (inset->Editable() == Inset::HIGHLY_EDITABLE) {
2161 CursorLeft(bview, true);
2167 void LyXText::copyEnvironmentType()
2169 copylayouttype = cursor.par()->GetLayout();
2173 void LyXText::pasteEnvironmentType(BufferView * bview)
2175 SetLayout(bview, copylayouttype);
2179 void LyXText::CutSelection(BufferView * bview, bool doclear)
2181 // Stuff what we got on the clipboard. Even if there is no selection.
2183 // There is a problem with having the stuffing here in that the
2184 // larger the selection the slower LyX will get. This can be
2185 // solved by running the line below only when the selection has
2186 // finished. The solution used currently just works, to make it
2187 // faster we need to be more clever and probably also have more
2188 // calls to stuffClipboard. (Lgb)
2189 bview->stuffClipboard(selectionAsString(bview->buffer()));
2191 // This doesn't make sense, if there is no selection
2195 // OK, we have a selection. This is always between sel_start_cursor
2196 // and sel_end_cursor
2198 // Check whether there are half footnotes in the selection
2199 if (sel_start_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE
2200 || sel_end_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2201 LyXParagraph * tmppar = sel_start_cursor.par();
2202 while (tmppar != sel_end_cursor.par()){
2203 if (tmppar->footnoteflag != sel_end_cursor.par()->footnoteflag) {
2204 WriteAlert(_("Impossible operation"),
2205 _("Don't know what to do with half floats."),
2209 tmppar = tmppar->Next();
2214 // make sure that the depth behind the selection are restored, too
2216 LyXParagraph * endpar = sel_end_cursor.par()->LastPhysicalPar()->Next();
2218 LyXParagraph * endpar = sel_end_cursor.par()->Next();
2220 LyXParagraph * undoendpar = endpar;
2222 if (endpar && endpar->GetDepth()) {
2223 while (endpar && endpar->GetDepth()) {
2225 endpar = endpar->LastPhysicalPar()->Next();
2227 endpar = endpar->Next();
2229 undoendpar = endpar;
2231 } else if (endpar) {
2232 endpar = endpar->Next(); // because of parindents etc.
2235 SetUndo(bview->buffer(), Undo::DELETE,
2238 .par()->ParFromPos(sel_start_cursor.pos())->previous,
2240 sel_start_cursor.par()->previous,
2246 // there are two cases: cut only within one paragraph or
2247 // more than one paragraph
2249 if (sel_start_cursor.par()->ParFromPos(sel_start_cursor.pos())
2250 == sel_end_cursor.par()->ParFromPos(sel_end_cursor.pos()))
2252 if (sel_start_cursor.par() == sel_end_cursor.par())
2255 // only within one paragraph
2256 endpar = sel_start_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);
2261 sel_end_cursor.pos(pos);
2263 endpar = sel_end_cursor.par();
2265 int pos = sel_end_cursor.pos();
2266 cap.cutSelection(sel_start_cursor.par(), &endpar,
2267 sel_start_cursor.pos(), pos,
2268 bview->buffer()->params.textclass, doclear);
2270 sel_end_cursor.par(endpar);
2271 sel_end_cursor.pos(pos);
2272 cursor.pos(sel_end_cursor.pos());
2274 endpar = endpar->Next();
2276 // sometimes necessary
2278 sel_start_cursor.par()->StripLeadingSpaces(bview->buffer()->params.textclass);
2280 RedoParagraphs(bview, sel_start_cursor, endpar);
2282 ClearSelection(bview);
2283 cursor = sel_start_cursor;
2284 SetCursor(bview, cursor.par(), cursor.pos());
2285 sel_cursor = cursor;
2286 UpdateCounters(bview, cursor.row());
2290 void LyXText::CopySelection(BufferView * bview)
2292 // Stuff what we got on the clipboard. Even if there is no selection.
2294 // There is a problem with having the stuffing here in that the
2295 // larger the selection the slower LyX will get. This can be
2296 // solved by running the line below only when the selection has
2297 // finished. The solution used currently just works, to make it
2298 // faster we need to be more clever and probably also have more
2299 // calls to stuffClipboard. (Lgb)
2300 bview->stuffClipboard(selectionAsString(bview->buffer()));
2302 // this doesnt make sense, if there is no selection
2306 // ok we have a selection. This is always between sel_start_cursor
2307 // and sel_end cursor
2310 /* check wether there are half footnotes in the selection */
2311 if (sel_start_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE
2312 || sel_end_cursor.par()->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
2313 LyXParagraph * tmppar = sel_start_cursor.par();
2314 while (tmppar != sel_end_cursor.par()) {
2315 if (tmppar->footnoteflag !=
2316 sel_end_cursor.par()->footnoteflag) {
2317 WriteAlert(_("Impossible operation"),
2318 _("Don't know what to do"
2319 " with half floats."),
2323 tmppar = tmppar->Next();
2328 // copy behind a space if there is one
2329 while (sel_start_cursor.par()->Last() > sel_start_cursor.pos()
2330 && sel_start_cursor.par()->IsLineSeparator(sel_start_cursor.pos())
2331 && (sel_start_cursor.par() != sel_end_cursor.par()
2332 || sel_start_cursor.pos() < sel_end_cursor.pos()))
2333 sel_start_cursor.pos(sel_start_cursor.pos() + 1);
2337 cap.copySelection(sel_start_cursor.par(), sel_end_cursor.par(),
2338 sel_start_cursor.pos(), sel_end_cursor.pos(),
2339 bview->buffer()->params.textclass);
2343 void LyXText::PasteSelection(BufferView * bview)
2347 // this does not make sense, if there is nothing to paste
2348 if (!cap.checkPastePossible(cursor.par(), cursor.pos()))
2351 SetUndo(bview->buffer(), Undo::INSERT,
2353 cursor.par()->ParFromPos(cursor.pos())->previous,
2354 cursor.par()->ParFromPos(cursor.pos())->next
2356 cursor.par()->previous,
2361 LyXParagraph * endpar;
2362 LyXParagraph * actpar = cursor.par();
2364 int pos = cursor.pos();
2365 cap.pasteSelection(&actpar, &endpar, pos, bview->buffer()->params.textclass);
2367 RedoParagraphs(bview, cursor, endpar);
2369 SetCursor(bview, cursor.par(), cursor.pos());
2370 ClearSelection(bview);
2372 sel_cursor = cursor;
2373 SetCursor(bview, actpar, pos);
2374 SetSelection(bview);
2375 UpdateCounters(bview, cursor.row());
2379 // returns a pointer to the very first LyXParagraph
2380 LyXParagraph * LyXText::FirstParagraph() const
2382 return OwnerParagraph();
2386 // sets the selection over the number of characters of string, no check!!
2387 void LyXText::SetSelectionOverString(BufferView * bview, string const & str)
2389 sel_cursor = cursor;
2390 for (int i = 0; str[i]; ++i)
2392 SetSelection(bview);
2396 // simple replacing. The font of the first selected character is used
2397 void LyXText::ReplaceSelectionWithString(BufferView * bview,
2400 SetCursorParUndo(bview->buffer());
2403 if (!selection) { // create a dummy selection
2404 sel_end_cursor = cursor;
2405 sel_start_cursor = cursor;
2408 // Get font setting before we cut
2409 LyXParagraph::size_type pos = sel_end_cursor.pos();
2410 LyXFont const font = sel_start_cursor.par()
2411 ->GetFontSettings(bview->buffer()->params,
2412 sel_start_cursor.pos());
2414 // Insert the new string
2415 for (string::const_iterator cit = str.begin(); cit != str.end(); ++cit) {
2416 sel_end_cursor.par()->InsertChar(pos, (*cit), font);
2420 // Cut the selection
2421 CutSelection(bview);
2427 // needed to insert the selection
2428 void LyXText::InsertStringA(BufferView * bview, string const & str)
2430 LyXParagraph * par = cursor.par();
2431 LyXParagraph::size_type pos = cursor.pos();
2432 LyXParagraph::size_type a = 0;
2433 LyXParagraph * endpar = cursor.par()->Next();
2435 SetCursorParUndo(bview->buffer());
2438 textclasslist.Style(bview->buffer()->params.textclass,
2439 cursor.par()->GetLayout()).isEnvironment();
2440 // only to be sure, should not be neccessary
2441 ClearSelection(bview);
2443 // insert the string, don't insert doublespace
2444 string::size_type i = 0;
2445 while (i < str.length()) {
2446 if (str[i] != '\n') {
2448 && i + 1 < str.length() && str[i + 1] != ' '
2449 && pos && par->GetChar(pos - 1)!= ' ') {
2450 par->InsertChar(pos, ' ', current_font);
2452 } else if (str[i] == ' ') {
2453 InsetSpecialChar * new_inset =
2454 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2455 if (par->InsertInsetAllowed(new_inset)) {
2456 par->InsertInset(pos, new_inset,
2462 } else if (str[i] == '\t') {
2463 for (a = pos; a < (pos / 8 + 1) * 8 ; ++a) {
2464 InsetSpecialChar * new_inset =
2465 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2466 if (par->InsertInsetAllowed(new_inset)) {
2467 par->InsertInset(pos, new_inset,
2474 } else if (str[i] != 13 &&
2475 // Ignore unprintables
2476 (str[i] & 127) >= ' ') {
2477 par->InsertChar(pos, str[i], current_font);
2481 if (!par->size()) { // par is empty
2482 InsetSpecialChar * new_inset =
2483 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
2484 if (par->InsertInsetAllowed(new_inset)) {
2485 par->InsertInset(pos,
2493 par->BreakParagraph(bview->buffer()->params, pos, flag);
2500 RedoParagraphs(bview, cursor, endpar);
2501 SetCursor(bview, cursor.par(), cursor.pos());
2502 sel_cursor = cursor;
2503 SetCursor(bview, par, pos);
2504 SetSelection(bview);
2508 /* turns double-CR to single CR, others where converted into one blank and 13s
2509 * that are ignored .Double spaces are also converted into one. Spaces at
2510 * the beginning of a paragraph are forbidden. tabs are converted into one
2511 * space. then InsertStringA is called */
2512 void LyXText::InsertStringB(BufferView * bview, string const & s)
2515 string::size_type i = 1;
2516 while (i < str.length()) {
2519 if (str[i] == ' ' && i + 1 < str.length() && str[i + 1] == ' ')
2521 if (str[i] == '\n' && i + 1 < str.length()) {
2522 if (str[i + 1] != '\n') {
2523 if (str[i - 1] != ' ')
2528 while (i + 1 < str.length()
2529 && (str[i + 1] == ' '
2530 || str[i + 1] == '\t'
2531 || str[i + 1] == '\n'
2532 || str[i + 1] == 13)) {
2539 InsertStringA(bview, str);
2543 bool LyXText::GotoNextInset(BufferView * bview,
2544 std::vector<Inset::Code> const & codes,
2545 string const & contents) const
2547 LyXCursor res = cursor;
2550 if (res.pos() < res.par()->Last() - 1) {
2551 res.pos(res.pos() + 1);
2553 res.par(res.par()->Next());
2557 } while (res.par() &&
2558 !(res.par()->GetChar(res.pos()) == LyXParagraph::META_INSET
2559 && (inset = res.par()->GetInset(res.pos())) != 0
2560 && find(codes.begin(), codes.end(), inset->LyxCode())
2562 && (contents.empty() ||
2563 static_cast<InsetCommand *>(res.par()->GetInset(res.pos()))->getContents()
2567 SetCursor(bview, res.par(), res.pos());
2574 void LyXText::CheckParagraph(BufferView * bview, LyXParagraph * par,
2575 LyXParagraph::size_type pos)
2577 LyXCursor tmpcursor;
2580 LyXParagraph::size_type z;
2581 Row * row = GetRow(par, pos, y);
2583 // is there a break one row above
2584 if (row->previous() && row->previous()->par() == row->par()) {
2585 z = NextBreakPoint(bview, row->previous(), workWidth(bview));
2586 if (z >= row->pos()) {
2587 // set the dimensions of the row above
2588 y -= row->previous()->height();
2590 refresh_row = row->previous();
2591 status = LyXText::NEED_MORE_REFRESH;
2593 BreakAgain(bview, row->previous());
2595 // set the cursor again. Otherwise
2596 // dangling pointers are possible
2597 SetCursor(bview, cursor.par(), cursor.pos(),
2598 false, cursor.boundary());
2599 sel_cursor = cursor;
2604 int const tmpheight = row->height();
2605 LyXParagraph::size_type const tmplast = RowLast(row);
2609 BreakAgain(bview, row);
2610 if (row->height() == tmpheight && RowLast(row) == tmplast)
2611 status = LyXText::NEED_VERY_LITTLE_REFRESH;
2613 status = LyXText::NEED_MORE_REFRESH;
2615 // check the special right address boxes
2616 if (textclasslist.Style(bview->buffer()->params.textclass,
2617 par->GetLayout()).margintype
2618 == MARGIN_RIGHT_ADDRESS_BOX) {
2625 RedoDrawingOfParagraph(bview, tmpcursor);
2628 // set the cursor again. Otherwise dangling pointers are possible
2629 // also set the selection
2633 SetCursorIntern(bview, sel_cursor.par(), sel_cursor.pos(),
2634 false, sel_cursor.boundary());
2635 sel_cursor = cursor;
2636 SetCursorIntern(bview, sel_start_cursor.par(),
2637 sel_start_cursor.pos(),
2638 false, sel_start_cursor.boundary());
2639 sel_start_cursor = cursor;
2640 SetCursorIntern(bview, sel_end_cursor.par(),
2641 sel_end_cursor.pos(),
2642 false, sel_end_cursor.boundary());
2643 sel_end_cursor = cursor;
2644 SetCursorIntern(bview, last_sel_cursor.par(),
2645 last_sel_cursor.pos(),
2646 false, last_sel_cursor.boundary());
2647 last_sel_cursor = cursor;
2650 SetCursorIntern(bview, cursor.par(), cursor.pos(),
2651 false, cursor.boundary());
2655 // returns false if inset wasn't found
2656 bool LyXText::UpdateInset(BufferView * bview, Inset * inset)
2658 // first check the current paragraph
2659 int pos = cursor.par()->GetPositionOfInset(inset);
2661 CheckParagraph(bview, cursor.par(), pos);
2665 // check every paragraph
2667 LyXParagraph * par = FirstParagraph();
2670 // make sure the paragraph is open
2671 if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
2673 pos = par->GetPositionOfInset(inset);
2675 CheckParagraph(bview, par, pos);
2688 void LyXText::SetCursor(BufferView * bview, LyXParagraph * par,
2689 LyXParagraph::size_type pos,
2690 bool setfont, bool boundary) const
2692 LyXCursor old_cursor = cursor;
2693 SetCursorIntern(bview, par, pos, setfont, boundary);
2694 DeleteEmptyParagraphMechanism(bview, old_cursor);
2698 void LyXText::SetCursor(BufferView *bview, LyXCursor & cur, LyXParagraph * par,
2699 LyXParagraph::size_type pos, bool boundary) const
2702 // correct the cursor position if impossible
2703 if (pos > par->Last()){
2704 LyXParagraph * tmppar = par->ParFromPos(pos);
2705 pos = par->PositionInParFromPos(pos);
2708 if (par->IsDummy() && par->previous &&
2709 par->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
2710 while (par->previous &&
2711 ((par->previous->IsDummy() &&
2712 (par->previous->previous->footnoteflag ==
2713 LyXParagraph::CLOSED_FOOTNOTE)) ||
2714 (par->previous->footnoteflag ==
2715 LyXParagraph::CLOSED_FOOTNOTE))) {
2716 par = par->previous ;
2717 if (par->IsDummy() &&
2718 (par->previous->footnoteflag ==
2719 LyXParagraph::CLOSED_FOOTNOTE))
2720 pos += par->size() + 1;
2722 if (par->previous) {
2723 par = par->previous;
2725 pos += par->size() + 1;
2730 cur.boundary(boundary);
2732 /* get the cursor y position in text */
2734 Row * row = GetRow(par, pos, y);
2735 /* y is now the beginning of the cursor row */
2736 y += row->baseline();
2737 /* y is now the cursor baseline */
2740 /* now get the cursors x position */
2742 float fill_separator, fill_hfill, fill_label_hfill;
2743 PrepareToPrint(bview, row, x, fill_separator, fill_hfill,
2745 LyXParagraph::size_type cursor_vpos = 0;
2746 LyXParagraph::size_type last = RowLastPrintable(row);
2748 if (pos > last + 1) // This shouldn't happen.
2750 else if (pos < row->pos())
2753 if (last < row->pos())
2754 cursor_vpos = row->pos();
2755 else if (pos > last && !boundary)
2756 cursor_vpos = (row->par()->isRightToLeftPar(bview->buffer()->params))
2757 ? row->pos() : last + 1;
2758 else if (pos > row->pos() &&
2759 (pos > last || boundary))
2760 /// Place cursor after char at (logical) position pos - 1
2761 cursor_vpos = (bidi_level(pos - 1) % 2 == 0)
2762 ? log2vis(pos - 1) + 1 : log2vis(pos - 1);
2764 /// Place cursor before char at (logical) position pos
2765 cursor_vpos = (bidi_level(pos) % 2 == 0)
2766 ? log2vis(pos) : log2vis(pos) + 1;
2768 LyXParagraph::size_type main_body =
2769 BeginningOfMainBody(bview->buffer(), row->par());
2770 if ((main_body > 0) &&
2771 ((main_body-1 > last) ||
2772 !row->par()->IsLineSeparator(main_body-1)))
2775 for (LyXParagraph::size_type vpos = row->pos();
2776 vpos < cursor_vpos; ++vpos) {
2777 pos = vis2log(vpos);
2778 if (main_body > 0 && pos == main_body - 1) {
2779 x += fill_label_hfill +
2780 lyxfont::width(textclasslist.Style(
2781 bview->buffer()->params.textclass,
2782 row->par()->GetLayout())
2784 GetFont(bview->buffer(), row->par(), -2));
2785 if (row->par()->IsLineSeparator(main_body-1))
2786 x -= SingleWidth(bview, row->par(),main_body-1);
2788 if (HfillExpansion(bview->buffer(), row, pos)) {
2789 x += SingleWidth(bview, row->par(), pos);
2790 if (pos >= main_body)
2793 x += fill_label_hfill;
2794 } else if (row->par()->IsSeparator(pos)) {
2795 x += SingleWidth(bview, row->par(), pos);
2796 if (pos >= main_body)
2797 x += fill_separator;
2799 x += SingleWidth(bview, row->par(), pos);
2808 void LyXText::SetCursorIntern(BufferView * bview, LyXParagraph * par,
2809 LyXParagraph::size_type pos,
2810 bool setfont, bool boundary) const
2812 SetCursor(bview, cursor, par, pos, boundary);
2814 SetCurrentFont(bview);
2818 void LyXText::SetCurrentFont(BufferView * bview) const
2820 LyXParagraph::size_type pos = cursor.pos();
2821 if (cursor.boundary() && pos > 0)
2825 if (pos == cursor.par()->Last())
2827 else if (cursor.par()->IsSeparator(pos)) {
2828 if (pos > cursor.row()->pos() &&
2829 bidi_level(pos) % 2 ==
2830 bidi_level(pos - 1) % 2)
2832 else if (pos + 1 < cursor.par()->Last())
2838 cursor.par()->GetFontSettings(bview->buffer()->params, pos);
2839 real_current_font = GetFont(bview->buffer(), cursor.par(), pos);
2841 if (cursor.pos() == cursor.par()->Last() &&
2842 IsBoundary(bview->buffer(), cursor.par(), cursor.pos()) &&
2843 !cursor.boundary()) {
2844 Language const * lang =
2845 cursor.par()->getParLanguage(bview->buffer()->params);
2846 current_font.setLanguage(lang);
2847 current_font.setNumber(LyXFont::OFF);
2848 real_current_font.setLanguage(lang);
2849 real_current_font.setNumber(LyXFont::OFF);
2854 void LyXText::SetCursorFromCoordinates(BufferView * bview, int x, int y) const
2856 LyXCursor old_cursor = cursor;
2858 /* get the row first */
2860 Row * row = GetRowNearY(y);
2861 cursor.par(row->par());
2864 int column = GetColumnNearX(bview, row, x, bound);
2865 cursor.pos(row->pos() + column);
2867 cursor.y(y + row->baseline());
2869 cursor.boundary(bound);
2870 SetCurrentFont(bview);
2871 DeleteEmptyParagraphMechanism(bview, old_cursor);
2875 void LyXText::SetCursorFromCoordinates(BufferView * bview, LyXCursor & cur,
2878 /* get the row first */
2880 Row * row = GetRowNearY(y);
2882 int column = GetColumnNearX(bview, row, x, bound);
2884 cur.par(row->par());
2885 cur.pos(row->pos() + column);
2887 cur.y(y + row->baseline());
2889 cur.boundary(bound);
2893 void LyXText::CursorLeft(BufferView * bview, bool internal) const
2895 if (cursor.pos() > 0) {
2896 bool boundary = cursor.boundary();
2897 SetCursor(bview, cursor.par(), cursor.pos() - 1, true, false);
2898 if (!internal && !boundary &&
2899 IsBoundary(bview->buffer(), cursor.par(), cursor.pos() + 1))
2900 SetCursor(bview, cursor.par(), cursor.pos() + 1, true, true);
2901 } else if (cursor.par()->Previous()) { // steps into the above paragraph.
2902 LyXParagraph * par = cursor.par()->Previous();
2903 SetCursor(bview, par, par->Last());
2908 void LyXText::CursorRight(BufferView * bview, bool internal) const
2910 if (!internal && cursor.boundary() &&
2911 !cursor.par()->IsNewline(cursor.pos()))
2912 SetCursor(bview, cursor.par(), cursor.pos(), true, false);
2913 else if (cursor.pos() < cursor.par()->Last()) {
2914 SetCursor(bview, cursor.par(), cursor.pos() + 1, true, false);
2916 IsBoundary(bview->buffer(), cursor.par(), cursor.pos()))
2917 SetCursor(bview, cursor.par(), cursor.pos(), true, true);
2918 } else if (cursor.par()->Next())
2919 SetCursor(bview, cursor.par()->Next(), 0);
2923 void LyXText::CursorUp(BufferView * bview) const
2925 SetCursorFromCoordinates(bview, cursor.x_fix(),
2926 cursor.y() - cursor.row()->baseline() - 1);
2930 void LyXText::CursorDown(BufferView * bview) const
2932 SetCursorFromCoordinates(bview, cursor.x_fix(),
2933 cursor.y() - cursor.row()->baseline()
2934 + cursor.row()->height() + 1);
2938 void LyXText::CursorUpParagraph(BufferView * bview) const
2940 if (cursor.pos() > 0) {
2941 SetCursor(bview, cursor.par(), 0);
2943 else if (cursor.par()->Previous()) {
2944 SetCursor(bview, cursor.par()->Previous(), 0);
2949 void LyXText::CursorDownParagraph(BufferView * bview) const
2951 if (cursor.par()->Next()) {
2952 SetCursor(bview, cursor.par()->Next(), 0);
2954 SetCursor(bview, cursor.par(), cursor.par()->Last());
2959 void LyXText::DeleteEmptyParagraphMechanism(BufferView * bview,
2960 LyXCursor const & old_cursor) const
2962 // Would be wrong to delete anything if we have a selection.
2963 if (selection) return;
2965 // We allow all kinds of "mumbo-jumbo" when freespacing.
2966 if (textclasslist.Style(bview->buffer()->params.textclass,
2967 old_cursor.par()->GetLayout()).free_spacing)
2970 bool deleted = false;
2972 /* Ok I'll put some comments here about what is missing.
2973 I have fixed BackSpace (and thus Delete) to not delete
2974 double-spaces automagically. I have also changed Cut,
2975 Copy and Paste to hopefully do some sensible things.
2976 There are still some small problems that can lead to
2977 double spaces stored in the document file or space at
2978 the beginning of paragraphs. This happens if you have
2979 the cursor betwenn to spaces and then save. Or if you
2980 cut and paste and the selection have a space at the
2981 beginning and then save right after the paste. I am
2982 sure none of these are very hard to fix, but I will
2983 put out 1.1.4pre2 with FIX_DOUBLE_SPACE defined so
2984 that I can get some feedback. (Lgb)
2987 // If old_cursor.pos() == 0 and old_cursor.pos()(1) == LineSeparator
2988 // delete the LineSeparator.
2991 // If old_cursor.pos() == 1 and old_cursor.pos()(0) == LineSeparator
2992 // delete the LineSeparator.
2995 // If the pos around the old_cursor were spaces, delete one of them.
2996 if (old_cursor.par() != cursor.par() || old_cursor.pos() != cursor.pos()) {
2997 // Only if the cursor has really moved
2999 if (old_cursor.pos() > 0
3000 && old_cursor.pos() < old_cursor.par()->Last()
3001 && old_cursor.par()->IsLineSeparator(old_cursor.pos())
3002 && old_cursor.par()->IsLineSeparator(old_cursor.pos() - 1)) {
3003 old_cursor.par()->Erase(old_cursor.pos() - 1);
3004 RedoParagraphs(bview, old_cursor, old_cursor.par()->Next());
3006 if (old_cursor.par() == cursor.par() &&
3007 cursor.pos() > old_cursor.pos()) {
3008 SetCursorIntern(bview, cursor.par(),
3011 SetCursorIntern(bview, cursor.par(),
3017 // Do not delete empty paragraphs with keepempty set.
3018 if ((textclasslist.Style(bview->buffer()->params.textclass,
3019 old_cursor.par()->GetLayout())).keepempty)
3022 LyXCursor tmpcursor;
3024 if (old_cursor.par() != cursor.par()) {
3025 if ((old_cursor.par()->Last() == 0
3026 || (old_cursor.par()->Last() == 1
3027 && old_cursor.par()->IsLineSeparator(0)))
3029 && old_cursor.par()->FirstPhysicalPar()
3030 == old_cursor.par()->LastPhysicalPar()
3033 // ok, we will delete anything
3035 // make sure that you do not delete any environments
3038 old_cursor.par()->footnoteflag != LyXParagraph::OPEN_FOOTNOTE &&
3039 !(old_cursor.row()->previous()
3040 && old_cursor.row()->previous()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
3041 && !(old_cursor.row()->next()
3042 && old_cursor.row()->next()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE))
3043 || (old_cursor.par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE
3044 && ((old_cursor.row()->previous()
3045 && old_cursor.row()->previous()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE)
3046 || (old_cursor.row()->next()
3047 && old_cursor.row()->next()->par()->footnoteflag == LyXParagraph::OPEN_FOOTNOTE))
3050 status = LyXText::NEED_MORE_REFRESH;
3053 if (old_cursor.row()->previous()) {
3054 refresh_row = old_cursor.row()->previous();
3055 refresh_y = old_cursor.y() - old_cursor.row()->baseline() - refresh_row->height();
3057 cursor = old_cursor; // that undo can restore the right cursor position
3058 LyXParagraph * endpar = old_cursor.par()->next;
3059 if (endpar && endpar->GetDepth()) {
3060 while (endpar && endpar->GetDepth()) {
3062 endpar = endpar->LastPhysicalPar()->Next();
3064 endpar = endpar->Next();
3068 SetUndo(bview->buffer(), Undo::DELETE,
3069 old_cursor.par()->previous,
3074 RemoveRow(old_cursor.row());
3075 if (OwnerParagraph() == old_cursor.par()) {
3076 OwnerParagraph(OwnerParagraph()->next);
3079 delete old_cursor.par();
3081 /* Breakagain the next par. Needed
3082 * because of the parindent that
3083 * can occur or dissappear. The
3084 * next row can change its height,
3085 * if there is another layout before */
3086 if (refresh_row->next()) {
3087 BreakAgain(bview, refresh_row->next());
3088 UpdateCounters(bview, refresh_row);
3090 SetHeightOfRow(bview, refresh_row);
3092 refresh_row = old_cursor.row()->next();
3093 refresh_y = old_cursor.y() - old_cursor.row()->baseline();
3096 cursor = old_cursor; // that undo can restore the right cursor position
3097 LyXParagraph * endpar = old_cursor.par()->next;
3098 if (endpar && endpar->GetDepth()) {
3099 while (endpar && endpar->GetDepth()) {
3101 endpar = endpar->LastPhysicalPar()->Next();
3103 endpar = endpar->Next();
3107 SetUndo(bview->buffer(), Undo::DELETE,
3108 old_cursor.par()->previous,
3113 RemoveRow(old_cursor.row());
3115 if (OwnerParagraph() == old_cursor.par()) {
3116 OwnerParagraph(OwnerParagraph()->next);
3118 delete old_cursor.par();
3120 /* Breakagain the next par. Needed
3121 because of the parindent that can
3122 occur or dissappear.
3123 The next row can change its height,
3124 if there is another layout before
3127 BreakAgain(bview, refresh_row);
3128 UpdateCounters(bview, refresh_row->previous());
3134 SetCursorIntern(bview, cursor.par(), cursor.pos());
3136 if (sel_cursor.par() == old_cursor.par()
3137 && sel_cursor.pos() == sel_cursor.pos()) {
3138 // correct selection
3139 sel_cursor = cursor;
3146 if (old_cursor.par()->StripLeadingSpaces(bview->buffer()->params.textclass)) {
3147 RedoParagraphs(bview, old_cursor, old_cursor.par()->Next());
3149 SetCursorIntern(bview, cursor.par(), cursor.pos());
3150 sel_cursor = cursor;
3157 LyXParagraph * LyXText::GetParFromID(int id)
3159 LyXParagraph * result = FirstParagraph();
3160 while (result && result->id() != id)
3161 result = result->next;
3167 bool LyXText::TextUndo(BufferView * bview)
3171 // returns false if no undo possible
3172 Undo * undo = bview->buffer()->undostack.pop();
3176 bview->buffer()->redostack
3177 .push(CreateUndo(bview->buffer(), undo->kind,
3178 GetParFromID(undo->number_of_before_par),
3179 GetParFromID(undo->number_of_behind_par)));
3181 return TextHandleUndo(bview, undo);
3185 bool LyXText::TextRedo(BufferView * bview)
3189 // returns false if no redo possible
3190 Undo * undo = bview->buffer()->redostack.pop();
3194 bview->buffer()->undostack
3195 .push(CreateUndo(bview->buffer(), undo->kind,
3196 GetParFromID(undo->number_of_before_par),
3197 GetParFromID(undo->number_of_behind_par)));
3199 return TextHandleUndo(bview, undo);
3203 bool LyXText::TextHandleUndo(BufferView * bview, Undo * undo)
3207 // returns false if no undo possible
3208 bool result = false;
3210 LyXParagraph * before =
3211 GetParFromID(undo->number_of_before_par);
3212 LyXParagraph * behind =
3213 GetParFromID(undo->number_of_behind_par);
3214 LyXParagraph * tmppar;
3215 LyXParagraph * tmppar2;
3216 LyXParagraph * endpar;
3217 LyXParagraph * tmppar5;
3219 // if there's no before take the beginning
3220 // of the document for redoing
3222 SetCursorIntern(bview, FirstParagraph(), 0);
3224 // replace the paragraphs with the undo informations
3226 LyXParagraph * tmppar3 = undo->par;
3227 undo->par = 0; // otherwise the undo destructor would delete the paragraph
3228 LyXParagraph * tmppar4 = tmppar3;
3230 while (tmppar4->next)
3231 tmppar4 = tmppar4->next;
3232 } // get last undo par
3234 // now remove the old text if there is any
3235 if (before != behind || (!behind && !before)){
3237 tmppar5 = before->next;
3239 tmppar5 = OwnerParagraph();
3241 while (tmppar5 && tmppar5 != behind){
3243 tmppar5 = tmppar5->next;
3244 // a memory optimization for edit: Only layout information
3245 // is stored in the undo. So restore the text informations.
3246 if (undo->kind == Undo::EDIT) {
3247 tmppar2->setContentsFromPar(tmppar);
3248 tmppar->clearContents();
3249 tmppar2 = tmppar2->next;
3254 // put the new stuff in the list if there is one
3257 before->next = tmppar3;
3259 OwnerParagraph(tmppar3);
3260 tmppar3->previous = before;
3263 OwnerParagraph(behind);
3266 tmppar4->next = behind;
3268 behind->previous = tmppar4;
3272 // Set the cursor for redoing
3275 SetCursorIntern(bview, before->FirstSelfrowPar(), 0);
3277 SetCursorIntern(bview, before, 0);
3280 // check wether before points to a closed float and open it if necessary
3281 if (before && before->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE
3282 && before->next && before->next->footnoteflag != LyXParagraph::NO_FOOTNOTE){
3284 while (tmppar4->previous &&
3285 tmppar4->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
3286 tmppar4 = tmppar4->previous;
3287 while (tmppar4 && tmppar4->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3288 tmppar4->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
3289 tmppar4 = tmppar4->next;
3296 // open a cosed footnote at the end if necessary
3297 if (behind && behind->previous &&
3298 behind->previous->footnoteflag != LyXParagraph::NO_FOOTNOTE &&
3299 behind->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3300 while (behind && behind->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE){
3301 behind->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
3302 behind = behind->next;
3307 // calculate the endpar for redoing the paragraphs.
3310 if (behind->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE)
3311 endpar = behind->LastPhysicalPar()->Next();
3313 endpar = behind->NextAfterFootnote()->LastPhysicalPar()->Next();
3315 endpar = behind->Next();
3320 tmppar = GetParFromID(undo->number_of_cursor_par);
3321 RedoParagraphs(bview, cursor, endpar);
3323 SetCursorIntern(bview, tmppar, undo->cursor_pos);
3324 UpdateCounters(bview, cursor.row());
3334 void LyXText::FinishUndo()
3338 // makes sure the next operation will be stored
3339 undo_finished = true;
3343 void LyXText::FreezeUndo()
3347 // this is dangerous and for internal use only
3352 void LyXText::UnFreezeUndo()
3356 // this is dangerous and for internal use only
3357 undo_frozen = false;
3361 void LyXText::SetUndo(Buffer * buf, Undo::undo_kind kind,
3362 LyXParagraph const * before,
3363 LyXParagraph const * behind) const
3368 buf->undostack.push(CreateUndo(buf, kind, before, behind));
3369 buf->redostack.clear();
3373 void LyXText::SetRedo(Buffer * buf, Undo::undo_kind kind,
3374 LyXParagraph const * before, LyXParagraph const * behind)
3378 buf->redostack.push(CreateUndo(buf, kind, before, behind));
3382 Undo * LyXText::CreateUndo(Buffer * buf, Undo::undo_kind kind,
3383 LyXParagraph const * before,
3384 LyXParagraph const * behind) const
3389 int before_number = -1;
3390 int behind_number = -1;
3392 before_number = before->id();
3394 behind_number = behind->id();
3395 // Undo::EDIT and Undo::FINISH are
3396 // always finished. (no overlapping there)
3397 // overlapping only with insert and delete inside one paragraph:
3398 // Nobody wants all removed character
3399 // appear one by one when undoing.
3400 // EDIT is special since only layout information, not the
3401 // contents of a paragaph are stored.
3402 if (!undo_finished && (kind != Undo::EDIT) && (kind != Undo::FINISH)){
3403 // check wether storing is needed
3404 if (!buf->undostack.empty() &&
3405 buf->undostack.top()->kind == kind &&
3406 buf->undostack.top()->number_of_before_par == before_number &&
3407 buf->undostack.top()->number_of_behind_par == behind_number ){
3412 // create a new Undo
3413 LyXParagraph * undopar;
3414 LyXParagraph * tmppar;
3415 LyXParagraph * tmppar2;
3417 LyXParagraph * start = 0;
3418 LyXParagraph * end = 0;
3421 start = before->next;
3423 start = FirstParagraph();
3425 end = behind->previous;
3427 end = FirstParagraph();
3432 if (start && end && (start != end->next) &&
3433 ((before != behind) || (!before && !behind)))
3436 tmppar2 = tmppar->Clone();
3437 tmppar2->id(tmppar->id());
3439 // a memory optimization: Just store the layout information
3441 if (kind == Undo::EDIT){
3442 //tmppar2->text.clear();
3443 tmppar2->clearContents();
3448 while (tmppar != end && tmppar->next) {
3449 tmppar = tmppar->next;
3450 tmppar2->next = tmppar->Clone();
3451 tmppar2->next->id(tmppar->id());
3452 // a memory optimization: Just store the layout
3453 // information when only edit
3454 if (kind == Undo::EDIT){
3455 //tmppar2->next->text.clear();
3456 tmppar2->clearContents();
3458 tmppar2->next->previous = tmppar2;
3459 tmppar2 = tmppar2->next;
3463 undopar = 0; // nothing to replace (undo of delete maybe)
3466 int cursor_par = cursor.par()->ParFromPos(cursor.pos())->id();
3467 int cursor_pos = cursor.par()->PositionInParFromPos(cursor.pos());
3469 int cursor_par = cursor.par()->id();
3470 int cursor_pos = cursor.pos();
3473 Undo * undo = new Undo(kind,
3474 before_number, behind_number,
3475 cursor_par, cursor_pos,
3478 undo_finished = false;
3483 void LyXText::SetCursorParUndo(Buffer * buf)
3487 SetUndo(buf, Undo::FINISH,
3489 cursor.par()->ParFromPos(cursor.pos())->previous,
3490 cursor.par()->ParFromPos(cursor.pos())->next
3492 cursor.par()->previous,
3499 void LyXText::toggleAppendix(BufferView * bview)
3502 LyXParagraph * par = cursor.par()->FirstPhysicalPar();
3504 LyXParagraph * par = cursor.par();
3506 bool start = !par->params.startOfAppendix();
3508 // ensure that we have only one start_of_appendix in this document
3509 LyXParagraph * tmp = FirstParagraph();
3510 for (; tmp; tmp = tmp->next)
3511 tmp->params.startOfAppendix(false);
3512 par->params.startOfAppendix(start);
3514 // we can set the refreshing parameters now
3515 status = LyXText::NEED_MORE_REFRESH;
3517 refresh_row = 0; // not needed for full update
3518 UpdateCounters(bview, 0);
3519 SetCursor(bview, cursor.par(), cursor.pos());
3523 LyXParagraph * LyXText::OwnerParagraph() const
3526 return inset_owner->par;
3528 return bv_owner->buffer()->paragraph;
3532 LyXParagraph * LyXText::OwnerParagraph(LyXParagraph * p) const
3535 inset_owner->par = p;
3537 bv_owner->buffer()->paragraph = p;