]> git.lyx.org Git - lyx.git/blob - src/BufferView.C
fix layouts in gbrief2 example
[lyx.git] / src / BufferView.C
1 /**
2  * \file BufferView.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alfredo Braunstein
7  * \author Lars Gullik Bjønnes
8  * \author John Levon
9  * \author André Pönitz
10  * \author Jürgen Vigna
11  *
12  * Full author contact details are available in file CREDITS.
13  */
14
15 #include <config.h>
16
17 #include "BufferView.h"
18
19 #include "buffer.h"
20 #include "bufferlist.h"
21 #include "BufferView_pimpl.h"
22 #include "debug.h"
23 #include "funcrequest.h"
24 #include "gettext.h"
25 #include "iterators.h"
26 #include "language.h"
27 #include "lyxlayout.h"
28 #include "lyxtext.h"
29 #include "paragraph.h"
30 #include "paragraph_funcs.h"
31 #include "PosIterator.h"
32 #include "texrow.h"
33 #include "undo.h"
34 #include "WordLangTuple.h"
35
36 #include "frontends/Alert.h"
37 #include "frontends/Dialogs.h"
38 #include "frontends/LyXView.h"
39 #include "frontends/screen.h"
40 #include "frontends/WorkArea.h"
41
42 #include "insets/insetcommand.h" // ChangeRefs
43 #include "insets/updatableinset.h"
44
45 #include "support/filetools.h"
46 #include "support/lyxalgo.h" // lyx_count
47
48 using lyx::support::bformat;
49 using lyx::support::MakeAbsPath;
50
51 using std::find;
52 using std::string;
53 using std::vector;
54
55
56 extern BufferList bufferlist;
57
58
59 BufferView::BufferView(LyXView * owner, int xpos, int ypos,
60                        int width, int height)
61         : pimpl_(new Pimpl(*this, owner, xpos, ypos, width, height)),
62           x_target_(0)
63 {}
64
65
66 BufferView::~BufferView()
67 {
68         delete pimpl_;
69 }
70
71
72 void BufferView::unsetXSel()
73 {
74         pimpl_->xsel_cache_.set = false;
75 }
76
77
78 Buffer * BufferView::buffer() const
79 {
80         return pimpl_->buffer_;
81 }
82
83
84 LyXScreen & BufferView::screen() const
85 {
86         return pimpl_->screen();
87 }
88
89
90 LyXView * BufferView::owner() const
91 {
92         return pimpl_->owner_;
93 }
94
95
96 Painter & BufferView::painter() const
97 {
98         return pimpl_->painter();
99 }
100
101
102 void BufferView::buffer(Buffer * b)
103 {
104         pimpl_->buffer(b);
105 }
106
107
108 bool BufferView::newFile(string const & fn, string const & tn, bool named)
109 {
110         return pimpl_->newFile(fn, tn, named);
111 }
112
113
114 bool BufferView::loadLyXFile(string const & fn, bool tl)
115 {
116         return pimpl_->loadLyXFile(fn, tl);
117 }
118
119
120 void BufferView::reload()
121 {
122         string const fn = buffer()->fileName();
123         if (bufferlist.close(buffer(), false))
124                 loadLyXFile(fn);
125 }
126
127
128 void BufferView::resize()
129 {
130         if (pimpl_->buffer_)
131                 pimpl_->resizeCurrentBuffer();
132 }
133
134
135 bool BufferView::fitCursor()
136 {
137         return pimpl_->fitCursor();
138 }
139
140
141 void BufferView::update()
142 {
143         pimpl_->update();
144 }
145
146
147 void BufferView::updateScrollbar()
148 {
149         pimpl_->updateScrollbar();
150 }
151
152
153 void BufferView::scrollDocView(int value)
154 {
155         pimpl_->scrollDocView(value);
156 }
157
158
159 void BufferView::redoCurrentBuffer()
160 {
161         pimpl_->redoCurrentBuffer();
162 }
163
164
165 bool BufferView::available() const
166 {
167         return pimpl_->available();
168 }
169
170
171 Change const BufferView::getCurrentChange()
172 {
173         return pimpl_->getCurrentChange();
174 }
175
176
177 void BufferView::savePosition(unsigned int i)
178 {
179         pimpl_->savePosition(i);
180 }
181
182
183 void BufferView::restorePosition(unsigned int i)
184 {
185         pimpl_->restorePosition(i);
186 }
187
188
189 bool BufferView::isSavedPosition(unsigned int i)
190 {
191         return pimpl_->isSavedPosition(i);
192 }
193
194
195 void BufferView::switchKeyMap()
196 {
197         pimpl_->switchKeyMap();
198 }
199
200
201 int BufferView::workWidth() const
202 {
203         return pimpl_->workarea().workWidth();
204 }
205
206
207 void BufferView::center()
208 {
209         pimpl_->center();
210 }
211
212
213 int BufferView::top_y() const
214 {
215         return pimpl_->top_y();
216 }
217
218
219 void BufferView::top_y(int y)
220 {
221         pimpl_->top_y(y);
222 }
223
224
225 string const BufferView::getClipboard() const
226 {
227         return pimpl_->workarea().getClipboard();
228 }
229
230
231 void BufferView::stuffClipboard(string const & stuff) const
232 {
233         pimpl_->stuffClipboard(stuff);
234 }
235
236
237 bool BufferView::dispatch(FuncRequest const & ev)
238 {
239         return pimpl_->dispatch(ev);
240 }
241
242
243 void BufferView::scroll(int lines)
244 {
245         pimpl_->scroll(lines);
246 }
247
248
249 // Inserts a file into current document
250 bool BufferView::insertLyXFile(string const & filen)
251         //
252         // Copyright CHT Software Service GmbH
253         // Uwe C. Schroeder
254         //
255         // Insert a LyXformat - file into current buffer
256         //
257         // Moved from lyx_cb.C (Lgb)
258 {
259         BOOST_ASSERT(!filen.empty());
260
261         string const fname = MakeAbsPath(filen);
262
263         clearSelection();
264         text()->breakParagraph(buffer()->paragraphs());
265
266         bool res = buffer()->readFile(fname, text()->cursorPar());
267         resize();
268         return res;
269 }
270
271
272 void BufferView::showErrorList(string const & action) const
273 {
274         if (getErrorList().size()) {
275                 string const title = bformat(_("LyX: %1$s errors (%2$s)"),
276                         action, buffer()->fileName());
277                 owner()->getDialogs().show("errorlist", title);
278                 pimpl_->errorlist_.clear();
279         }
280 }
281
282
283 ErrorList const & BufferView::getErrorList() const
284 {
285         return pimpl_->errorlist_;
286 }
287
288
289 void BufferView::setCursorFromRow(int row)
290 {
291         int tmpid = -1;
292         int tmppos = -1;
293
294         buffer()->texrow().getIdFromRow(row, tmpid, tmppos);
295
296         if (tmpid == -1)
297                 text()->setCursor(0, 0);
298         else
299                 text()->setCursor(buffer()->getParFromID(tmpid).pit(), tmppos);
300 }
301
302
303 bool BufferView::insertInset(InsetOld * inset, string const & lout)
304 {
305         return pimpl_->insertInset(inset, lout);
306 }
307
308
309 void BufferView::gotoLabel(string const & label)
310 {
311         for (Buffer::inset_iterator it = buffer()->inset_iterator_begin();
312              it != buffer()->inset_iterator_end(); ++it) {
313                 vector<string> labels;
314                 it->getLabelList(*buffer(), labels);
315                 if (find(labels.begin(),labels.end(),label) != labels.end()) {
316                         clearSelection();
317                         text()->setCursor(
318                                 std::distance(text()->paragraphs().begin(), it.getPar()),
319                                 it.getPos());
320                         resetAnchor();
321                         update();
322                         return;
323                 }
324         }
325 }
326
327
328 void BufferView::undo()
329 {
330         if (!available())
331                 return;
332
333         owner()->message(_("Undo"));
334         clearSelection();
335         if (!textUndo(this))
336                 owner()->message(_("No further undo information"));
337         update();
338         switchKeyMap();
339 }
340
341
342 void BufferView::redo()
343 {
344         if (!available())
345                 return;
346
347         owner()->message(_("Redo"));
348         clearSelection();
349         if (!textRedo(this))
350                 owner()->message(_("No further redo information"));
351         update();
352         switchKeyMap();
353 }
354
355
356 void BufferView::replaceWord(string const & replacestring)
357 {
358         if (!available())
359                 return;
360
361         LyXText * t = getLyXText();
362
363         t->replaceSelectionWithString(replacestring);
364         t->setSelectionRange(replacestring.length());
365
366         // Go back so that replacement string is also spellchecked
367         for (string::size_type i = 0; i < replacestring.length() + 1; ++i)
368                 t->cursorLeft(this);
369
370         // FIXME: should be done through LFUN
371         buffer()->markDirty();
372         update();
373 }
374
375
376 void BufferView::hideCursor()
377 {
378         screen().hideCursor();
379 }
380
381
382 bool BufferView::ChangeRefsIfUnique(string const & from, string const & to)
383 {
384         // Check if the label 'from' appears more than once
385         vector<string> labels;
386         buffer()->getLabelList(labels);
387
388         if (lyx::count(labels.begin(), labels.end(), from) > 1)
389                 return false;
390
391         return pimpl_->ChangeInsets(InsetOld::REF_CODE, from, to);
392 }
393
394
395 UpdatableInset * BufferView::innerInset() const
396 {
397         return static_cast<UpdatableInset*>(fullCursor().innerInset());
398 }
399
400
401 LyXText * BufferView::getLyXText() const
402 {
403         return fullCursor().innerText();
404 }
405
406
407 Language const * BufferView::getParentLanguage(InsetOld * inset) const
408 {
409         Paragraph const & par = ownerPar(*buffer(), inset);
410         return par.getFontSettings(buffer()->params(),
411                                    par.getPositionOfInset(inset)).language();
412 }
413
414
415 Encoding const * BufferView::getEncoding() const
416 {
417         LyXText * t = getLyXText();
418         if (!t)
419                 return 0;
420         return t->cursorPar()->getFont(
421                 buffer()->params(),
422                 t->cursor().pos(),
423                 outerFont(t->cursorPar(), t->paragraphs())
424         ).language()->encoding();
425 }
426
427
428 void BufferView::haveSelection(bool sel)
429 {
430         pimpl_->workarea().haveSelection(sel);
431 }
432
433
434 int BufferView::workHeight() const
435 {
436         return pimpl_->workarea().workHeight();
437 }
438
439
440 void BufferView::fullCursor(LCursor const & cur)
441 {
442         pimpl_->cursor_ = cur;
443 }
444
445
446 LCursor & BufferView::fullCursor()
447 {
448         return pimpl_->cursor_;
449 }
450
451
452 LCursor const & BufferView::fullCursor() const
453 {
454         return pimpl_->cursor_;
455 }
456
457
458 CursorSlice & BufferView::cursor()
459 {
460         return fullCursor().cursor_.back();
461 }
462
463
464 CursorSlice const & BufferView::cursor() const
465 {
466         return fullCursor().cursor_.back();
467 }
468
469
470 CursorSlice & BufferView::anchor()
471 {
472         return fullCursor().anchor_.back();
473 }
474
475
476 CursorSlice const & BufferView::anchor() const
477 {
478         return fullCursor().anchor_.back();
479 }
480
481
482 Selection & BufferView::selection()
483 {
484         return selection_;
485 }
486
487
488 Selection const & BufferView::selection() const
489 {
490         return selection_;
491 }
492
493
494 void BufferView::x_target(int x)
495 {
496         x_target_ = x;
497 }
498
499
500 int BufferView::x_target() const
501 {
502         return x_target_;
503 }
504
505
506 void BufferView::updateParagraphDialog()
507 {
508         pimpl_->updateParagraphDialog();
509 }
510
511
512 LyXText * BufferView::text() const
513 {
514         return pimpl_->buffer_ ? &pimpl_->buffer_->text() : 0;
515 }
516
517
518 void BufferView::resetAnchor()
519 {
520         return fullCursor().resetAnchor();
521 }
522
523
524 CursorSlice const & BufferView::selStart() const
525 {
526         if (!selection().set())
527                 return cursor();
528         // can't use std::min as this creates a new object
529         return anchor() < cursor() ? anchor() : cursor();
530 }
531
532
533 CursorSlice const & BufferView::selEnd() const
534 {
535         if (!selection().set())
536                 return cursor();
537         return anchor() > cursor() ? anchor() : cursor();
538 }
539
540
541 CursorSlice & BufferView::selStart()
542 {
543         if (!selection().set())
544                 return cursor();
545         return anchor() < cursor() ? anchor() : cursor();
546 }
547
548
549 CursorSlice & BufferView::selEnd()
550 {
551         if (selection().set())
552                 return cursor();
553         return anchor() > cursor() ? anchor() : cursor();
554 }
555
556
557 void BufferView::setSelection()
558 {
559         selection().set(true);
560         // a selection with no contents is not a selection
561         if (cursor().par() == anchor().par() && cursor().pos() == anchor().pos())
562                 selection().set(false);
563 }
564
565
566 void BufferView::clearSelection()
567 {
568         selection().set(false);
569         selection().mark(false);
570         resetAnchor();
571         unsetXSel();
572 }
573
574
575
576 /*
577 if the fitCursor call refers to some point in never-explored-land, then we
578 don't have y information in insets there, then we cannot even do an update
579 to get it (because we need the y infomation for setting top_y first). So
580 this is solved in put_selection_at with:
581
582 - setting top_y to the y of the outerPar (that has good info)
583 - calling update
584 - calling cursor().updatePos()
585 - then call fitCursor()
586
587 Ab.
588 */
589
590 void BufferView::putSelectionAt(PosIterator const & cur,
591                       int length, bool backwards)
592 {
593         ParIterator par(cur);
594         
595         clearSelection();
596
597         LyXText * text = par.text(*buffer());
598         par.lockPath(this);
599         // hack for the chicken and egg problem
600         if (par.inset())
601                 top_y(par.outerPar()->y);
602         update();
603         text->setCursor(cur.pit(), cur.pos());
604         fullCursor().updatePos();
605
606         if (length) {
607                 text->setSelectionRange(length);
608                 setSelection();
609                 if (backwards)
610                         std::swap(cursor(), anchor());
611         }
612
613         fitCursor();
614         update();
615 }
616
617
618 CursorSlice & cursorTip(BufferView & bv)
619 {
620         return bv.cursor();
621 }