]> git.lyx.org Git - lyx.git/blob - src/text2.C
471a65be75f117113a32f860b7f472397c35baf7
[lyx.git] / src / text2.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *       
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2001 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #include FORMS_H_LOCATION
14
15
16 #ifdef __GNUG__
17 #pragma implementation "lyxtext.h"
18 #endif
19
20 #include "lyxtext.h"
21 #include "LString.h"
22 #include "paragraph.h"
23 #include "insets/inseterror.h"
24 #include "insets/insetbib.h"
25 #include "insets/insetspecialchar.h"
26 #include "insets/insettext.h"
27 #include "insets/insetfloat.h"
28 #include "layout.h"
29 #include "LyXView.h"
30 #include "support/textutils.h"
31 #include "undo.h"
32 #include "buffer.h"
33 #include "bufferparams.h"
34 #include "lyx_gui_misc.h"
35 #include "gettext.h"
36 #include "BufferView.h"
37 #include "LyXView.h"
38 #include "CutAndPaste.h"
39 #include "Painter.h"
40 #include "font.h"
41 #include "debug.h"
42 #include "lyxrc.h"
43 #include "FloatList.h"
44 #include "language.h"
45 #include "ParagraphParameters.h"
46
47 using std::copy;
48 using std::find;
49 using std::endl;
50 using std::find;
51 using std::pair;
52
53
54 LyXText::LyXText(BufferView * bv)
55 {
56         bv_owner = bv;
57         inset_owner = 0;
58         init();
59 }
60
61
62 LyXText::LyXText(InsetText * inset)
63 {
64         inset_owner = inset;
65         bv_owner = 0;
66         init();
67 }
68
69
70 void LyXText::init()
71 {
72         the_locking_inset = 0;
73         firstrow = 0;
74         lastrow = 0;
75         number_of_rows = 0;
76         refresh_y = 0;
77         height = 0;
78         width = 0;
79         first = 0;
80         status = LyXText::UNCHANGED;
81
82         // set cursor at the very top position
83         selection.set(true);        /* these setting is necessary 
84                                        because of the delete-empty-
85                                        paragraph mechanism in
86                                        SetCursor */
87         if (bv_owner) {
88                 Paragraph * par = ownerParagraph();
89                 current_font = getFont(bv_owner->buffer(), par, 0);
90                 while (par) {
91                         insertParagraph(bv_owner, par, lastrow);
92                         par = par->next();
93                 }
94                 setCursor(bv_owner, firstrow->par(), 0);
95         } else
96                 current_font = LyXFont(LyXFont::ALL_SANE);
97
98         selection.cursor = cursor;
99         selection.set(false);
100         selection.mark(false);
101         
102         // no rebreak necessary
103         need_break_row = 0;
104    
105         undo_finished = true;
106         undo_frozen = false;
107
108         // Default layouttype for copy environment type
109         copylayouttype = 0;
110
111 #if 0
112         // Dump all rowinformation:
113         Row * tmprow = firstrow;
114         lyxerr << "Baseline Paragraph Pos Height Ascent Fill\n";
115         while (tmprow) {
116                 lyxerr << tmprow->baseline() << '\t'
117                        << tmprow->par << '\t'
118                        << tmprow->pos() << '\t'
119                        << tmprow->height << '\t'
120                        << tmprow->ascent_of_text << '\t'
121                        << tmprow->fill << '\n';
122                 tmprow = tmprow->next();
123         }
124         lyxerr.flush();
125 #endif
126 }
127
128
129 void LyXText::init(BufferView * bview)
130 {
131         if (firstrow)
132                 return;
133
134         Paragraph * par = ownerParagraph();
135         current_font = getFont(bview->buffer(), par, 0);
136         while (par) {
137                 insertParagraph(bview, par, lastrow);
138                 par = par->next();
139         }
140         setCursorIntern(bview, firstrow->par(), 0);
141         selection.cursor = cursor;
142 #if 0
143         printf("TP = %x\n",inset_owner->owner());
144         // Dump all rowinformation:
145         Row * tmprow = firstrow;
146         lyxerr << "Width = " << width << endl;
147         lyxerr << "Baseline Paragraph Pos Height Ascent Fill\n";
148         while (tmprow) {
149                 lyxerr << tmprow->baseline() << '\t'
150                        << tmprow->par() << '\t'
151                        << tmprow->pos() << '\t'
152                        << tmprow->height() << '\t'
153                        << tmprow->ascent_of_text() << '\t'
154                        << tmprow->fill() << '\n';
155                 tmprow = tmprow->next();
156         }
157         lyxerr.flush();
158 #endif
159 }
160
161 LyXText::~LyXText()
162 {
163         // Delete all rows, this does not touch the paragraphs!
164         Row * tmprow = firstrow;
165         while (firstrow) {
166                 tmprow = firstrow->next();
167                 delete firstrow;
168                 firstrow = tmprow;
169         }
170 }
171
172
173 // Gets the fully instantiated font at a given position in a paragraph
174 // Basically the same routine as Paragraph::getFont() in paragraph.C.
175 // The difference is that this one is used for displaying, and thus we
176 // are allowed to make cosmetic improvements. For instance make footnotes
177 // smaller. (Asger)
178 // If position is -1, we get the layout font of the paragraph.
179 // If position is -2, we get the font of the manual label of the paragraph.
180 LyXFont const LyXText::getFont(Buffer const * buf, Paragraph * par,
181                          Paragraph::size_type pos) const
182 {
183         LyXLayout const & layout = 
184                 textclasslist.Style(buf->params.textclass, par->getLayout());
185
186         Paragraph::depth_type par_depth = par->getDepth();
187         // We specialize the 95% common case:
188         if (!par_depth) {
189                 if (pos >= 0){
190                         // 95% goes here
191                         if (layout.labeltype == LABEL_MANUAL
192                             && pos < beginningOfMainBody(buf, par)) {
193                                 // 1% goes here
194                                 LyXFont f = par->getFontSettings(buf->params,
195                                                                  pos);
196                                 return f.realize(layout.reslabelfont);
197                         } else {
198                                 LyXFont f = par->getFontSettings(buf->params, pos);
199                                 return f.realize(layout.resfont);
200                         }
201                         
202                 } else {
203                         // 5% goes here.
204                         // process layoutfont for pos == -1 and labelfont for pos < -1
205                         if (pos == -1)
206                                 return layout.resfont;
207                         else
208                                 return layout.reslabelfont;
209                 }
210         }
211
212         // The uncommon case need not be optimized as much
213
214         LyXFont layoutfont, tmpfont;
215
216         if (pos >= 0){
217                 // 95% goes here
218                 if (pos < beginningOfMainBody(buf, par)) {
219                         // 1% goes here
220                         layoutfont = layout.labelfont;
221                 } else {
222                         // 99% goes here
223                         layoutfont = layout.font;
224                 }
225                 tmpfont = par->getFontSettings(buf->params, pos);
226                 tmpfont.realize(layoutfont);
227         } else {
228                 // 5% goes here.
229                 // process layoutfont for pos == -1 and labelfont for pos < -1
230                 if (pos == -1)
231                         tmpfont = layout.font;
232                 else
233                         tmpfont = layout.labelfont;
234         }
235
236         // Resolve against environment font information
237         while (par && par_depth && !tmpfont.resolved()) {
238                 par = par->outerHook();
239                 if (par) {
240                         tmpfont.realize(textclasslist.
241                                         Style(buf->params.textclass,
242                                               par->getLayout()).font);
243                         par_depth = par->getDepth();
244                 }
245         }
246
247         tmpfont.realize(textclasslist.TextClass(buf->params.textclass).defaultfont());
248
249         return tmpfont;
250 }
251
252
253 void LyXText::setCharFont(BufferView * bv, Paragraph * par,
254                           Paragraph::size_type pos, LyXFont const & fnt,
255                           bool toggleall)
256 {
257         Buffer const * buf = bv->buffer();
258         LyXFont font = getFont(buf, par, pos);
259         font.update(fnt, buf->params.language, toggleall);
260         // Let the insets convert their font
261         if (par->getChar(pos) == Paragraph::META_INSET) {
262                 Inset * inset = par->getInset(pos);
263                 if (inset) {
264                         if (inset->editable()==Inset::HIGHLY_EDITABLE) {
265                                 UpdatableInset * uinset = static_cast<UpdatableInset *>(inset);
266                                 uinset->setFont(bv, fnt, toggleall, true);
267                         }
268                         font = inset->convertFont(font);
269                 }
270         }
271
272         LyXLayout const & layout =
273                 textclasslist.Style(buf->params.textclass,
274                                     par->getLayout());
275
276         // Get concrete layout font to reduce against
277         LyXFont layoutfont;
278
279         if (pos < beginningOfMainBody(buf, par))
280                 layoutfont = layout.labelfont;
281         else
282                 layoutfont = layout.font;
283
284         // Realize against environment font information
285         if (par->getDepth()){
286                 Paragraph * tp = par;
287                 while (!layoutfont.resolved() && tp && tp->getDepth()) {
288                         tp = tp->outerHook();
289                         if (tp)
290                                 layoutfont.realize(textclasslist.
291                                                 Style(buf->params.textclass,
292                                                       tp->getLayout()).font);
293                 }
294         }
295
296         layoutfont.realize(textclasslist.TextClass(buf->params.textclass).defaultfont());
297
298         // Now, reduce font against full layout font
299         font.reduce(layoutfont);
300
301         par->setFont(pos, font);
302 }
303
304 void LyXText::setCharFont(Buffer const * buf, Paragraph * par,
305                           Paragraph::size_type pos, LyXFont const & fnt)
306 {
307         LyXFont font(fnt);
308         // Let the insets convert their font
309         if (par->getChar(pos) == Paragraph::META_INSET) {
310                 font = par->getInset(pos)->convertFont(font);
311         }
312
313         LyXLayout const & layout =
314                 textclasslist.Style(buf->params.textclass,
315                                     par->getLayout());
316
317         // Get concrete layout font to reduce against
318         LyXFont layoutfont;
319
320         if (pos < beginningOfMainBody(buf, par))
321                 layoutfont = layout.labelfont;
322         else
323                 layoutfont = layout.font;
324
325         // Realize against environment font information
326         if (par->getDepth()){
327                 Paragraph * tp = par;
328                 while (!layoutfont.resolved() && tp && tp->getDepth()) {
329                         tp = tp->outerHook();
330                         if (tp)
331                                 layoutfont.realize(textclasslist.
332                                                 Style(buf->params.textclass,
333                                                       tp->getLayout()).font);
334                 }
335         }
336
337         layoutfont.realize(textclasslist.TextClass(buf->params.textclass).defaultfont());
338
339         // Now, reduce font against full layout font
340         font.reduce(layoutfont);
341
342         par->setFont(pos, font);
343 }
344
345
346 /* inserts a new row behind the specified row, increments
347  * the touched counters */
348 void LyXText::insertRow(Row * row, Paragraph * par,
349                         Paragraph::size_type pos) const
350 {
351         Row * tmprow = new Row;
352         if (!row) {
353                 tmprow->previous(0);
354                 tmprow->next(firstrow);
355                 firstrow = tmprow;
356         } else {
357                 tmprow->previous(row);
358                 tmprow->next(row->next());
359                 row->next(tmprow);
360         }
361    
362         if (tmprow->next())
363                 tmprow->next()->previous(tmprow);
364    
365         if (tmprow->previous())
366                 tmprow->previous()->next(tmprow);
367    
368    
369         tmprow->par(par);
370         tmprow->pos(pos);
371
372         if (row == lastrow)
373                 lastrow = tmprow;
374         ++number_of_rows; // one more row
375 }
376
377
378 // removes the row and reset the touched counters
379 void LyXText::removeRow(Row * row) const
380 {
381         /* this must not happen before the currentrow for clear reasons.
382            so the trick is just to set the current row onto the previous
383            row of this row */
384         int unused_y;
385         getRow(row->par(), row->pos(), unused_y);
386    
387         if (row->next())
388                 row->next()->previous(row->previous());
389         if (!row->previous()) {
390                 firstrow = row->next();
391         } else  {
392                 row->previous()->next(row->next());
393         }
394         if (row == lastrow)
395                 lastrow = row->previous();
396    
397         height -= row->height(); // the text becomes smaller
398    
399         delete row;
400         --number_of_rows;       // one row less
401 }
402
403
404 // remove all following rows of the paragraph of the specified row.
405 void LyXText::removeParagraph(Row * row) const
406 {
407         Paragraph * tmppar = row->par();
408         row = row->next();
409     
410         Row * tmprow;
411         while (row && row->par() == tmppar) {
412                 tmprow = row->next();
413                 removeRow(row);
414                 row = tmprow;
415         }
416 }
417    
418
419 // insert the specified paragraph behind the specified row
420 void LyXText::insertParagraph(BufferView * bview, Paragraph * par,
421                               Row * row) const
422 {
423         insertRow(row, par, 0);        /* insert a new row, starting 
424                                         * at postition 0 */
425
426         setCounter(bview->buffer(), par);  // set the counters
427    
428         // and now append the whole paragraph behind the new row
429         if (!row) {
430                 firstrow->height(0);
431                 appendParagraph(bview, firstrow);
432         } else {
433                 row->next()->height(0);
434                 appendParagraph(bview, row->next());
435         }
436 }
437
438
439 /* used in setlayout */
440 // Asger is not sure we want to do this...
441 void LyXText::makeFontEntriesLayoutSpecific(Buffer const * buf,
442                                             Paragraph * par)
443 {
444    
445         LyXLayout const & layout =
446                 textclasslist.Style(buf->params.textclass, par->getLayout());
447
448         LyXFont layoutfont, tmpfont;
449         for (Paragraph::size_type pos = 0;
450              pos < par->size(); ++pos) {
451                 if (pos < beginningOfMainBody(buf, par))
452                         layoutfont = layout.labelfont;
453                 else
454                         layoutfont = layout.font;
455       
456                 tmpfont = par->getFontSettings(buf->params, pos);
457                 tmpfont.reduce(layoutfont);
458                 par->setFont(pos, tmpfont);
459         }
460 }
461
462
463 Paragraph * LyXText::setLayout(BufferView * bview,
464                                   LyXCursor & cur, LyXCursor & sstart_cur,
465                                   LyXCursor & send_cur,
466                                   LyXTextClass::size_type layout)
467 {
468         Paragraph * endpar = send_cur.par()->next();
469         Paragraph * undoendpar = endpar;
470         
471         if (endpar && endpar->getDepth()) {
472                 while (endpar && endpar->getDepth()) {
473                         endpar = endpar->next();
474                         undoendpar = endpar;
475                 }
476         } else if (endpar) {
477                 endpar = endpar->next(); // because of parindents etc.
478         }
479         
480         setUndo(bview->buffer(), Undo::EDIT,
481                 sstart_cur.par()->previous(),
482                 undoendpar);
483         
484         /* ok we have a selection. This is always between sstart_cur
485          * and sel_end cursor */ 
486         cur = sstart_cur;
487         
488         LyXLayout const & lyxlayout =
489                 textclasslist.Style(bview->buffer()->params.textclass, layout);
490         
491         while (cur.par() != send_cur.par()) {
492                 cur.par()->setLayout(layout);
493                 makeFontEntriesLayoutSpecific(bview->buffer(), cur.par());
494                 Paragraph * fppar = cur.par();
495                 fppar->params().spaceTop(lyxlayout.fill_top ?
496                                        VSpace(VSpace::VFILL)
497                                        : VSpace(VSpace::NONE));
498                 fppar->params().spaceBottom(lyxlayout.fill_bottom ? 
499                                           VSpace(VSpace::VFILL)
500                                           : VSpace(VSpace::NONE));
501                 if (lyxlayout.margintype == MARGIN_MANUAL)
502                         cur.par()->setLabelWidthString(lyxlayout.labelstring());
503                 if (lyxlayout.labeltype != LABEL_BIBLIO
504                     && fppar->bibkey) {
505                         delete fppar->bibkey;
506                         fppar->bibkey = 0;
507                 }
508                 cur.par(cur.par()->next());
509         }
510         cur.par()->setLayout(layout);
511         makeFontEntriesLayoutSpecific(bview->buffer(), cur.par());
512         Paragraph * fppar = cur.par();
513         fppar->params().spaceTop(lyxlayout.fill_top ?
514                                VSpace(VSpace::VFILL) : VSpace(VSpace::NONE));
515         fppar->params().spaceBottom(lyxlayout.fill_bottom ? 
516                                   VSpace(VSpace::VFILL) : VSpace(VSpace::NONE));
517         if (lyxlayout.margintype == MARGIN_MANUAL)
518                 cur.par()->setLabelWidthString(lyxlayout.labelstring());
519         if (lyxlayout.labeltype != LABEL_BIBLIO
520             && fppar->bibkey) {
521                 delete fppar->bibkey;
522                 fppar->bibkey = 0;
523         }
524         return endpar;
525 }
526
527
528 // set layout over selection and make a total rebreak of those paragraphs
529 void LyXText::setLayout(BufferView * bview, LyXTextClass::size_type layout)
530 {
531         LyXCursor tmpcursor = cursor;  /* store the current cursor  */
532
533         // if there is no selection just set the layout
534         // of the current paragraph  */
535         if (!selection.set()) {
536                 selection.start = cursor;  // dummy selection
537                 selection.end = cursor;
538         }
539         Paragraph * endpar = setLayout(bview, cursor, selection.start,
540                                           selection.end, layout);
541         redoParagraphs(bview, selection.start, endpar);
542    
543         // we have to reset the selection, because the
544         // geometry could have changed
545         setCursor(bview, selection.start.par(),
546                   selection.start.pos(), false);
547         selection.cursor = cursor;
548         setCursor(bview, selection.end.par(), selection.end.pos(),
549                   false);
550         updateCounters(bview, cursor.row());
551         clearSelection(bview);
552         setSelection(bview);
553         setCursor(bview, tmpcursor.par(), tmpcursor.pos(), true);
554 }
555
556
557 // increment depth over selection and
558 // make a total rebreak of those paragraphs
559 void  LyXText::incDepth(BufferView * bview)
560 {
561         // If there is no selection, just use the current paragraph
562         if (!selection.set()) {
563                 selection.start = cursor; // dummy selection
564                 selection.end = cursor;
565         }
566
567         // We end at the next paragraph with depth 0
568         Paragraph * endpar = selection.end.par()->next();
569
570         Paragraph * undoendpar = endpar;
571
572         if (endpar && endpar->getDepth()) {
573                 while (endpar && endpar->getDepth()) {
574                         endpar = endpar->next();
575                         undoendpar = endpar;
576                 }
577         }
578         else if (endpar) {
579                 endpar = endpar->next(); // because of parindents etc.
580         }
581         
582         setUndo(bview->buffer(), Undo::EDIT,
583                 selection.start.par()->previous(),
584                 undoendpar);
585
586         LyXCursor tmpcursor = cursor; // store the current cursor
587
588         // ok we have a selection. This is always between sel_start_cursor
589         // and sel_end cursor
590         cursor = selection.start;
591    
592         bool anything_changed = false;
593    
594         while (true) {
595                 // NOTE: you can't change the depth of a bibliography entry
596                 if (
597                     textclasslist.Style(bview->buffer()->params.textclass,
598                                       cursor.par()->getLayout()
599                                      ).labeltype != LABEL_BIBLIO) {
600                         Paragraph * prev = cursor.par()->previous();
601
602                         if (prev 
603                             && (prev->getDepth() - cursor.par()->getDepth() > 0
604                                 || (prev->getDepth() == cursor.par()->getDepth()
605                                     && textclasslist.Style(bview->buffer()->params.textclass,
606                                                       prev->getLayout()).isEnvironment()))) {
607                                 cursor.par()->params().depth(cursor.par()->params().depth() + 1);
608                                 anything_changed = true;
609                                 }
610                 }
611                 if (cursor.par() == selection.end.par())
612                        break;
613                 cursor.par(cursor.par()->next());
614         }
615    
616         // if nothing changed set all depth to 0
617         if (!anything_changed) {
618                 cursor = selection.start;
619                 while (cursor.par() != selection.end.par()) {
620                         cursor.par()->params().depth(0);
621                         cursor.par(cursor.par()->next());
622                 }
623                 cursor.par()->params().depth(0);
624         }
625    
626         redoParagraphs(bview, selection.start, endpar);
627    
628         // we have to reset the selection, because the
629         // geometry could have changed
630         setCursor(bview, selection.start.par(), selection.start.pos());
631         selection.cursor = cursor;
632         setCursor(bview, selection.end.par(), selection.end.pos());
633         updateCounters(bview, cursor.row());
634         clearSelection(bview);
635         setSelection(bview);
636         setCursor(bview, tmpcursor.par(), tmpcursor.pos());
637 }
638
639
640 // decrement depth over selection and
641 // make a total rebreak of those paragraphs
642 void  LyXText::decDepth(BufferView * bview)
643 {
644         // if there is no selection just set the layout
645         // of the current paragraph
646         if (!selection.set()) {
647                 selection.start = cursor; // dummy selection
648                 selection.end = cursor;
649         }
650         Paragraph * endpar = selection.end.par()->next();
651         Paragraph * undoendpar = endpar;
652
653         if (endpar && endpar->getDepth()) {
654                 while (endpar && endpar->getDepth()) {
655                         endpar = endpar->next();
656                         undoendpar = endpar;
657                 }
658         } else if (endpar) {
659                 endpar = endpar->next(); // because of parindents etc.
660         }
661    
662         setUndo(bview->buffer(), Undo::EDIT,
663                 selection.start.par()->previous(),
664                 undoendpar);
665
666         LyXCursor tmpcursor = cursor; // store the current cursor
667
668         // ok we have a selection. This is always between sel_start_cursor
669         // and sel_end cursor
670         cursor = selection.start;
671
672         while (true) {
673                 if (cursor.par()->params().depth())
674                         cursor.par()->params().depth(cursor.par()->params().depth() - 1);
675                 if (cursor.par() == selection.end.par())
676                         break;
677                 cursor.par(cursor.par()->next());
678         }
679
680         redoParagraphs(bview, selection.start, endpar);
681    
682         // we have to reset the selection, because the
683         // geometry could have changed
684         setCursor(bview, selection.start.par(),
685                   selection.start.pos());
686         selection.cursor = cursor;
687         setCursor(bview, selection.end.par(), selection.end.pos());
688         updateCounters(bview, cursor.row());
689         clearSelection(bview);
690         setSelection(bview);
691         setCursor(bview, tmpcursor.par(), tmpcursor.pos());
692 }
693
694
695 // set font over selection and make a total rebreak of those paragraphs
696 void LyXText::setFont(BufferView * bview, LyXFont const & font, bool toggleall)
697 {
698         // if there is no selection just set the current_font
699         if (!selection.set()) {
700                 // Determine basis font
701                 LyXFont layoutfont;
702                 if (cursor.pos() < beginningOfMainBody(bview->buffer(),
703                                                        cursor.par()))
704                         layoutfont = getFont(bview->buffer(), cursor.par(),-2);
705                 else
706                         layoutfont = getFont(bview->buffer(), cursor.par(),-1);
707                 // Update current font
708                 real_current_font.update(font,
709                                          bview->buffer()->params.language,
710                                          toggleall);
711
712                 // Reduce to implicit settings
713                 current_font = real_current_font;
714                 current_font.reduce(layoutfont);
715                 // And resolve it completely
716                 real_current_font.realize(layoutfont);
717                 return;
718         }
719
720         LyXCursor tmpcursor = cursor; // store the current cursor
721    
722         // ok we have a selection. This is always between sel_start_cursor
723         // and sel_end cursor
724    
725         setUndo(bview->buffer(), Undo::EDIT,
726                 selection.start.par()->previous(),
727                 selection.end.par()->next()); 
728         freezeUndo();
729         cursor = selection.start;
730         while (cursor.par() != selection.end.par() ||
731                (cursor.pos() < selection.end.pos())) {
732                 if (cursor.pos() < cursor.par()->size()) {
733                         // an open footnote should behave
734                         // like a closed one
735                         setCharFont(bview, cursor.par(), cursor.pos(), font, toggleall);
736                         cursor.pos(cursor.pos() + 1);
737                 } else {
738                         cursor.pos(0);
739                         cursor.par(cursor.par()->next());
740                 }
741         }
742         unFreezeUndo();
743    
744         redoParagraphs(bview, selection.start, selection.end.par()->next());
745    
746         // we have to reset the selection, because the
747         // geometry could have changed
748         setCursor(bview, selection.start.par(), selection.start.pos());
749         selection.cursor = cursor;
750         setCursor(bview, selection.end.par(), selection.end.pos());
751         clearSelection(bview);
752         setSelection(bview);
753         setCursor(bview, tmpcursor.par(), tmpcursor.pos(), true,
754                   tmpcursor.boundary());
755 }
756
757
758 void LyXText::redoHeightOfParagraph(BufferView * bview, LyXCursor const & cur)
759 {
760         Row * tmprow = cur.row();
761         int y = cur.y() - tmprow->baseline();
762
763         setHeightOfRow(bview, tmprow);
764         Paragraph * first_phys_par = tmprow->par();
765
766         // find the first row of the paragraph
767         if (first_phys_par != tmprow->par())
768                 while (tmprow->previous()
769                        && tmprow->previous()->par() != first_phys_par) {
770                         tmprow = tmprow->previous();
771                         y -= tmprow->height();
772                         setHeightOfRow(bview, tmprow);
773                 }
774         while (tmprow->previous() && tmprow->previous()->par() == first_phys_par) {
775                 tmprow = tmprow->previous();
776                 y -= tmprow->height();
777                 setHeightOfRow(bview, tmprow);
778         }
779         
780         // we can set the refreshing parameters now
781         status = LyXText::NEED_MORE_REFRESH;
782         refresh_y = y;
783         refresh_row = tmprow;
784         setCursor(bview, cur.par(), cur.pos(), false, cursor.boundary());
785 }
786
787
788 void LyXText::redoDrawingOfParagraph(BufferView * bview, LyXCursor const & cur)
789 {
790         Row * tmprow = cur.row();
791    
792         int y = cur.y() - tmprow->baseline();
793         setHeightOfRow(bview, tmprow);
794         Paragraph * first_phys_par = tmprow->par();
795
796         // find the first row of the paragraph
797         if (first_phys_par != tmprow->par())
798                 while (tmprow->previous() && tmprow->previous()->par() != first_phys_par)  {
799                         tmprow = tmprow->previous();
800                         y -= tmprow->height();
801                 }
802         while (tmprow->previous() && tmprow->previous()->par() == first_phys_par)  {
803                 tmprow = tmprow->previous();
804                 y -= tmprow->height();
805         }
806    
807         // we can set the refreshing parameters now
808         if (status == LyXText::UNCHANGED || y < refresh_y) {
809                 refresh_y = y;
810                 refresh_row = tmprow;
811         }
812         status = LyXText::NEED_MORE_REFRESH;
813         setCursor(bview, cur.par(), cur.pos());
814 }
815
816
817 /* deletes and inserts again all paragaphs between the cursor
818 * and the specified par 
819 * This function is needed after SetLayout and SetFont etc. */
820 void LyXText::redoParagraphs(BufferView * bview, LyXCursor const & cur,
821                              Paragraph const * endpar) const
822 {
823         Row * tmprow2;
824         Paragraph * tmppar = 0, * first_phys_par = 0;
825    
826         Row * tmprow = cur.row();
827    
828         int y = cur.y() - tmprow->baseline();
829    
830         if (!tmprow->previous()){
831                 first_phys_par = firstParagraph();   // a trick/hack for UNDO
832         } else {
833                 first_phys_par = tmprow->par();
834                 // find the first row of the paragraph
835                 if (first_phys_par != tmprow->par())
836                         while (tmprow->previous() &&
837                                (tmprow->previous()->par() != first_phys_par)) {
838                                 tmprow = tmprow->previous();
839                                 y -= tmprow->height();
840                         }
841                 while (tmprow->previous()
842                        && tmprow->previous()->par() == first_phys_par) {
843                         tmprow = tmprow->previous();
844                         y -= tmprow->height();
845                 }
846         }
847    
848         // we can set the refreshing parameters now
849         status = LyXText::NEED_MORE_REFRESH;
850         refresh_y = y;
851         refresh_row = tmprow->previous();        /* the real refresh row will
852                                             be deleted, so I store
853                                             the previous here */ 
854         // remove it
855         if (tmprow->next())
856                 tmppar = tmprow->next()->par();
857         else
858                 tmppar = 0;
859         while (tmppar != endpar) {
860                 removeRow(tmprow->next());
861                 if (tmprow->next())
862                         tmppar = tmprow->next()->par();
863                 else
864                         tmppar = 0;
865         }  
866    
867         // remove the first one
868         tmprow2 = tmprow;     /* this is because tmprow->previous()
869                                  can be 0 */
870         tmprow = tmprow->previous();
871         removeRow(tmprow2);
872    
873         tmppar = first_phys_par;
874
875         do {
876                 if (tmppar) {
877                         insertParagraph(bview, tmppar, tmprow);
878                         if (!tmprow)
879                                 tmprow = firstrow;
880                         while (tmprow->next() && tmprow->next()->par() == tmppar)
881                                 tmprow = tmprow->next();
882                         tmppar = tmppar->next();
883                 }
884         } while (tmppar != endpar);
885    
886         // this is because of layout changes
887         if (refresh_row) {
888                 refresh_y -= refresh_row->height();
889                 setHeightOfRow(bview, refresh_row);   
890         } else {
891                 refresh_row = firstrow;
892                 refresh_y = 0;
893                 setHeightOfRow(bview, refresh_row);   
894         }
895    
896         if (tmprow && tmprow->next())
897                 setHeightOfRow(bview, tmprow->next());
898 }
899
900
901 bool LyXText::fullRebreak(BufferView * bview)
902 {
903         if (!firstrow) {
904                 init(bview);
905                 return true;
906         }
907         if (need_break_row) {
908                 breakAgain(bview, need_break_row);
909                 need_break_row = 0;
910                 return true;
911         }
912         return false;
913 }
914
915
916 /* important for the screen */
917
918
919 /* the cursor set functions have a special mechanism. When they
920  * realize, that you left an empty paragraph, they will delete it.
921  * They also delete the corresponding row */
922    
923 // need the selection cursor:
924 void LyXText::setSelection(BufferView * bview)
925 {
926         bool const lsel = selection.set();
927
928         if (!selection.set()) {
929                 last_sel_cursor = selection.cursor;
930                 selection.start = selection.cursor;
931                 selection.end = selection.cursor;
932         }
933    
934         selection.set(true);
935    
936         // first the toggling area
937         if (cursor.y() < last_sel_cursor.y()
938             || (cursor.y() == last_sel_cursor.y()
939              && cursor.x() < last_sel_cursor.x())) {
940                 toggle_end_cursor = last_sel_cursor;
941                 toggle_cursor = cursor;
942         } else {
943                 toggle_end_cursor = cursor;
944                 toggle_cursor = last_sel_cursor;
945         }
946    
947         last_sel_cursor = cursor;
948    
949         // and now the whole selection
950
951         if (selection.cursor.par() == cursor.par())
952            if (selection.cursor.pos() < cursor.pos()) {
953                 selection.end = cursor;
954                 selection.start = selection.cursor;
955         } else {
956                 selection.end = selection.cursor; 
957                 selection.start = cursor;
958         }
959         else if (selection.cursor.y() < cursor.y() ||
960             (selection.cursor.y() == cursor.y() && selection.cursor.x() < cursor.x())) {
961                 selection.end = cursor;
962                 selection.start = selection.cursor;
963         }
964         else {
965                 selection.end = selection.cursor; 
966                 selection.start = cursor;
967         }
968    
969         // a selection with no contents is not a selection
970         if (selection.start.par() == selection.end.par() && 
971             selection.start.pos() == selection.end.pos())
972                 selection.set(false);
973
974         if (inset_owner && (selection.set() || lsel))
975                 inset_owner->setUpdateStatus(bview, InsetText::SELECTION);
976 }
977
978
979 string const LyXText::selectionAsString(Buffer const * buffer) const
980 {
981         if (!selection.set()) return string();
982         string result;
983         
984         // Special handling if the whole selection is within one paragraph
985         if (selection.start.par() == selection.end.par()) {
986                 result += selection.start.par()->asString(buffer,
987                                                          selection.start.pos(),
988                                                          selection.end.pos());
989                 return result;
990         }
991         
992         // The selection spans more than one paragraph
993
994         // First paragraph in selection
995         result += selection.start.par()->asString(buffer,
996                                                  selection.start.pos(),
997                                                  selection.start.par()->size())
998                 + "\n\n";
999         
1000         // The paragraphs in between (if any)
1001         LyXCursor tmpcur(selection.start);
1002         tmpcur.par(tmpcur.par()->next());
1003         while (tmpcur.par() != selection.end.par()) {
1004                 result += tmpcur.par()->asString(buffer, 0, tmpcur.par()->size()) + "\n\n";
1005                 tmpcur.par(tmpcur.par()->next()); // Or NextAfterFootnote??
1006         }
1007
1008         // Last paragraph in selection
1009         result += selection.end.par()->asString(buffer, 0, selection.end.pos());
1010         
1011         return result;
1012 }
1013
1014
1015 void LyXText::clearSelection(BufferView * /*bview*/) const
1016 {
1017         selection.set(false);
1018         selection.mark(false);
1019         selection.end = selection.start = cursor;
1020 }
1021
1022
1023 void LyXText::cursorHome(BufferView * bview) const
1024 {
1025         setCursor(bview, cursor.par(), cursor.row()->pos());
1026 }
1027
1028
1029 void LyXText::cursorEnd(BufferView * bview) const
1030 {
1031         if (!cursor.row()->next() || cursor.row()->next()->par() != cursor.row()->par())
1032                 setCursor(bview, cursor.par(), rowLast(cursor.row()) + 1);
1033         else {
1034                 if (cursor.par()->size() &&
1035                     (cursor.par()->getChar(rowLast(cursor.row())) == ' '
1036                      || cursor.par()->isNewline(rowLast(cursor.row()))))
1037                         setCursor(bview, cursor.par(), rowLast(cursor.row()));
1038                 else
1039                         setCursor(bview,cursor.par(), rowLast(cursor.row()) + 1);
1040         }
1041 }
1042
1043
1044 void LyXText::cursorTop(BufferView * bview) const
1045 {
1046         while (cursor.par()->previous())
1047                 cursor.par(cursor.par()->previous());
1048         setCursor(bview, cursor.par(), 0);
1049 }
1050
1051
1052 void LyXText::cursorBottom(BufferView * bview) const
1053 {
1054         while (cursor.par()->next())
1055                 cursor.par(cursor.par()->next());
1056         setCursor(bview, cursor.par(), cursor.par()->size());
1057 }
1058    
1059    
1060 void LyXText::toggleFree(BufferView * bview,
1061                          LyXFont const & font, bool toggleall)
1062 {
1063         // If the mask is completely neutral, tell user
1064         if (font == LyXFont(LyXFont::ALL_IGNORE)) {
1065                 // Could only happen with user style
1066                 bview->owner()->message(_("No font change defined. Use Character under the Layout menu to define font change."));
1067                 return;
1068         }
1069
1070         // Try implicit word selection
1071         // If there is a change in the language the implicit word selection 
1072         // is disabled.
1073         LyXCursor resetCursor = cursor;
1074         bool implicitSelection = (font.language() == ignore_language
1075                                   && font.number() == LyXFont::IGNORE)
1076                 ? selectWordWhenUnderCursor(bview) : false;
1077
1078         // Set font
1079         setFont(bview, font, toggleall);
1080
1081         /* Implicit selections are cleared afterwards and cursor is set to the
1082            original position. */
1083         if (implicitSelection) {
1084                 clearSelection(bview);
1085                 cursor = resetCursor;
1086                 setCursor(bview, cursor.par(), cursor.pos());
1087                 selection.cursor = cursor;
1088         }
1089         if (inset_owner)
1090                 inset_owner->setUpdateStatus(bview, InsetText::CURSOR_PAR);
1091 }
1092
1093
1094 Paragraph::size_type
1095 LyXText::beginningOfMainBody(Buffer const * buf,
1096                              Paragraph const * par) const
1097 {
1098         if (textclasslist.Style(buf->params.textclass,
1099                                 par->getLayout()).labeltype != LABEL_MANUAL)
1100                 return 0;
1101         else
1102                 return par->beginningOfMainBody();
1103 }
1104
1105
1106 /* the DTP switches for paragraphs. LyX will store them in the 
1107 * first physicla paragraph. When a paragraph is broken, the top settings 
1108 * rest, the bottom settings are given to the new one. So I can make shure, 
1109 * they do not duplicate themself and you cannnot make dirty things with 
1110 * them!  */ 
1111
1112 void LyXText::setParagraph(BufferView * bview,
1113                            bool line_top, bool line_bottom,
1114                            bool pagebreak_top, bool pagebreak_bottom,
1115                            VSpace const & space_top,
1116                            VSpace const & space_bottom,
1117                            LyXAlignment align, 
1118                            string labelwidthstring,
1119                            bool noindent) 
1120 {
1121         LyXCursor tmpcursor = cursor;
1122         if (!selection.set()) {
1123                 selection.start = cursor;
1124                 selection.end = cursor;
1125         }
1126
1127         // make sure that the depth behind the selection are restored, too
1128         Paragraph * endpar = selection.end.par()->next();
1129         Paragraph * undoendpar = endpar;
1130
1131         if (endpar && endpar->getDepth()) {
1132                 while (endpar && endpar->getDepth()) {
1133                         endpar = endpar->next();
1134                         undoendpar = endpar;
1135                 }
1136         }
1137         else if (endpar) {
1138                 endpar = endpar->next(); // because of parindents etc.
1139         }
1140    
1141         setUndo(bview->buffer(), Undo::EDIT,
1142                 selection.start.par()->previous(),
1143                 undoendpar);
1144
1145         
1146         Paragraph * tmppar = selection.end.par();
1147         while (tmppar != selection.start.par()->previous()) {
1148                 setCursor(bview, tmppar, 0);
1149                 status = LyXText::NEED_MORE_REFRESH;
1150                 refresh_row = cursor.row();
1151                 refresh_y = cursor.y() - cursor.row()->baseline();
1152                         cursor.par()->params().lineTop(line_top);
1153                         cursor.par()->params().lineBottom(line_bottom);
1154                         cursor.par()->params().pagebreakTop(pagebreak_top);
1155                         cursor.par()->params().pagebreakBottom(pagebreak_bottom);
1156                         cursor.par()->params().spaceTop(space_top);
1157                         cursor.par()->params().spaceBottom(space_bottom);
1158                         // does the layout allow the new alignment?
1159                         if (align == LYX_ALIGN_LAYOUT)
1160                                 align = textclasslist
1161                                         .Style(bview->buffer()->params.textclass,
1162                                                cursor.par()->getLayout()).align;
1163                         if (align & textclasslist
1164                             .Style(bview->buffer()->params.textclass,
1165                                    cursor.par()->getLayout()).alignpossible) {
1166                                 if (align == textclasslist
1167                                     .Style(bview->buffer()->params.textclass,
1168                                            cursor.par()->getLayout()).align)
1169                                         cursor.par()->params().align(LYX_ALIGN_LAYOUT);
1170                                 else
1171                                         cursor.par()->params().align(align);
1172                         }
1173                         cursor.par()->setLabelWidthString(labelwidthstring);
1174                         cursor.par()->params().noindent(noindent);
1175                 tmppar = cursor.par()->previous();
1176         }
1177         
1178         redoParagraphs(bview, selection.start, endpar);
1179         
1180         clearSelection(bview);
1181         setCursor(bview, selection.start.par(), selection.start.pos());
1182         selection.cursor = cursor;
1183         setCursor(bview, selection.end.par(), selection.end.pos());
1184         setSelection(bview);
1185         setCursor(bview, tmpcursor.par(), tmpcursor.pos());
1186         if (inset_owner)
1187             bview->updateInset(inset_owner, true);
1188 }
1189
1190
1191 char loweralphaCounter(int n)
1192 {
1193         if (n < 1 || n > 26)
1194                 return '?';
1195         else
1196                 return 'a' + n - 1;
1197 }
1198
1199
1200 namespace {
1201
1202 inline
1203 char alphaCounter(int n)
1204 {
1205         if (n < 1 || n > 26)
1206                 return '?';
1207         else
1208                 return 'A' + n - 1;
1209 }
1210
1211
1212 inline
1213 char hebrewCounter(int n)
1214 {
1215         static const char hebrew[22] = {
1216                 'à', 'á', 'â', 'ã', 'ä', 'Ã¥', 'æ', 'ç', 'è',
1217                 'é', 'ë', 'ì', 'î', 'ð', 'ñ', 'ò', 'ô', 'ö', 
1218                 '÷', 'ø', 'ù', 'ú'
1219         };
1220         if (n < 1 || n > 22)
1221                 return '?';
1222         else
1223                 return hebrew[n-1];
1224 }
1225
1226
1227 inline
1228 string const romanCounter(int n)
1229 {
1230         static char const * roman[20] = {
1231                 "i",   "ii",  "iii", "iv", "v",
1232                 "vi",  "vii", "viii", "ix", "x",
1233                 "xi",  "xii", "xiii", "xiv", "xv",
1234                 "xvi", "xvii", "xviii", "xix", "xx"
1235         };
1236         if (n < 1 || n > 20)
1237                 return "??";
1238         else
1239                 return roman[n-1];
1240 }
1241
1242 } // namespace anon
1243
1244
1245 // set the counter of a paragraph. This includes the labels
1246 void LyXText::setCounter(Buffer const * buf, Paragraph * par) const
1247 {
1248         LyXLayout const & layout =
1249                 textclasslist.Style(buf->params.textclass, 
1250                                     par->getLayout());
1251
1252         LyXTextClass const & textclass =
1253                 textclasslist.TextClass(buf->params.textclass);
1254
1255         /* copy the prev-counters to this one, unless this is the start of a 
1256            footnote or of a bibliography or the very first paragraph */
1257         if (par->previous()
1258             && !(textclasslist.Style(buf->params.textclass,
1259                                 par->previous()->getLayout()
1260                                 ).labeltype != LABEL_BIBLIO
1261                  && layout.labeltype == LABEL_BIBLIO)) {
1262                 for (int i = 0; i < 10; ++i) {
1263                         par->setCounter(i, par->previous()->getFirstCounter(i));
1264                 }
1265                 par->params().appendix(par->previous()->params().appendix());
1266                 if (!par->params().appendix() && par->params().startOfAppendix()) {
1267                   par->params().appendix(true);
1268                   for (int i = 0; i < 10; ++i) {
1269                     par->setCounter(i, 0);
1270                   }  
1271                 }
1272                 par->enumdepth = par->previous()->enumdepth;
1273                 par->itemdepth = par->previous()->itemdepth;
1274         } else {
1275                 for (int i = 0; i < 10; ++i) {
1276                         par->setCounter(i, 0);
1277                 }  
1278                 par->params().appendix(par->params().startOfAppendix());
1279                 par->enumdepth = 0;
1280                 par->itemdepth = 0;
1281         }
1282
1283         /* Maybe we have to increment the enumeration depth.
1284          * BUT, enumeration in a footnote is considered in isolation from its
1285          *      surrounding paragraph so don't increment if this is the
1286          *      first line of the footnote
1287          * AND, bibliographies can't have their depth changed ie. they
1288          *      are always of depth 0
1289          */
1290         if (par->previous()
1291             && par->previous()->getDepth() < par->getDepth()
1292             && textclasslist.Style(buf->params.textclass,
1293                               par->previous()->getLayout()
1294                              ).labeltype == LABEL_COUNTER_ENUMI
1295             && par->enumdepth < 3
1296             && layout.labeltype != LABEL_BIBLIO) {
1297                 par->enumdepth++;
1298         }
1299
1300         /* Maybe we have to decrement the enumeration depth, see note above */
1301         if (par->previous()
1302             && par->previous()->getDepth() > par->getDepth()
1303             && layout.labeltype != LABEL_BIBLIO) {
1304                 par->enumdepth = par->depthHook(par->getDepth())->enumdepth;
1305                 par->setCounter(6 + par->enumdepth,
1306                         par->depthHook(par->getDepth())->getCounter(6 + par->enumdepth));
1307                 /* reset the counters.
1308                  * A depth change is like a breaking layout
1309                  */
1310                 for (int i = 6 + par->enumdepth + 1; i < 10; ++i)
1311                         par->setCounter(i, 0);
1312         }
1313    
1314         if (!par->params().labelString().empty()) {
1315                 par->params().labelString(string());
1316         }
1317    
1318         if (layout.margintype == MARGIN_MANUAL) {
1319                 if (par->params().labelWidthString().empty()) {
1320                         par->setLabelWidthString(layout.labelstring());
1321                 }
1322         } else {
1323                 par->setLabelWidthString(string());
1324         }
1325    
1326         /* is it a layout that has an automatic label ? */ 
1327         if (layout.labeltype >=  LABEL_COUNTER_CHAPTER) {
1328       
1329                 int i = layout.labeltype - LABEL_COUNTER_CHAPTER;
1330                 if (i >= 0 && i<= buf->params.secnumdepth) {
1331                         par->incCounter(i);     // increment the counter  
1332          
1333                         // Is there a label? Useful for Chapter layout
1334                         if (!par->params().appendix()) {
1335                                 if (!layout.labelstring().empty())
1336                                         par->params().labelString(layout.labelstring());
1337                                 else
1338                                         par->params().labelString(string());
1339                         } else {
1340                                 if (!layout.labelstring_appendix().empty())
1341                                         par->params().labelString(layout.labelstring_appendix());
1342                                 else
1343                                         par->params().labelString(string());
1344                         }
1345
1346                         std::ostringstream s;
1347
1348                         if (!par->params().appendix()) {
1349                                 switch (2 * LABEL_COUNTER_CHAPTER -
1350                                         textclass.maxcounter() + i) {
1351                                 case LABEL_COUNTER_CHAPTER:
1352                                         s << par->getCounter(i);
1353                                         break;
1354                                 case LABEL_COUNTER_SECTION:
1355                                         s << par->getCounter(i - 1) << '.'
1356                                            << par->getCounter(i);
1357                                         break;
1358                                 case LABEL_COUNTER_SUBSECTION:
1359                                         s << par->getCounter(i - 2) << '.'
1360                                           << par->getCounter(i - 1) << '.'
1361                                           << par->getCounter(i);
1362                                         break;
1363                                 case LABEL_COUNTER_SUBSUBSECTION:
1364                                         s << par->getCounter(i - 3) << '.'
1365                                           << par->getCounter(i - 2) << '.'
1366                                           << par->getCounter(i - 1) << '.'
1367                                           << par->getCounter(i);
1368                                         
1369                                         break;
1370                                 case LABEL_COUNTER_PARAGRAPH:
1371                                         s << par->getCounter(i - 4) << '.'
1372                                           << par->getCounter(i - 3) << '.'
1373                                           << par->getCounter(i - 2) << '.'
1374                                           << par->getCounter(i - 1) << '.'
1375                                           << par->getCounter(i);
1376                                         break;
1377                                 case LABEL_COUNTER_SUBPARAGRAPH:
1378                                         s << par->getCounter(i - 5) << '.'
1379                                           << par->getCounter(i - 4) << '.'
1380                                           << par->getCounter(i - 3) << '.'
1381                                           << par->getCounter(i - 2) << '.'
1382                                           << par->getCounter(i - 1) << '.'
1383                                           << par->getCounter(i);
1384
1385                                         break;
1386                                 default:
1387                                         // Can this ever be reached? And in the
1388                                         // case it is, how can this be correct?
1389                                         // (Lgb)
1390                                         s << par->getCounter(i) << '.';
1391                                         break;
1392                                 }
1393                         } else { // appendix
1394                                 switch (2 * LABEL_COUNTER_CHAPTER - textclass.maxcounter() + i) {
1395                                 case LABEL_COUNTER_CHAPTER:
1396                                         if (par->isRightToLeftPar(buf->params))
1397                                                 s << hebrewCounter(par->getCounter(i));
1398                                         else
1399                                                 s << alphaCounter(par->getCounter(i));
1400                                         break;
1401                                 case LABEL_COUNTER_SECTION:
1402                                         if (par->isRightToLeftPar(buf->params))
1403                                                 s << hebrewCounter(par->getCounter(i - 1));
1404                                         else
1405                                                 s << alphaCounter(par->getCounter(i - 1));
1406
1407                                         s << '.'
1408                                           << par->getCounter(i);
1409
1410                                         break;
1411                                 case LABEL_COUNTER_SUBSECTION:
1412                                         if (par->isRightToLeftPar(buf->params))
1413                                                 s << hebrewCounter(par->getCounter(i - 2));
1414                                         else
1415                                                 s << alphaCounter(par->getCounter(i - 2));
1416
1417                                         s << '.'
1418                                           << par->getCounter(i-1) << '.'
1419                                           << par->getCounter(i);
1420
1421                                         break;
1422                                 case LABEL_COUNTER_SUBSUBSECTION:
1423                                         if (par->isRightToLeftPar(buf->params))
1424                                                 s << hebrewCounter(par->getCounter(i-3));
1425                                         else
1426                                                 s << alphaCounter(par->getCounter(i-3));
1427
1428                                         s << '.'
1429                                           << par->getCounter(i-2) << '.'
1430                                           << par->getCounter(i-1) << '.'
1431                                           << par->getCounter(i);
1432
1433                                         break;
1434                                 case LABEL_COUNTER_PARAGRAPH:
1435                                         if (par->isRightToLeftPar(buf->params))
1436                                                 s << hebrewCounter(par->getCounter(i-4));
1437                                         else
1438                                                 s << alphaCounter(par->getCounter(i-4));
1439
1440                                         s << '.'
1441                                           << par->getCounter(i-3) << '.'
1442                                           << par->getCounter(i-2) << '.'
1443                                           << par->getCounter(i-1) << '.'
1444                                           << par->getCounter(i);
1445
1446                                         break;
1447                                 case LABEL_COUNTER_SUBPARAGRAPH:
1448                                         if (par->isRightToLeftPar(buf->params))
1449                                                 s << hebrewCounter(par->getCounter(i-5));
1450                                         else
1451                                                 s << alphaCounter(par->getCounter(i-5));
1452
1453                                         s << '.'
1454                                           << par->getCounter(i-4) << '.'
1455                                           << par->getCounter(i-3) << '.'
1456                                           << par->getCounter(i-2) << '.'
1457                                           << par->getCounter(i-1) << '.'
1458                                           << par->getCounter(i);
1459
1460                                         break;
1461                                 default:
1462                                         // Can this ever be reached? And in the
1463                                         // case it is, how can this be correct?
1464                                         // (Lgb)
1465                                         s << par->getCounter(i) << '.';
1466                                         
1467                                         break;
1468                                 }
1469                         }
1470
1471                         par->params().labelString(par->params().labelString() +s.str().c_str());
1472                         // We really want to remove the c_str as soon as
1473                         // possible...
1474                         
1475                         for (i++; i < 10; ++i) {
1476                                 // reset the following counters
1477                                 par->setCounter(i, 0);
1478                         }
1479                 } else if (layout.labeltype < LABEL_COUNTER_ENUMI) {
1480                         for (i++; i < 10; ++i) {
1481                                 // reset the following counters
1482                                 par->setCounter(i, 0);
1483                         }
1484                 } else if (layout.labeltype == LABEL_COUNTER_ENUMI) {
1485                         par->incCounter(i + par->enumdepth);
1486                         int number = par->getCounter(i + par->enumdepth);
1487
1488                         std::ostringstream s;
1489
1490                         switch (par->enumdepth) {
1491                         case 1:
1492                                 if (par->isRightToLeftPar(buf->params))
1493                                         s << '('
1494                                           << hebrewCounter(number)
1495                                           << ')';
1496                                 else
1497                                         s << '('
1498                                           << loweralphaCounter(number)
1499                                           << ')';
1500                                 break;
1501                         case 2:
1502                                 if (par->isRightToLeftPar(buf->params))
1503                                         s << '.' << romanCounter(number);
1504                                 else
1505                                         s << romanCounter(number) << '.';
1506                                 break;
1507                         case 3:
1508                                 if (par->isRightToLeftPar(buf->params))
1509                                         s << '.'
1510                                           << alphaCounter(number);
1511                                 else
1512                                         s << alphaCounter(number)
1513                                           << '.';
1514                                 break;
1515                         default:
1516                                 if (par->isRightToLeftPar(buf->params))
1517                                         s << '.' << number;
1518                                 else
1519                                         s << number << '.';
1520                                 break;
1521                         }
1522
1523                         par->params().labelString(s.str().c_str());
1524                         // we really want to get rid of that c_str()
1525
1526                         for (i += par->enumdepth + 1; i < 10; ++i)
1527                                 par->setCounter(i, 0);  /* reset the following counters  */
1528          
1529                 } 
1530         } else if (layout.labeltype == LABEL_BIBLIO) {// ale970302
1531                 int i = LABEL_COUNTER_ENUMI - LABEL_COUNTER_CHAPTER + par->enumdepth;
1532                 par->incCounter(i);
1533                 int number = par->getCounter(i);
1534                 if (!par->bibkey) {
1535                         InsetCommandParams p( "bibitem" );
1536                         par->bibkey = new InsetBibKey(p);
1537                 }
1538                 par->bibkey->setCounter(number);
1539                 par->params().labelString(layout.labelstring());
1540                 
1541                 // In biblio should't be following counters but...
1542         } else {
1543                 string s = layout.labelstring();
1544                 
1545                 // the caption hack:
1546                 if (layout.labeltype == LABEL_SENSITIVE) {
1547                         bool isOK (par->InInset() && par->InInset()->owner() &&
1548                                    (par->InInset()->owner()->lyxCode() == Inset::FLOAT_CODE));
1549                         
1550                         if (isOK) {
1551                                 InsetFloat * tmp = static_cast<InsetFloat*>(par->InInset()->owner());
1552                                 Floating const & fl
1553                                         = floatList.getType(tmp->type());
1554                                 // We should get the correct number here too.
1555                                 s = fl.name() + " #:";
1556                         } else {
1557                                 /* par->SetLayout(0); 
1558                                    s = layout->labelstring;  */
1559                                 s = (par->getParLanguage(buf->params)->lang() == "hebrew")
1560                                         ? " :úåòîùî Ã¸Ã±Ã§" : "Senseless: ";
1561                         }
1562                 }
1563                 par->params().labelString(s);
1564                 
1565                 /* reset the enumeration counter. They are always resetted
1566                  * when there is any other layout between */ 
1567                 for (int i = 6 + par->enumdepth; i < 10; ++i)
1568                         par->setCounter(i, 0);
1569         }
1570 }
1571
1572
1573 /* Updates all counters BEHIND the row. Changed paragraphs
1574 * with a dynamic left margin will be rebroken. */ 
1575 void LyXText::updateCounters(BufferView * bview, Row * row) const
1576 {
1577         Paragraph * par;
1578
1579         if (!row) {
1580                 row = firstrow;
1581                 par = row->par();
1582         } else {
1583                 par = row->par()->next();
1584         }
1585
1586         while (par) {
1587                 while (row->par() != par)
1588                         row = row->next();
1589                 
1590                 setCounter(bview->buffer(), par);
1591                 
1592                 /* now  check for the headline layouts. remember that they
1593                  * have a dynamic left margin */ 
1594                 if ((textclasslist.Style(bview->buffer()->params.textclass,
1595                                          par->layout).margintype == MARGIN_DYNAMIC
1596                      || textclasslist.Style(bview->buffer()->params.textclass,
1597                                             par->layout).labeltype == LABEL_SENSITIVE)) {
1598                         
1599                         /* Rebreak the paragraph */ 
1600                         removeParagraph(row);
1601                         appendParagraph(bview, row);
1602                 }
1603                 par = par->next();
1604         }
1605 }
1606
1607
1608 /* insets an inset. */ 
1609 void LyXText::insertInset(BufferView * bview, Inset * inset)
1610 {
1611         if (!cursor.par()->insertInsetAllowed(inset))
1612                 return;
1613         setUndo(bview->buffer(), Undo::INSERT,
1614                 cursor.par()->previous(),
1615                 cursor.par()->next());
1616         cursor.par()->insertInset(cursor.pos(), inset);
1617         insertChar(bview, Paragraph::META_INSET);  /* just to rebreak and refresh correctly.
1618                                       * The character will not be inserted a
1619                                       * second time */
1620 #if 1
1621         // If we enter a highly editable inset the cursor should be to before
1622         // the inset. This couldn't happen before as Undo was not handled inside
1623         // inset now after the Undo LyX tries to call inset->Edit(...) again
1624         // and cannot do this as the cursor is behind the inset and GetInset
1625         // does not return the inset!
1626         if (inset->editable() == Inset::HIGHLY_EDITABLE) {
1627                 cursorLeft(bview, true);
1628         }
1629 #endif
1630 }
1631
1632
1633 void LyXText::copyEnvironmentType()
1634 {
1635         copylayouttype = cursor.par()->getLayout();
1636 }
1637
1638
1639 void LyXText::pasteEnvironmentType(BufferView * bview)
1640 {
1641         setLayout(bview, copylayouttype);
1642 }
1643
1644
1645 void LyXText::cutSelection(BufferView * bview, bool doclear)
1646 {
1647         // Stuff what we got on the clipboard. Even if there is no selection.
1648
1649         // There is a problem with having the stuffing here in that the
1650         // larger the selection the slower LyX will get. This can be
1651         // solved by running the line below only when the selection has
1652         // finished. The solution used currently just works, to make it
1653         // faster we need to be more clever and probably also have more
1654         // calls to stuffClipboard. (Lgb)
1655         bview->stuffClipboard(selectionAsString(bview->buffer()));
1656
1657         // This doesn't make sense, if there is no selection
1658         if (!selection.set())
1659                 return;
1660    
1661         // OK, we have a selection. This is always between selection.start
1662         // and selection.end
1663
1664         // make sure that the depth behind the selection are restored, too
1665         Paragraph * endpar = selection.end.par()->next();
1666         Paragraph * undoendpar = endpar;
1667     
1668         if (endpar && endpar->getDepth()) {
1669                 while (endpar && endpar->getDepth()) {
1670                         endpar = endpar->next();
1671                         undoendpar = endpar;
1672                 }
1673         } else if (endpar) {
1674                 endpar = endpar->next(); // because of parindents etc.
1675         }
1676     
1677         setUndo(bview->buffer(), Undo::DELETE,
1678                 selection.start.par()->previous(),
1679                 undoendpar);
1680     
1681         CutAndPaste cap;
1682
1683         // there are two cases: cut only within one paragraph or
1684         // more than one paragraph
1685         if (selection.start.par() == selection.end.par()) {
1686                 // only within one paragraph
1687                 endpar = selection.end.par();
1688                 int pos = selection.end.pos();
1689                 cap.cutSelection(selection.start.par(), &endpar,
1690                                  selection.start.pos(), pos,
1691                                  bview->buffer()->params.textclass, doclear);
1692                 selection.end.pos(pos);
1693         } else {
1694                 endpar = selection.end.par();
1695                 int pos = selection.end.pos();
1696                 cap.cutSelection(selection.start.par(), &endpar,
1697                                  selection.start.pos(), pos,
1698                                  bview->buffer()->params.textclass, doclear);
1699                 cursor.par(endpar);
1700                 selection.end.par(endpar);
1701                 selection.end.pos(pos);
1702                 cursor.pos(selection.end.pos());
1703         }
1704         endpar = endpar->next();
1705
1706         // sometimes necessary
1707         if (doclear)
1708                 selection.start.par()->stripLeadingSpaces(bview->buffer()->params.textclass);
1709
1710         redoParagraphs(bview, selection.start, endpar);
1711
1712         // cutSelection can invalidate the cursor so we need to set
1713         // it anew. (Lgb)
1714         cursor = selection.start;
1715
1716         // need a valid cursor. (Lgb)
1717         clearSelection(bview);
1718
1719         setCursor(bview, cursor.par(), cursor.pos());
1720         selection.cursor = cursor;
1721         updateCounters(bview, cursor.row());
1722 }
1723
1724
1725 void LyXText::copySelection(BufferView * bview)
1726 {
1727         // Stuff what we got on the clipboard. Even if there is no selection.
1728
1729         // There is a problem with having the stuffing here in that the
1730         // larger the selection the slower LyX will get. This can be
1731         // solved by running the line below only when the selection has
1732         // finished. The solution used currently just works, to make it
1733         // faster we need to be more clever and probably also have more
1734         // calls to stuffClipboard. (Lgb)
1735         bview->stuffClipboard(selectionAsString(bview->buffer()));
1736
1737         // this doesnt make sense, if there is no selection
1738         if (!selection.set())
1739                 return;
1740
1741         // ok we have a selection. This is always between selection.start
1742         // and sel_end cursor
1743
1744         // copy behind a space if there is one
1745         while (selection.start.par()->size() > selection.start.pos()
1746                && selection.start.par()->isLineSeparator(selection.start.pos())
1747                && (selection.start.par() != selection.end.par()
1748                    || selection.start.pos() < selection.end.pos()))
1749                 selection.start.pos(selection.start.pos() + 1); 
1750
1751         CutAndPaste cap;
1752
1753         cap.copySelection(selection.start.par(), selection.end.par(),
1754                           selection.start.pos(), selection.end.pos(),
1755                           bview->buffer()->params.textclass);
1756 }
1757
1758
1759 void LyXText::pasteSelection(BufferView * bview)
1760 {
1761         CutAndPaste cap;
1762
1763         // this does not make sense, if there is nothing to paste
1764         if (!cap.checkPastePossible(cursor.par()))
1765                 return;
1766
1767         setUndo(bview->buffer(), Undo::INSERT,
1768                 cursor.par()->previous(),
1769                 cursor.par()->next()); 
1770
1771         Paragraph * endpar;
1772         Paragraph * actpar = cursor.par();
1773
1774         int pos = cursor.pos();
1775         cap.pasteSelection(&actpar, &endpar, pos,
1776                            bview->buffer()->params.textclass);
1777     
1778         redoParagraphs(bview, cursor, endpar);
1779         
1780         setCursor(bview, cursor.par(), cursor.pos());
1781         clearSelection(bview);
1782    
1783         selection.cursor = cursor;
1784         setCursor(bview, actpar, pos);
1785         setSelection(bview);
1786         updateCounters(bview, cursor.row());
1787 }
1788
1789
1790 // returns a pointer to the very first Paragraph
1791 Paragraph * LyXText::firstParagraph() const
1792 {
1793         return ownerParagraph();
1794 }
1795
1796
1797 // sets the selection over the number of characters of string, no check!!
1798 void LyXText::setSelectionOverString(BufferView * bview, string const & str)
1799 {
1800         if (str.empty())
1801                 return;
1802         
1803         selection.cursor = cursor;
1804         for (string::size_type i = 0; i < str.length(); ++i)
1805                 cursorRight(bview);
1806         setSelection(bview);
1807 }
1808
1809
1810 // simple replacing. The font of the first selected character is used
1811 void LyXText::replaceSelectionWithString(BufferView * bview,
1812                                          string const & str)
1813 {
1814         setCursorParUndo(bview->buffer());
1815         freezeUndo();
1816
1817         if (!selection.set()) { // create a dummy selection
1818                 selection.end = cursor;
1819                 selection.start = cursor;
1820         }
1821
1822         // Get font setting before we cut
1823         Paragraph::size_type pos = selection.end.pos();
1824         LyXFont const font = selection.start.par()
1825                 ->getFontSettings(bview->buffer()->params,
1826                                   selection.start.pos());
1827
1828         // Insert the new string
1829         for (string::const_iterator cit = str.begin(); cit != str.end(); ++cit) {
1830                 selection.end.par()->insertChar(pos, (*cit), font);
1831                 ++pos;
1832         }
1833         
1834         // Cut the selection
1835         cutSelection(bview);
1836
1837         unFreezeUndo();
1838 }
1839
1840
1841 // needed to insert the selection
1842 void LyXText::insertStringAsLines(BufferView * bview, string const & str)
1843 {
1844         Paragraph * par = cursor.par();
1845         Paragraph::size_type pos = cursor.pos();
1846         Paragraph * endpar = cursor.par()->next();
1847         
1848         setCursorParUndo(bview->buffer());
1849         
1850         bool isEnvironment =
1851                 textclasslist.Style(bview->buffer()->params.textclass, 
1852                                     cursor.par()->getLayout()).isEnvironment();
1853         bool free_spacing =
1854                 textclasslist.Style(bview->buffer()->params.textclass, 
1855                                     cursor.par()->getLayout()).free_spacing;
1856         bool keepempty =
1857                 textclasslist.Style(bview->buffer()->params.textclass, 
1858                                     cursor.par()->getLayout()).keepempty;
1859
1860         // only to be sure, should not be neccessary
1861         clearSelection(bview);
1862         
1863         // insert the string, don't insert doublespace
1864         bool space_inserted = true;
1865         for(string::const_iterator cit = str.begin(); 
1866             cit != str.end(); ++cit) {
1867                 if (*cit == '\n') {
1868                         if (par->size() || keepempty) { 
1869                                 par->breakParagraph(bview->buffer()->params, 
1870                                                     pos, isEnvironment);
1871                                 par = par->next();
1872                                 pos = 0;
1873                                 space_inserted = true;
1874                         } else {
1875                                 continue;
1876                         }
1877                 // do not insert consecutive spaces if !free_spacing
1878                 } else if ((*cit == ' ' || *cit == '\t')
1879                     && space_inserted && !free_spacing) {
1880                         continue;
1881                 } else if (*cit == '\t') {
1882                         if (!free_spacing) {
1883                                 // tabs are like spaces here
1884                                 par->insertChar(pos, ' ', 
1885                                                 current_font);
1886                                 ++pos;
1887                                 space_inserted = true;
1888                         } else {
1889                                 const Paragraph::value_type nb = 8 - pos % 8;
1890                                 for (Paragraph::size_type a = 0; 
1891                                      a < nb ; ++a) {
1892                                         par->insertChar(pos, ' ', 
1893                                                         current_font);
1894                                         ++pos;
1895                                 }
1896                                 space_inserted = true;
1897                         }
1898                 } else if (!IsPrintable(*cit)) {
1899                         // Ignore unprintables
1900                         continue;
1901                 } else {
1902                         // just insert the character
1903                         par->insertChar(pos, *cit, current_font);
1904                         ++pos;
1905                         space_inserted = (*cit == ' ');
1906                 }
1907
1908         }       
1909
1910         redoParagraphs(bview, cursor, endpar);
1911         setCursor(bview, cursor.par(), cursor.pos());
1912         selection.cursor = cursor;
1913         setCursor(bview, par, pos);
1914         setSelection(bview);
1915 }
1916
1917
1918 /* turns double-CR to single CR, others where converted into one
1919    blank. Then InsertStringAsLines is called */
1920 void LyXText::insertStringAsParagraphs(BufferView * bview, string const & str)
1921 {
1922         string linestr(str);
1923         bool newline_inserted = false;
1924         for (string::size_type i = 0; i < linestr.length(); ++i) {
1925                 if (linestr[i] == '\n') {
1926                         if (newline_inserted) {
1927                                 // we know that \r will be ignored by
1928                                 // InsertStringA. Of course, it is a dirty
1929                                 // trick, but it works...
1930                                 linestr[i - 1] = '\r';
1931                                 linestr[i] = '\n';
1932                         } else {
1933                                 linestr[i] = ' ';
1934                                 newline_inserted = true;
1935                         } 
1936                 } else if (IsPrintable(linestr[i])) {
1937                         newline_inserted = false;
1938                 }
1939         }
1940         insertStringAsLines(bview, linestr);
1941 }
1942
1943
1944 bool LyXText::gotoNextInset(BufferView * bview,
1945                             std::vector<Inset::Code> const & codes,
1946                             string const & contents) const
1947 {
1948         LyXCursor res = cursor;
1949         Inset * inset;
1950         do {
1951                 if (res.pos() < res.par()->size() - 1) {
1952                         res.pos(res.pos() + 1);
1953                 } else  {
1954                         res.par(res.par()->next());
1955                         res.pos(0);
1956                 }
1957       
1958         } while (res.par() && 
1959                  !(res.par()->getChar(res.pos()) == Paragraph::META_INSET
1960                    && (inset = res.par()->getInset(res.pos())) != 0
1961                    && find(codes.begin(), codes.end(), inset->lyxCode())
1962                       != codes.end()
1963                    && (contents.empty() ||
1964                        static_cast<InsetCommand *>(res.par()->getInset(res.pos()))->getContents()
1965                        == contents)));
1966
1967         if (res.par()) {
1968                 setCursor(bview, res.par(), res.pos());
1969                 return true;
1970         }
1971         return false;
1972 }
1973
1974
1975 void LyXText::checkParagraph(BufferView * bview, Paragraph * par,
1976                              Paragraph::size_type pos)
1977 {
1978         LyXCursor tmpcursor;                    
1979
1980         int y = 0;
1981         Paragraph::size_type z;
1982         Row * row = getRow(par, pos, y);
1983         
1984         // is there a break one row above
1985         if (row->previous() && row->previous()->par() == row->par()) {
1986                 z = nextBreakPoint(bview, row->previous(), workWidth(bview));
1987                 if (z >= row->pos()) {
1988                         // set the dimensions of the row above
1989                         y -= row->previous()->height();
1990                         refresh_y = y;
1991                         refresh_row = row->previous();
1992                         status = LyXText::NEED_MORE_REFRESH;
1993                         
1994                         breakAgain(bview, row->previous());
1995                         
1996                         // set the cursor again. Otherwise
1997                         // dangling pointers are possible
1998                         setCursor(bview, cursor.par(), cursor.pos(),
1999                                   false, cursor.boundary());
2000                         selection.cursor = cursor;
2001                         return;
2002                 }
2003         }
2004
2005         int const tmpheight = row->height();
2006         Paragraph::size_type const tmplast = rowLast(row);
2007         refresh_y = y;
2008         refresh_row = row;
2009         
2010         breakAgain(bview, row);
2011         if (row->height() == tmpheight && rowLast(row) == tmplast)
2012                 status = LyXText::NEED_VERY_LITTLE_REFRESH;
2013         else
2014                 status = LyXText::NEED_MORE_REFRESH; 
2015         
2016         // check the special right address boxes
2017         if (textclasslist.Style(bview->buffer()->params.textclass,
2018                                 par->getLayout()).margintype
2019             == MARGIN_RIGHT_ADDRESS_BOX) {
2020                 tmpcursor.par(par);
2021                 tmpcursor.row(row);
2022                 tmpcursor.y(y);
2023                 tmpcursor.x(0);
2024                 tmpcursor.x_fix(0);
2025                 tmpcursor.pos(pos);
2026                 redoDrawingOfParagraph(bview, tmpcursor); 
2027         }
2028
2029         // set the cursor again. Otherwise dangling pointers are possible
2030         // also set the selection
2031    
2032         if (selection.set()) {
2033                 tmpcursor = cursor;
2034                 setCursorIntern(bview, selection.cursor.par(), selection.cursor.pos(),
2035                                 false, selection.cursor.boundary());
2036                 selection.cursor = cursor; 
2037                 setCursorIntern(bview, selection.start.par(),
2038                                 selection.start.pos(),
2039                                 false, selection.start.boundary());
2040                 selection.start = cursor; 
2041                 setCursorIntern(bview, selection.end.par(),
2042                                 selection.end.pos(),
2043                                 false, selection.end.boundary());
2044                 selection.end = cursor; 
2045                 setCursorIntern(bview, last_sel_cursor.par(),
2046                                 last_sel_cursor.pos(),
2047                                 false, last_sel_cursor.boundary());
2048                 last_sel_cursor = cursor; 
2049                 cursor = tmpcursor;
2050         }
2051         setCursorIntern(bview, cursor.par(), cursor.pos(),
2052                         false, cursor.boundary());
2053 }
2054
2055
2056 // returns false if inset wasn't found
2057 bool LyXText::updateInset(BufferView * bview, Inset * inset)
2058 {
2059         // first check the current paragraph
2060         int pos = cursor.par()->getPositionOfInset(inset);
2061         if (pos != -1){
2062                 checkParagraph(bview, cursor.par(), pos);
2063                 return true;
2064         }
2065   
2066         // check every paragraph
2067   
2068         Paragraph * par = firstParagraph();
2069         do {
2070                         pos = par->getPositionOfInset(inset);
2071                         if (pos != -1){
2072                                 checkParagraph(bview, par, pos);
2073                                 return true;
2074                         }
2075                 par = par->next();
2076         } while (par);
2077   
2078         return false;
2079 }
2080
2081
2082 void LyXText::setCursor(BufferView * bview, Paragraph * par,
2083                         Paragraph::size_type pos, 
2084                         bool setfont, bool boundary) const
2085 {
2086         LyXCursor old_cursor = cursor;
2087         setCursorIntern(bview, par, pos, setfont, boundary);
2088         deleteEmptyParagraphMechanism(bview, old_cursor);
2089 }
2090
2091
2092 void LyXText::setCursor(BufferView *bview, LyXCursor & cur, Paragraph * par,
2093                         Paragraph::size_type pos, bool boundary) const
2094 {
2095         cur.par(par);
2096         cur.pos(pos);
2097         cur.boundary(boundary);
2098
2099         /* get the cursor y position in text  */
2100         int y = 0;
2101         Row * row = getRow(par, pos, y);
2102         /* y is now the beginning of the cursor row */ 
2103         y += row->baseline();
2104         /* y is now the cursor baseline */ 
2105         cur.y(y);
2106    
2107         /* now get the cursors x position */
2108         float x;
2109         float fill_separator;
2110         float fill_hfill;
2111         float fill_label_hfill;
2112         prepareToPrint(bview, row, x, fill_separator, fill_hfill,
2113                        fill_label_hfill);
2114         Paragraph::size_type cursor_vpos = 0;
2115         Paragraph::size_type last = rowLastPrintable(row);
2116
2117         if (pos > last + 1)   // This shouldn't happen.
2118                 pos = last + 1;
2119         else if (pos < row->pos())
2120                 pos = row->pos();
2121
2122         if (last < row->pos())
2123                 cursor_vpos = row->pos();
2124         else if (pos > last && !boundary)
2125                 cursor_vpos = (row->par()->isRightToLeftPar(bview->buffer()->params))
2126                         ? row->pos() : last + 1; 
2127         else if (pos > row->pos() &&
2128                  (pos > last || boundary))
2129                 /// Place cursor after char at (logical) position pos - 1
2130                 cursor_vpos = (bidi_level(pos - 1) % 2 == 0)
2131                         ? log2vis(pos - 1) + 1 : log2vis(pos - 1);
2132         else
2133                 /// Place cursor before char at (logical) position pos
2134                 cursor_vpos = (bidi_level(pos) % 2 == 0)
2135                         ? log2vis(pos) : log2vis(pos) + 1;
2136         
2137         Paragraph::size_type main_body =
2138                 beginningOfMainBody(bview->buffer(), row->par());
2139         if ((main_body > 0) &&
2140             ((main_body-1 > last) || 
2141              !row->par()->isLineSeparator(main_body-1)))
2142                 main_body = 0;
2143         
2144         for (Paragraph::size_type vpos = row->pos();
2145              vpos < cursor_vpos; ++vpos) {
2146                 pos = vis2log(vpos);
2147                 if (main_body > 0 && pos == main_body - 1) {
2148                         x += fill_label_hfill +
2149                                 lyxfont::width(textclasslist.Style(
2150                                         bview->buffer()->params.textclass,
2151                                         row->par()->getLayout())
2152                                                .labelsep,
2153                                                getFont(bview->buffer(), row->par(), -2));
2154                         if (row->par()->isLineSeparator(main_body-1))
2155                                 x -= singleWidth(bview, row->par(),main_body-1);
2156                 }
2157                 if (hfillExpansion(bview->buffer(), row, pos)) {
2158                         x += singleWidth(bview, row->par(), pos);
2159                         if (pos >= main_body)
2160                                 x += fill_hfill;
2161                         else 
2162                                 x += fill_label_hfill;
2163                 } else if (row->par()->isSeparator(pos)) {
2164                         x += singleWidth(bview, row->par(), pos);
2165                         if (pos >= main_body)
2166                                 x += fill_separator;
2167                 } else
2168                         x += singleWidth(bview, row->par(), pos);
2169         }
2170         
2171         cur.x(int(x));
2172         cur.x_fix(cur.x());
2173         cur.row(row);
2174 }
2175
2176
2177 void LyXText::setCursorIntern(BufferView * bview, Paragraph * par,
2178                               Paragraph::size_type pos,
2179                               bool setfont, bool boundary) const
2180 {
2181         setCursor(bview, cursor, par, pos, boundary);
2182         if (setfont)
2183                 setCurrentFont(bview);
2184 }
2185
2186
2187 void LyXText::setCurrentFont(BufferView * bview) const
2188 {
2189         Paragraph::size_type pos = cursor.pos();
2190         if (cursor.boundary() && pos > 0)
2191                 --pos;
2192
2193         if (pos > 0) {
2194                 if (pos == cursor.par()->size())
2195                         --pos;
2196                 else // potentional bug... BUG (Lgb)
2197                 if (cursor.par()->isSeparator(pos)) {
2198                         if (pos > cursor.row()->pos() &&
2199                             bidi_level(pos) % 2 == 
2200                             bidi_level(pos - 1) % 2)
2201                                 --pos;
2202                         else if (pos + 1 < cursor.par()->size())
2203                                 ++pos;
2204                 }
2205         }
2206
2207         current_font =
2208                 cursor.par()->getFontSettings(bview->buffer()->params, pos);
2209         real_current_font = getFont(bview->buffer(), cursor.par(), pos);
2210
2211         if (cursor.pos() == cursor.par()->size() &&
2212             isBoundary(bview->buffer(), cursor.par(), cursor.pos()) &&
2213             !cursor.boundary()) {
2214                 Language const * lang =
2215                         cursor.par()->getParLanguage(bview->buffer()->params);
2216                 current_font.setLanguage(lang);
2217                 current_font.setNumber(LyXFont::OFF);
2218                 real_current_font.setLanguage(lang);
2219                 real_current_font.setNumber(LyXFont::OFF);
2220         }
2221 }
2222
2223
2224 void LyXText::setCursorFromCoordinates(BufferView * bview, int x, int y) const
2225 {
2226         LyXCursor old_cursor = cursor;
2227    
2228         /* get the row first */ 
2229    
2230         Row * row = getRowNearY(y);
2231         cursor.par(row->par());
2232
2233         bool bound = false;
2234         int column = getColumnNearX(bview, row, x, bound);
2235         cursor.pos(row->pos() + column);
2236         cursor.x(x);
2237         cursor.y(y + row->baseline());
2238         cursor.row(row);
2239         cursor.boundary(bound);
2240         setCurrentFont(bview);
2241         deleteEmptyParagraphMechanism(bview, old_cursor);
2242 }
2243
2244
2245 void LyXText::setCursorFromCoordinates(BufferView * bview, LyXCursor & cur,
2246                                        int x, int y) const
2247 {
2248         /* get the row first */ 
2249    
2250         Row * row = getRowNearY(y);
2251         bool bound = false;
2252         int column = getColumnNearX(bview, row, x, bound);
2253    
2254         cur.par(row->par());
2255         cur.pos(row->pos() + column);
2256         cur.x(x);
2257         cur.y(y + row->baseline());
2258         cur.row(row);
2259         cur.boundary(bound);
2260 }
2261
2262
2263 void LyXText::cursorLeft(BufferView * bview, bool internal) const
2264 {
2265         if (cursor.pos() > 0) {
2266                 bool boundary = cursor.boundary();
2267                 setCursor(bview, cursor.par(), cursor.pos() - 1, true, false);
2268                 if (!internal && !boundary &&
2269                     isBoundary(bview->buffer(), cursor.par(), cursor.pos() + 1))
2270                         setCursor(bview, cursor.par(), cursor.pos() + 1, true, true);
2271         } else if (cursor.par()->previous()) { // steps into the above paragraph.
2272                 Paragraph * par = cursor.par()->previous();
2273                 setCursor(bview, par, par->size());
2274         }
2275 }
2276
2277
2278 void LyXText::cursorRight(BufferView * bview, bool internal) const
2279 {
2280         if (!internal && cursor.boundary() &&
2281             !cursor.par()->isNewline(cursor.pos()))
2282                 setCursor(bview, cursor.par(), cursor.pos(), true, false);
2283         else if (cursor.pos() < cursor.par()->size()) {
2284                 setCursor(bview, cursor.par(), cursor.pos() + 1, true, false);
2285                 if (!internal &&
2286                     isBoundary(bview->buffer(), cursor.par(), cursor.pos()))
2287                         setCursor(bview, cursor.par(), cursor.pos(), true, true);
2288         } else if (cursor.par()->next())
2289                 setCursor(bview, cursor.par()->next(), 0);
2290 }
2291
2292
2293 void LyXText::cursorUp(BufferView * bview) const
2294 {
2295         setCursorFromCoordinates(bview, cursor.x_fix(), 
2296                                  cursor.y() - cursor.row()->baseline() - 1);
2297 }
2298
2299
2300 void LyXText::cursorDown(BufferView * bview) const
2301 {
2302         setCursorFromCoordinates(bview, cursor.x_fix(), 
2303                                  cursor.y() - cursor.row()->baseline()
2304                                  + cursor.row()->height() + 1);
2305 }
2306
2307
2308 void LyXText::cursorUpParagraph(BufferView * bview) const
2309 {
2310         if (cursor.pos() > 0) {
2311                 setCursor(bview, cursor.par(), 0);
2312         }
2313         else if (cursor.par()->previous()) {
2314                 setCursor(bview, cursor.par()->previous(), 0);
2315         }
2316 }
2317
2318
2319 void LyXText::cursorDownParagraph(BufferView * bview) const
2320 {
2321         if (cursor.par()->next()) {
2322                 setCursor(bview, cursor.par()->next(), 0);
2323         } else {
2324                 setCursor(bview, cursor.par(), cursor.par()->size());
2325         }
2326 }
2327
2328
2329 void LyXText::deleteEmptyParagraphMechanism(BufferView * bview,
2330                                             LyXCursor const & old_cursor) const
2331 {
2332         // Would be wrong to delete anything if we have a selection.
2333         if (selection.set()) return;
2334
2335         // We allow all kinds of "mumbo-jumbo" when freespacing.
2336         if (textclasslist.Style(bview->buffer()->params.textclass,
2337                                 old_cursor.par()->getLayout()).free_spacing)
2338                 return;
2339
2340         bool deleted = false;
2341         
2342         /* Ok I'll put some comments here about what is missing.
2343            I have fixed BackSpace (and thus Delete) to not delete
2344            double-spaces automagically. I have also changed Cut,
2345            Copy and Paste to hopefully do some sensible things.
2346            There are still some small problems that can lead to
2347            double spaces stored in the document file or space at
2348            the beginning of paragraphs. This happens if you have
2349            the cursor betwenn to spaces and then save. Or if you
2350            cut and paste and the selection have a space at the
2351            beginning and then save right after the paste. I am
2352            sure none of these are very hard to fix, but I will
2353            put out 1.1.4pre2 with FIX_DOUBLE_SPACE defined so
2354            that I can get some feedback. (Lgb)
2355         */
2356
2357         // If old_cursor.pos() == 0 and old_cursor.pos()(1) == LineSeparator
2358         // delete the LineSeparator.
2359         // MISSING
2360
2361         // If old_cursor.pos() == 1 and old_cursor.pos()(0) == LineSeparator
2362         // delete the LineSeparator.
2363         // MISSING
2364
2365         // If the pos around the old_cursor were spaces, delete one of them.
2366         if (old_cursor.par() != cursor.par() || old_cursor.pos() != cursor.pos()) { 
2367                 // Only if the cursor has really moved
2368                 
2369                 if (old_cursor.pos() > 0
2370                     && old_cursor.pos() < old_cursor.par()->size()
2371                     && old_cursor.par()->isLineSeparator(old_cursor.pos())
2372                     && old_cursor.par()->isLineSeparator(old_cursor.pos() - 1)) {
2373                         old_cursor.par()->erase(old_cursor.pos() - 1);
2374                         redoParagraphs(bview, old_cursor, old_cursor.par()->next());
2375                         // correct cursor
2376                         if (old_cursor.par() == cursor.par() &&
2377                             cursor.pos() > old_cursor.pos()) {
2378                                 setCursorIntern(bview, cursor.par(),
2379                                                 cursor.pos() - 1);
2380                         } else
2381                                 setCursorIntern(bview, cursor.par(),
2382                                                 cursor.pos());
2383                         return;
2384                 }
2385         }
2386
2387         // Do not delete empty paragraphs with keepempty set.
2388         if ((textclasslist.Style(bview->buffer()->params.textclass,
2389                                  old_cursor.par()->getLayout())).keepempty)
2390                 return;
2391
2392         LyXCursor tmpcursor;
2393
2394         if (old_cursor.par() != cursor.par()) {
2395                 if ((old_cursor.par()->size() == 0
2396                       || (old_cursor.par()->size() == 1
2397                           && old_cursor.par()->isLineSeparator(0)))) {
2398                         // ok, we will delete anything
2399                         
2400                         // make sure that you do not delete any environments
2401                                 status = LyXText::NEED_MORE_REFRESH;
2402                                 deleted = true;
2403                                 
2404                                 if (old_cursor.row()->previous()) {
2405                                         refresh_row = old_cursor.row()->previous();
2406                                         refresh_y = old_cursor.y() - old_cursor.row()->baseline() - refresh_row->height();
2407                                         tmpcursor = cursor;
2408                                         cursor = old_cursor; // that undo can restore the right cursor position
2409                                         Paragraph * endpar = old_cursor.par()->next();
2410                                         if (endpar && endpar->getDepth()) {
2411                                                 while (endpar && endpar->getDepth()) {
2412                                                         endpar = endpar->next();
2413                                                 }
2414                                         }
2415                                         setUndo(bview->buffer(), Undo::DELETE,
2416                                                 old_cursor.par()->previous(),
2417                                                 endpar);
2418                                         cursor = tmpcursor;
2419
2420                                         // delete old row
2421                                         removeRow(old_cursor.row());
2422                                         if (ownerParagraph() == old_cursor.par()) {
2423                                                 ownerParagraph(ownerParagraph()->next());
2424                                         }
2425                                         // delete old par
2426                                         delete old_cursor.par();
2427                                         
2428                                         /* Breakagain the next par. Needed
2429                                          * because of the parindent that
2430                                          * can occur or dissappear. The
2431                                          * next row can change its height,
2432                                          * if there is another layout before */
2433                                         if (refresh_row->next()) {
2434                                                 breakAgain(bview, refresh_row->next());
2435                                                 updateCounters(bview, refresh_row);
2436                                         }
2437                                         setHeightOfRow(bview, refresh_row);
2438                                 } else {
2439                                         refresh_row = old_cursor.row()->next();
2440                                         refresh_y = old_cursor.y() - old_cursor.row()->baseline();
2441                                         
2442                                         tmpcursor = cursor;
2443                                         cursor = old_cursor; // that undo can restore the right cursor position
2444                                         Paragraph * endpar = old_cursor.par()->next();
2445                                         if (endpar && endpar->getDepth()) {
2446                                                 while (endpar && endpar->getDepth()) {
2447                                                         endpar = endpar->next();
2448                                                 }
2449                                         }
2450                                         setUndo(bview->buffer(), Undo::DELETE,
2451                                                 old_cursor.par()->previous(),
2452                                                 endpar);
2453                                         cursor = tmpcursor;
2454
2455                                         // delete old row
2456                                         removeRow(old_cursor.row());
2457                                         // delete old par
2458                                         if (ownerParagraph() == old_cursor.par()) {
2459                                                 ownerParagraph(ownerParagraph()->next());
2460                                         }
2461
2462                                         delete old_cursor.par();
2463                                         
2464                                         /* Breakagain the next par. Needed
2465                                            because of the parindent that can
2466                                            occur or dissappear.
2467                                            The next row can change its height,
2468                                            if there is another layout before
2469                                         */ 
2470                                         if (refresh_row) {
2471                                                 breakAgain(bview, refresh_row);
2472                                                 updateCounters(bview, refresh_row->previous());
2473                                         }
2474                                 }
2475                                 
2476                                 // correct cursor y
2477
2478                                 setCursorIntern(bview, cursor.par(), cursor.pos());
2479
2480                                 if (selection.cursor.par()  == old_cursor.par()
2481                                     && selection.cursor.pos() == selection.cursor.pos()) {
2482                                         // correct selection
2483                                         selection.cursor = cursor;
2484                                 }
2485                 }
2486                 if (!deleted) {
2487                         if (old_cursor.par()->stripLeadingSpaces(bview->buffer()->params.textclass)) {
2488                                 redoParagraphs(bview, old_cursor, old_cursor.par()->next());
2489                                 // correct cursor y
2490                                 setCursorIntern(bview, cursor.par(), cursor.pos());
2491                                 selection.cursor = cursor;
2492                         }
2493                 }
2494         }
2495 }
2496
2497
2498 Paragraph * LyXText::getParFromID(int id)
2499 {
2500         Paragraph * result = firstParagraph();
2501         while (result && result->id() != id)
2502                 result = result->next();
2503         return result;
2504 }
2505
2506
2507 // undo functions
2508 bool LyXText::textUndo(BufferView * bview)
2509 {
2510         if (inset_owner)
2511                 return false;
2512         // returns false if no undo possible
2513         Undo * undo = bview->buffer()->undostack.pop();
2514         if (undo) {
2515                 finishUndo();
2516                 if (!undo_frozen)
2517                         bview->buffer()->redostack
2518                                 .push(createUndo(bview->buffer(), undo->kind, 
2519                                                  getParFromID(undo->number_of_before_par),
2520                                                  getParFromID(undo->number_of_behind_par)));
2521         }
2522         return textHandleUndo(bview, undo);
2523 }
2524
2525
2526 bool LyXText::textRedo(BufferView * bview)
2527 {
2528         if (inset_owner)
2529                 return false;
2530         // returns false if no redo possible
2531         Undo * undo = bview->buffer()->redostack.pop();
2532         if (undo) {
2533                 finishUndo();
2534                 if (!undo_frozen)
2535                         bview->buffer()->undostack
2536                                 .push(createUndo(bview->buffer(), undo->kind, 
2537                                                  getParFromID(undo->number_of_before_par),
2538                                                  getParFromID(undo->number_of_behind_par)));
2539         }
2540         return textHandleUndo(bview, undo);
2541 }
2542
2543
2544 bool LyXText::textHandleUndo(BufferView * bview, Undo * undo)
2545 {
2546         if (inset_owner)
2547                 return false;
2548         // returns false if no undo possible
2549         bool result = false;
2550         if (undo) {
2551                 Paragraph * before =
2552                         getParFromID(undo->number_of_before_par); 
2553                 Paragraph * behind =
2554                         getParFromID(undo->number_of_behind_par); 
2555                 Paragraph * tmppar;
2556                 Paragraph * tmppar2;
2557                 Paragraph * endpar;
2558                 Paragraph * tmppar5;
2559     
2560                 // if there's no before take the beginning
2561                 // of the document for redoing
2562                 if (!before)
2563                         setCursorIntern(bview, firstParagraph(), 0);
2564
2565                 // replace the paragraphs with the undo informations
2566
2567                 Paragraph * tmppar3 = undo->par;
2568                 undo->par = 0; // otherwise the undo destructor would delete the paragraph
2569                 Paragraph * tmppar4 = tmppar3;
2570
2571                 if (tmppar4) {
2572                         while (tmppar4->next())
2573                                 tmppar4 = tmppar4->next();
2574                 } // get last undo par
2575     
2576                 // now remove the old text if there is any
2577                 if (before != behind || (!behind && !before)) {
2578                         if (before)
2579                                 tmppar5 = before->next();
2580                         else
2581                                 tmppar5 = ownerParagraph();
2582                         tmppar2 = tmppar3;
2583                         while (tmppar5 && tmppar5 != behind) {
2584                                 tmppar = tmppar5;
2585                                 tmppar5 = tmppar5->next();
2586                                 // a memory optimization for edit: Only layout information
2587                                 // is stored in the undo. So restore the text informations.
2588                                 if (undo->kind == Undo::EDIT) {
2589                                         tmppar2->setContentsFromPar(tmppar);
2590                                         tmppar->clearContents();
2591                                         tmppar2 = tmppar2->next();
2592                                 }
2593                         }
2594                 }
2595     
2596                 // put the new stuff in the list if there is one
2597                 if (tmppar3){
2598                         if (before)
2599                                 before->next(tmppar3);
2600                         else
2601                                 ownerParagraph(tmppar3);
2602                         tmppar3->previous(before);
2603                 } else {
2604                         if (!before)
2605                                 ownerParagraph(behind);
2606                 }
2607                 if (tmppar4) {
2608                         tmppar4->next(behind);
2609                         if (behind)
2610                                 behind->previous(tmppar4);
2611                 }
2612     
2613     
2614                 // Set the cursor for redoing
2615                 if (before) {
2616                         setCursorIntern(bview, before, 0);
2617                 }
2618
2619                 // calculate the endpar for redoing the paragraphs.
2620                 if (behind) {
2621                                 endpar = behind->next();
2622                 } else
2623                         endpar = behind;
2624     
2625                 tmppar = getParFromID(undo->number_of_cursor_par);
2626                 redoParagraphs(bview, cursor, endpar); 
2627                 if (tmppar){
2628                         setCursorIntern(bview, tmppar, undo->cursor_pos);
2629                         updateCounters(bview, cursor.row());
2630                 }
2631                 result = true;
2632                 delete undo;
2633         }
2634         finishUndo();
2635         return result;
2636 }
2637
2638
2639 void LyXText::finishUndo()
2640 {
2641         if (inset_owner)
2642                 return;
2643         // makes sure the next operation will be stored
2644         undo_finished = true;
2645 }
2646
2647
2648 void LyXText::freezeUndo()
2649 {
2650         if (inset_owner)
2651                 return;
2652         // this is dangerous and for internal use only
2653         undo_frozen = true;
2654 }
2655
2656
2657 void LyXText::unFreezeUndo()
2658 {
2659         if (inset_owner)
2660                 return;
2661         // this is dangerous and for internal use only
2662         undo_frozen = false;
2663 }
2664
2665
2666 void LyXText::setUndo(Buffer * buf, Undo::undo_kind kind,
2667                       Paragraph const * before,
2668                       Paragraph const * behind) const
2669 {
2670         if (inset_owner)
2671                 return;
2672         if (!undo_frozen)
2673                 buf->undostack.push(createUndo(buf, kind, before, behind));
2674         buf->redostack.clear();
2675 }
2676
2677
2678 void LyXText::setRedo(Buffer * buf, Undo::undo_kind kind,
2679                       Paragraph const * before, Paragraph const * behind)
2680 {
2681         if (inset_owner)
2682                 return;
2683         buf->redostack.push(createUndo(buf, kind, before, behind));
2684 }
2685
2686
2687 Undo * LyXText::createUndo(Buffer * buf, Undo::undo_kind kind,
2688                            Paragraph const * before,
2689                            Paragraph const * behind) const
2690 {
2691         if (inset_owner)
2692                 return 0;
2693
2694         int before_number = -1;
2695         int behind_number = -1;
2696         if (before)
2697                 before_number = before->id();
2698         if (behind)
2699                 behind_number = behind->id();
2700         // Undo::EDIT  and Undo::FINISH are
2701         // always finished. (no overlapping there)
2702         // overlapping only with insert and delete inside one paragraph: 
2703         // Nobody wants all removed  character
2704         // appear one by one when undoing. 
2705         // EDIT is special since only layout information, not the
2706         // contents of a paragaph are stored.
2707         if (!undo_finished && (kind != Undo::EDIT) && (kind != Undo::FINISH)){
2708                 // check wether storing is needed
2709                 if (!buf->undostack.empty() && 
2710                     buf->undostack.top()->kind == kind &&
2711                     buf->undostack.top()->number_of_before_par ==  before_number &&
2712                     buf->undostack.top()->number_of_behind_par ==  behind_number ){
2713                         // no undo needed
2714                         return 0;
2715                 }
2716         }
2717         // create a new Undo
2718         Paragraph * undopar;
2719
2720         Paragraph * start = 0;
2721         Paragraph * end = 0;
2722
2723         if (before)
2724                 start = const_cast<Paragraph*>(before->next());
2725         else
2726                 start = firstParagraph();
2727         if (behind)
2728                 end = const_cast<Paragraph*>(behind->previous());
2729         else {
2730                 end = firstParagraph();
2731                 while (end->next())
2732                         end = end->next();
2733         }
2734         if (start && end && (start != end->next()) &&
2735             ((before != behind) || (!before && !behind))) {
2736                 Paragraph * tmppar = start;
2737                 Paragraph * tmppar2 = new Paragraph(*tmppar);
2738                 tmppar2->id(tmppar->id());
2739                 
2740                 // a memory optimization: Just store the layout information
2741                 // when only edit
2742                 if (kind == Undo::EDIT){
2743                         //tmppar2->text.clear();
2744                         tmppar2->clearContents();
2745                 }
2746
2747                 undopar = tmppar2;
2748   
2749                 while (tmppar != end && tmppar->next()) {
2750                         tmppar = tmppar->next();
2751                         tmppar2->next(new Paragraph(*tmppar));
2752                         tmppar2->next()->id(tmppar->id());
2753                         // a memory optimization: Just store the layout
2754                         // information when only edit
2755                         if (kind == Undo::EDIT){
2756                                 //tmppar2->next->text.clear();
2757                                 tmppar2->clearContents();
2758                         }
2759                         tmppar2->next()->previous(tmppar2);
2760                         tmppar2 = tmppar2->next();
2761                 }
2762                 tmppar2->next(0);
2763         } else
2764                 undopar = 0; // nothing to replace (undo of delete maybe)
2765
2766         int cursor_par = cursor.par()->id();
2767         int cursor_pos =  cursor.pos();
2768         
2769         Undo * undo = new Undo(kind, 
2770                                before_number, behind_number,  
2771                                cursor_par, cursor_pos, 
2772                                undopar);
2773   
2774         undo_finished = false;
2775         return undo;
2776 }
2777
2778
2779 void LyXText::setCursorParUndo(Buffer * buf)
2780 {
2781         if (inset_owner)
2782                 return;
2783         setUndo(buf, Undo::FINISH,
2784                 cursor.par()->previous(),
2785                 cursor.par()->next()); 
2786 }
2787
2788
2789 void LyXText::toggleAppendix(BufferView * bview)
2790 {
2791         Paragraph * par = cursor.par();
2792         bool start = !par->params().startOfAppendix();
2793
2794         // ensure that we have only one start_of_appendix in this document
2795         Paragraph * tmp = firstParagraph();
2796         for (; tmp; tmp = tmp->next())
2797                 tmp->params().startOfAppendix(false);
2798
2799         par->params().startOfAppendix(start);
2800
2801         // we can set the refreshing parameters now
2802         status = LyXText::NEED_MORE_REFRESH;
2803         refresh_y = 0;
2804         refresh_row = 0; // not needed for full update
2805         updateCounters(bview, 0);
2806         setCursor(bview, cursor.par(), cursor.pos());
2807 }
2808
2809
2810 Paragraph * LyXText::ownerParagraph() const
2811 {
2812         if (inset_owner)
2813                 return inset_owner->par;
2814
2815         return bv_owner->buffer()->paragraph;
2816 }
2817
2818
2819 Paragraph * LyXText::ownerParagraph(Paragraph * p) const
2820 {
2821         if (inset_owner)
2822                 inset_owner->par = p;
2823         else
2824                 bv_owner->buffer()->paragraph = p;
2825         return 0;
2826 }