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