]> git.lyx.org Git - lyx.git/blob - src/BufferView.C
Part of IU.
[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 {}
63
64
65 BufferView::~BufferView()
66 {
67         delete pimpl_;
68 }
69
70
71 void BufferView::unsetXSel()
72 {
73         pimpl_->xsel_cache_.set = false;
74 }
75
76
77 Buffer * BufferView::buffer() const
78 {
79         return pimpl_->buffer_;
80 }
81
82
83 LyXScreen & BufferView::screen() const
84 {
85         return pimpl_->screen();
86 }
87
88
89 LyXView * BufferView::owner() const
90 {
91         return pimpl_->owner_;
92 }
93
94
95 Painter & BufferView::painter() const
96 {
97         return pimpl_->painter();
98 }
99
100
101 void BufferView::buffer(Buffer * b)
102 {
103         pimpl_->buffer(b);
104 }
105
106
107 bool BufferView::newFile(string const & fn, string const & tn, bool named)
108 {
109         return pimpl_->newFile(fn, tn, named);
110 }
111
112
113 bool BufferView::loadLyXFile(string const & fn, bool tl)
114 {
115         return pimpl_->loadLyXFile(fn, tl);
116 }
117
118
119 void BufferView::reload()
120 {
121         string const fn = buffer()->fileName();
122         if (bufferlist.close(buffer(), false))
123                 loadLyXFile(fn);
124 }
125
126
127 void BufferView::resize()
128 {
129         if (pimpl_->buffer_)
130                 pimpl_->resizeCurrentBuffer();
131 }
132
133
134 bool BufferView::fitCursor()
135 {
136         return pimpl_->fitCursor();
137 }
138
139
140 void BufferView::update()
141 {
142         pimpl_->update();
143 }
144
145
146 void BufferView::updateScrollbar()
147 {
148         pimpl_->updateScrollbar();
149 }
150
151
152 void BufferView::scrollDocView(int value)
153 {
154         pimpl_->scrollDocView(value);
155 }
156
157
158 void BufferView::redoCurrentBuffer()
159 {
160         pimpl_->redoCurrentBuffer();
161 }
162
163
164 bool BufferView::available() const
165 {
166         return pimpl_->available();
167 }
168
169
170 Change const BufferView::getCurrentChange()
171 {
172         return pimpl_->getCurrentChange();
173 }
174
175
176 void BufferView::savePosition(unsigned int i)
177 {
178         pimpl_->savePosition(i);
179 }
180
181
182 void BufferView::restorePosition(unsigned int i)
183 {
184         pimpl_->restorePosition(i);
185 }
186
187
188 bool BufferView::isSavedPosition(unsigned int i)
189 {
190         return pimpl_->isSavedPosition(i);
191 }
192
193
194 void BufferView::switchKeyMap()
195 {
196         pimpl_->switchKeyMap();
197 }
198
199
200 int BufferView::workWidth() const
201 {
202         return pimpl_->workarea().workWidth();
203 }
204
205
206 void BufferView::center()
207 {
208         pimpl_->center();
209 }
210
211
212 int BufferView::top_y() const
213 {
214         return pimpl_->top_y();
215 }
216
217
218 void BufferView::top_y(int y)
219 {
220         pimpl_->top_y(y);
221 }
222
223
224 string const BufferView::getClipboard() const
225 {
226         return pimpl_->workarea().getClipboard();
227 }
228
229
230 void BufferView::stuffClipboard(string const & stuff) const
231 {
232         pimpl_->stuffClipboard(stuff);
233 }
234
235
236 bool BufferView::dispatch(FuncRequest const & ev)
237 {
238         return pimpl_->dispatch(ev);
239 }
240
241
242 void BufferView::scroll(int lines)
243 {
244         pimpl_->scroll(lines);
245 }
246
247
248 // Inserts a file into current document
249 bool BufferView::insertLyXFile(string const & filen)
250         //
251         // Copyright CHT Software Service GmbH
252         // Uwe C. Schroeder
253         //
254         // Insert a LyXformat - file into current buffer
255         //
256         // Moved from lyx_cb.C (Lgb)
257 {
258         BOOST_ASSERT(!filen.empty());
259
260         string const fname = MakeAbsPath(filen);
261
262         cursor().clearSelection();
263         text()->breakParagraph(buffer()->paragraphs());
264
265         bool res = buffer()->readFile(fname, text()->cursorPar());
266         resize();
267         return res;
268 }
269
270
271 void BufferView::showErrorList(string const & action) const
272 {
273         if (getErrorList().size()) {
274                 string const title = bformat(_("LyX: %1$s errors (%2$s)"),
275                         action, buffer()->fileName());
276                 owner()->getDialogs().show("errorlist", title);
277                 pimpl_->errorlist_.clear();
278         }
279 }
280
281
282 ErrorList const & BufferView::getErrorList() const
283 {
284         return pimpl_->errorlist_;
285 }
286
287
288 void BufferView::setCursorFromRow(int row)
289 {
290         int tmpid = -1;
291         int tmppos = -1;
292
293         buffer()->texrow().getIdFromRow(row, tmpid, tmppos);
294
295         if (tmpid == -1)
296                 text()->setCursor(0, 0);
297         else
298                 text()->setCursor(buffer()->getParFromID(tmpid).pit(), tmppos);
299 }
300
301
302 bool BufferView::insertInset(InsetOld * inset, string const & lout)
303 {
304         return pimpl_->insertInset(inset, lout);
305 }
306
307
308 void BufferView::gotoLabel(string const & label)
309 {
310         for (Buffer::inset_iterator it = buffer()->inset_iterator_begin();
311              it != buffer()->inset_iterator_end(); ++it) {
312                 vector<string> labels;
313                 it->getLabelList(*buffer(), labels);
314                 if (find(labels.begin(),labels.end(),label) != labels.end()) {
315                         cursor().clearSelection();
316                         text()->setCursor(
317                                 std::distance(text()->paragraphs().begin(), it.getPar()),
318                                 it.getPos());
319                         cursor().resetAnchor();
320                         update();
321                         return;
322                 }
323         }
324 }
325
326
327 void BufferView::undo()
328 {
329         if (!available())
330                 return;
331
332         owner()->message(_("Undo"));
333         cursor().clearSelection();
334         if (!textUndo(this))
335                 owner()->message(_("No further undo information"));
336         update();
337         switchKeyMap();
338 }
339
340
341 void BufferView::redo()
342 {
343         if (!available())
344                 return;
345
346         owner()->message(_("Redo"));
347         cursor().clearSelection();
348         if (!textRedo(this))
349                 owner()->message(_("No further redo information"));
350         update();
351         switchKeyMap();
352 }
353
354
355 void BufferView::replaceWord(string const & replacestring)
356 {
357         if (!available())
358                 return;
359
360         LyXText * t = getLyXText();
361
362         t->replaceSelectionWithString(replacestring);
363         t->setSelectionRange(replacestring.length());
364
365         // Go back so that replacement string is also spellchecked
366         for (string::size_type i = 0; i < replacestring.length() + 1; ++i)
367                 t->cursorLeft(this);
368
369         // FIXME: should be done through LFUN
370         buffer()->markDirty();
371         update();
372 }
373
374
375 void BufferView::hideCursor()
376 {
377         screen().hideCursor();
378 }
379
380
381 bool BufferView::ChangeRefsIfUnique(string const & from, string const & to)
382 {
383         // Check if the label 'from' appears more than once
384         vector<string> labels;
385         buffer()->getLabelList(labels);
386
387         if (lyx::count(labels.begin(), labels.end(), from) > 1)
388                 return false;
389
390         return pimpl_->ChangeInsets(InsetOld::REF_CODE, from, to);
391 }
392
393
394 LyXText * BufferView::getLyXText() const
395 {
396         return cursor().innerText();
397 }
398
399
400 Language const * BufferView::getParentLanguage(InsetOld * inset) const
401 {
402         Paragraph const & par = ownerPar(*buffer(), inset);
403         return par.getFontSettings(buffer()->params(),
404                                    par.getPositionOfInset(inset)).language();
405 }
406
407
408 Encoding const * BufferView::getEncoding() const
409 {
410         LyXText * t = getLyXText();
411         if (!t)
412                 return 0;
413         return t->cursorPar()->getFont(
414                 buffer()->params(),
415                 t->cursor().pos(),
416                 outerFont(t->cursorPar(), t->paragraphs())
417         ).language()->encoding();
418 }
419
420
421 void BufferView::haveSelection(bool sel)
422 {
423         pimpl_->workarea().haveSelection(sel);
424 }
425
426
427 int BufferView::workHeight() const
428 {
429         return pimpl_->workarea().workHeight();
430 }
431
432
433 void BufferView::updateParagraphDialog()
434 {
435         pimpl_->updateParagraphDialog();
436 }
437
438
439 LyXText * BufferView::text() const
440 {
441         return pimpl_->buffer_ ? &pimpl_->buffer_->text() : 0;
442 }
443
444
445
446
447 /*
448 if the fitCursor call refers to some point in never-explored-land, then we
449 don't have y information in insets there, then we cannot even do an update
450 to get it (because we need the y infomation for setting top_y first). So
451 this is solved in put_selection_at with:
452
453 - setting top_y to the y of the outerPar (that has good info)
454 - calling update
455 - calling cursor().updatePos()
456 - then call fitCursor()
457
458 Ab.
459 */
460
461 void BufferView::putSelectionAt(PosIterator const & cur,
462                       int length, bool backwards)
463 {
464         ParIterator par(cur);
465         
466         cursor().clearSelection();
467
468         LyXText * text = par.text(*buffer());
469         par.lockPath(this);
470         // hack for the chicken and egg problem
471         if (par.inset())
472                 top_y(par.outerPar()->y);
473         update();
474         text->setCursor(cur.pit(), cur.pos());
475         cursor().updatePos();
476
477         if (length) {
478                 text->setSelectionRange(length);
479                 cursor().setSelection();
480                 if (backwards)
481                         std::swap(cursor().cursor_, cursor().anchor_);
482         }
483
484         fitCursor();
485         update();
486 }
487
488
489 LCursor & BufferView::cursor()
490 {
491         return pimpl_->cursor_;
492 }
493
494
495 LCursor const & BufferView::cursor() const
496 {
497         return pimpl_->cursor_;
498 }
499