12 #include "BufferView_pimpl.h"
14 #include "lyxscreen.h"
18 #include "commandtags.h"
21 #include "bufferview_funcs.h"
22 #include "TextCache.h"
23 #include "bufferlist.h"
24 #include "lyx_gui_misc.h"
27 #include "support/LAssert.h"
28 #include "frontends/Dialogs.h"
29 #include "insets/insetbib.h"
30 #include "insets/insettext.h"
31 /// added for Dispatch functions
33 #include "frontends/FileDialog.h"
35 #include "FloatList.h"
36 #include "support/filetools.h"
37 #include "support/lyxfunctional.h"
38 #include "insets/inseturl.h"
39 #include "insets/insetlatexaccent.h"
40 #include "insets/insettoc.h"
41 #include "insets/insetref.h"
42 #include "insets/insetparent.h"
43 #include "insets/insetindex.h"
44 #include "insets/insetinfo.h"
45 #include "insets/insetinclude.h"
46 #include "insets/insetcite.h"
47 #include "insets/insetert.h"
48 #include "insets/insetexternal.h"
49 #include "insets/insetgraphics.h"
50 #include "insets/insetfoot.h"
51 #include "insets/insetmarginal.h"
52 #include "insets/insetminipage.h"
53 #include "insets/insetfloat.h"
54 #include "insets/insetlist.h"
55 #include "insets/insettabular.h"
56 #include "insets/insettheorem.h"
57 #include "insets/insetcaption.h"
58 #include "insets/insetfloatlist.h"
59 #include "insets/insetspecialchar.h"
61 #include "ParagraphParameters.h"
62 #include "mathed/formulabase.h"
64 extern LyXTextClass::size_type current_layout;
65 extern int greek_kb_flag;
76 /* the selection possible is needed, that only motion events are
77 * used, where the bottom press event was on the drawing area too */
78 bool selection_possible = false;
80 extern BufferList bufferlist;
81 extern char ascii_type;
83 extern bool math_insert_greek(BufferView *, char);
84 extern void sigchldhandler(pid_t pid, int * status);
85 extern int bibitemMaxWidth(BufferView *, LyXFont const &);
90 const unsigned int saved_positions_num = 20;
95 XSync(fl_get_display(), 0);
99 void SetXtermCursor(Window win)
101 static Cursor cursor;
102 static bool cursor_undefined = true;
103 if (cursor_undefined){
104 cursor = XCreateFontCursor(fl_get_display(), XC_xterm);
105 XFlush(fl_get_display());
106 cursor_undefined = false;
108 XDefineCursor(fl_get_display(), win, cursor);
109 XFlush(fl_get_display());
115 BufferView::Pimpl::Pimpl(BufferView * b, LyXView * o,
116 int xpos, int ypos, int width, int height)
117 : bv_(b), owner_(o), buffer_(0),
118 current_scrollbar_value(0), cursor_timeout(400),
119 workarea_(xpos, ypos, width, height), using_xterm_cursor(false),
123 workarea_.scrollCB.connect(slot(this, &BufferView::Pimpl::scrollCB));
124 workarea_.workAreaExpose
125 .connect(slot(this, &BufferView::Pimpl::workAreaExpose));
126 workarea_.workAreaEnter
127 .connect(slot(this, &BufferView::Pimpl::enterView));
128 workarea_.workAreaLeave
129 .connect(slot(this, &BufferView::Pimpl::leaveView));
130 workarea_.workAreaButtonPress
131 .connect(slot(this, &BufferView::Pimpl::workAreaButtonPress));
132 workarea_.workAreaButtonRelease
134 &BufferView::Pimpl::workAreaButtonRelease));
135 workarea_.workAreaMotionNotify
136 .connect(slot(this, &BufferView::Pimpl::workAreaMotionNotify));
137 workarea_.workAreaDoubleClick
138 .connect(slot(this, &BufferView::Pimpl::doubleClick));
139 workarea_.workAreaTripleClick
140 .connect(slot(this, &BufferView::Pimpl::tripleClick));
141 workarea_.workAreaKeyPress
142 .connect(slot(this, &BufferView::Pimpl::workAreaKeyPress));
144 cursor_timeout.timeout.connect(slot(this,
145 &BufferView::Pimpl::cursorToggle));
146 cursor_timeout.start();
147 workarea_.setFocus();
148 saved_positions.resize(saved_positions_num);
152 Painter & BufferView::Pimpl::painter()
154 return workarea_.getPainter();
158 void BufferView::Pimpl::buffer(Buffer * b)
160 lyxerr[Debug::INFO] << "Setting buffer in BufferView ("
164 buffer_->delUser(bv_);
166 // Put the old text into the TextCache, but
167 // only if the buffer is still loaded.
168 // Also set the owner of the test to 0
169 // bv_->text->owner(0);
170 textcache.add(buffer_, workarea_.workWidth(), bv_->text);
171 if (lyxerr.debugging())
172 textcache.show(lyxerr, "BufferView::buffer");
177 // Set current buffer
180 if (bufferlist.getState() == BufferList::CLOSING) return;
183 // screen is always deleted when the buffer is changed.
186 // If we are closing the buffer, use the first buffer as current
188 buffer_ = bufferlist.first();
192 lyxerr[Debug::INFO] << "Buffer addr: " << buffer_ << endl;
193 buffer_->addUser(bv_);
194 // If we don't have a text object for this, we make one
195 if (bv_->text == 0) {
196 resizeCurrentBuffer();
201 bv_->text->first = screen_->topCursorVisible(bv_->text);
202 owner_->updateMenubar();
203 owner_->updateToolbar();
204 // Similarly, buffer-dependent dialogs should be updated or
205 // hidden. This should go here because some dialogs (eg ToC)
206 // require bv_->text.
207 owner_->getDialogs()->updateBufferDependent(true);
211 lyxerr[Debug::INFO] << " No Buffer!" << endl;
212 owner_->updateMenubar();
213 owner_->updateToolbar();
214 owner_->getDialogs()->hideBufferDependent();
218 // Also remove all remaining text's from the testcache.
219 // (there should not be any!) (if there is any it is a
221 if (lyxerr.debugging())
222 textcache.show(lyxerr, "buffer delete all");
225 // should update layoutchoice even if we don't have a buffer.
226 owner_->updateLayoutChoice();
228 owner_->updateWindowTitle();
232 void BufferView::Pimpl::resize(int xpos, int ypos, int width, int height)
234 workarea_.resize(xpos, ypos, width, height);
235 update(bv_->text, SELECT);
240 void BufferView::Pimpl::resize()
243 resizeCurrentBuffer();
247 void BufferView::Pimpl::redraw()
249 lyxerr[Debug::INFO] << "BufferView::redraw()" << endl;
254 bool BufferView::Pimpl::fitCursor(LyXText * text)
256 lyx::Assert(screen_.get());
258 bv_->owner()->getDialogs()->updateParagraph();
260 bool const ret = screen_->fitCursor(text, bv_);
267 void BufferView::Pimpl::redoCurrentBuffer()
269 lyxerr[Debug::INFO] << "BufferView::redoCurrentBuffer" << endl;
270 if (buffer_ && bv_->text) {
272 owner_->updateLayoutChoice();
277 int BufferView::Pimpl::resizeCurrentBuffer()
279 lyxerr[Debug::INFO] << "resizeCurrentBuffer" << endl;
282 Paragraph * selstartpar = 0;
283 Paragraph * selendpar = 0;
284 UpdatableInset * the_locking_inset = 0;
286 Paragraph::size_type pos = 0;
287 Paragraph::size_type selstartpos = 0;
288 Paragraph::size_type selendpos = 0;
289 bool selection = false;
290 bool mark_set = false;
292 owner_->prohibitInput();
294 owner_->message(_("Formatting document..."));
297 par = bv_->text->cursor.par();
298 pos = bv_->text->cursor.pos();
299 selstartpar = bv_->text->selection.start.par();
300 selstartpos = bv_->text->selection.start.pos();
301 selendpar = bv_->text->selection.end.par();
302 selendpos = bv_->text->selection.end.pos();
303 selection = bv_->text->selection.set();
304 mark_set = bv_->text->selection.mark();
305 the_locking_inset = bv_->theLockingInset();
307 bv_->text = new LyXText(bv_);
308 bv_->text->init(bv_);
310 // See if we have a text in TextCache that fits
311 // the new buffer_ with the correct width.
312 bv_->text = textcache.findFit(buffer_, workarea_.workWidth());
314 if (lyxerr.debugging()) {
315 lyxerr << "Found a LyXText that fits:\n";
316 textcache.show(lyxerr, make_pair(buffer_, make_pair(workarea_.workWidth(), bv_->text)));
318 // Set the owner of the newly found text
319 // bv_->text->owner(bv_);
320 if (lyxerr.debugging())
321 textcache.show(lyxerr, "resizeCurrentBuffer");
323 bv_->text = new LyXText(bv_);
324 bv_->text->init(bv_);
330 bv_->text->selection.set(true);
331 /* at this point just to avoid the Delete-Empty-Paragraph
332 * Mechanism when setting the cursor */
333 bv_->text->selection.mark(mark_set);
335 bv_->text->setCursor(bv_, selstartpar, selstartpos);
336 bv_->text->selection.cursor = bv_->text->cursor;
337 bv_->text->setCursor(bv_, selendpar, selendpos);
338 bv_->text->setSelection(bv_);
339 bv_->text->setCursor(bv_, par, pos);
341 bv_->text->setCursor(bv_, par, pos);
342 bv_->text->selection.cursor = bv_->text->cursor;
343 bv_->text->selection.set(false);
345 // remake the inset locking
346 bv_->theLockingInset(the_locking_inset);
348 bv_->text->first = screen_->topCursorVisible(bv_->text);
349 buffer_->resizeInsets(bv_);
350 // this will scroll the screen such that the cursor becomes visible
355 owner_->allowInput();
357 /// clear the "Formatting Document" message
360 /// get rid of the splash screen if it's not gone already
361 owner_->getDialogs()->destroySplash();
367 void BufferView::Pimpl::updateScreen()
369 // Regenerate the screen.
370 screen_.reset(new LyXScreen(workarea_));
374 void BufferView::Pimpl::updateScrollbar()
376 /* If the text is smaller than the working area, the scrollbar
377 * maximum must be the working area height. No scrolling will
381 workarea_.setScrollbar(0, 1.0);
385 long const text_height = bv_->text->height;
387 double const lineh = bv_->text->defaultHeight();
388 double const slider_size = 1.0 / double(text_height);
390 static long old_text_height;
391 static double old_lineh;
392 static double old_slider_size;
394 if (text_height != old_text_height) {
395 workarea_.setScrollbarBounds(0, text_height - workarea_.height());
396 old_text_height = text_height;
398 if (lineh != old_lineh) {
399 workarea_.setScrollbarIncrements(lineh);
402 if (current_scrollbar_value != bv_->text->first
403 || slider_size != old_slider_size) {
404 current_scrollbar_value = bv_->text->first;
405 workarea_.setScrollbar(current_scrollbar_value, slider_size);
406 old_slider_size = slider_size;
411 // Callback for scrollbar slider
412 void BufferView::Pimpl::scrollCB(double value)
414 if (!buffer_) return;
416 current_scrollbar_value = long(value);
417 if (current_scrollbar_value < 0)
418 current_scrollbar_value = 0;
423 screen_->draw(bv_->text, bv_, current_scrollbar_value);
425 if (!lyxrc.cursor_follows_scrollbar) {
430 LyXText * vbt = bv_->text;
432 int const height = vbt->defaultHeight();
433 int const first = static_cast<int>((bv_->text->first + height));
434 int const last = static_cast<int>((bv_->text->first + workarea_.height() - height));
436 if (vbt->cursor.y() < first)
437 vbt->setCursorFromCoordinates(bv_, 0, first);
438 else if (vbt->cursor.y() > last)
439 vbt->setCursorFromCoordinates(bv_, 0, last);
445 int BufferView::Pimpl::scrollUp(long time)
447 if (!buffer_) return 0;
448 if (!screen_.get()) return 0;
450 double value = workarea_.getScrollbarValue();
452 if (value == 0) return 0;
454 float add_value = (bv_->text->defaultHeight()
455 + float(time) * float(time) * 0.125);
457 if (add_value > workarea_.height())
458 add_value = float(workarea_.height() -
459 bv_->text->defaultHeight());
466 workarea_.setScrollbarValue(value);
473 int BufferView::Pimpl::scrollDown(long time)
475 if (!buffer_) return 0;
476 if (!screen_.get()) return 0;
478 double value = workarea_.getScrollbarValue();
479 pair<float, float> p = workarea_.getScrollbarBounds();
480 double const max = p.second;
482 if (value == max) return 0;
484 float add_value = (bv_->text->defaultHeight()
485 + float(time) * float(time) * 0.125);
487 if (add_value > workarea_.height())
488 add_value = float(workarea_.height() -
489 bv_->text->defaultHeight());
496 workarea_.setScrollbarValue(value);
503 void BufferView::Pimpl::workAreaKeyPress(KeySym keysym, unsigned int state)
505 bv_->owner()->getLyXFunc()->processKeySym(keysym, state);
509 void BufferView::Pimpl::workAreaMotionNotify(int x, int y, unsigned int state)
511 // Only use motion with button 1
512 if (!(state & Button1MotionMask))
515 if (!buffer_ || !screen_.get()) return;
517 // Check for inset locking
518 if (bv_->theLockingInset()) {
519 LyXCursor cursor = bv_->text->cursor;
520 LyXFont font = bv_->text->getFont(buffer_,
521 cursor.par(), cursor.pos());
522 int width = bv_->theLockingInset()->width(bv_, font);
523 int inset_x = font.isVisibleRightToLeft()
524 ? cursor.x() - width : cursor.x();
525 int start_x = inset_x + bv_->theLockingInset()->scroll();
526 bv_->theLockingInset()->
527 insetMotionNotify(bv_,
529 y - cursor.y() + bv_->text->first,
534 /* The test for not selection possible is needed, that only motion
535 events are used, where the bottom press event was on
536 the drawing area too */
537 if (!selection_possible)
540 screen_->hideCursor();
542 bv_->text->setCursorFromCoordinates(bv_, x, y + bv_->text->first);
544 if (!bv_->text->selection.set())
545 update(bv_->text, BufferView::UPDATE); // Maybe an empty line was deleted
547 bv_->text->setSelection(bv_);
548 screen_->toggleToggle(bv_->text, bv_);
549 fitCursor(bv_->text);
550 screen_->showCursor(bv_->text, bv_);
554 // Single-click on work area
555 void BufferView::Pimpl::workAreaButtonPress(int xpos, int ypos,
558 if (!buffer_ || !screen_.get()) return;
560 Inset * inset_hit = checkInsetHit(bv_->text, xpos, ypos, button);
562 // ok ok, this is a hack.
563 if (button == 4 || button == 5) {
566 scrollUp(lyxrc.wheel_jump); // default 100, set in lyxrc
569 scrollDown(lyxrc.wheel_jump);
574 if (bv_->theLockingInset()) {
575 // We are in inset locking mode
577 /* Check whether the inset was hit. If not reset mode,
578 otherwise give the event to the inset */
579 if (inset_hit == bv_->theLockingInset()) {
580 bv_->theLockingInset()->
581 insetButtonPress(bv_,
586 bv_->unlockInset(bv_->theLockingInset());
591 selection_possible = true;
592 screen_->hideCursor();
594 int const screen_first = bv_->text->first;
596 // Middle button press pastes if we have a selection
597 bool paste_internally = false;
599 && bv_->text->selection.set()) {
600 owner_->getLyXFunc()->Dispatch(LFUN_COPY);
601 paste_internally = true;
604 // Clear the selection
605 screen_->toggleSelection(bv_->text, bv_);
606 bv_->text->clearSelection(bv_);
607 bv_->text->fullRebreak(bv_);
608 screen_->update(bv_->text, bv_);
611 // Single left click in math inset?
612 if ((inset_hit != 0) &&
613 (inset_hit->editable()==Inset::HIGHLY_EDITABLE)) {
614 // Highly editable inset, like math
615 UpdatableInset * inset = static_cast<UpdatableInset *>(inset_hit);
616 selection_possible = false;
617 owner_->updateLayoutChoice();
618 owner_->message(inset->editMessage());
619 inset->insetButtonPress(bv_, xpos, ypos, button);
620 inset->edit(bv_, xpos, ypos, button);
624 // Right click on a footnote flag opens float menu
626 selection_possible = false;
630 if (!inset_hit) // otherwise it was already set in checkInsetHit(...)
631 bv_->text->setCursorFromCoordinates(bv_, xpos, ypos + screen_first);
632 bv_->text->finishUndo();
633 bv_->text->selection.cursor = bv_->text->cursor;
634 bv_->text->cursor.x_fix(bv_->text->cursor.x());
636 owner_->updateLayoutChoice();
637 if (fitCursor(bv_->text)) {
638 selection_possible = false;
641 // Insert primary selection with middle mouse
642 // if there is a local selection in the current buffer,
645 if (paste_internally)
646 owner_->getLyXFunc()->Dispatch(LFUN_PASTE);
648 owner_->getLyXFunc()->Dispatch(LFUN_PASTESELECTION,
650 selection_possible = false;
656 void BufferView::Pimpl::doubleClick(int /*x*/, int /*y*/, unsigned int button)
662 LyXText * text = bv_->getLyXText();
664 if (text->bv_owner && bv_->theLockingInset())
667 if (screen_.get() && button == 1) {
668 if (text->bv_owner) {
669 screen_->hideCursor();
670 screen_->toggleSelection(text, bv_);
671 text->selectWord(bv_);
672 screen_->toggleSelection(text, bv_, false);
674 text->selectWord(bv_);
676 /* This will fit the cursor on the screen
678 update(text, BufferView::SELECT|BufferView::FITCUR);
683 void BufferView::Pimpl::tripleClick(int /*x*/, int /*y*/, unsigned int button)
689 LyXText * text = bv_->getLyXText();
691 if (text->bv_owner && bv_->theLockingInset())
694 if (screen_.get() && (button == 1)) {
695 screen_->hideCursor();
696 screen_->toggleSelection(text, bv_);
697 text->cursorHome(bv_);
698 text->selection.cursor = text->cursor;
699 text->cursorEnd(bv_);
700 text->setSelection(bv_);
701 screen_->toggleSelection(text, bv_, false);
702 /* This will fit the cursor on the screen
704 update(text, BufferView::SELECT|BufferView::FITCUR);
709 void BufferView::Pimpl::enterView()
711 if (active() && available()) {
712 SetXtermCursor(workarea_.getWin());
713 using_xterm_cursor = true;
718 void BufferView::Pimpl::leaveView()
720 if (using_xterm_cursor) {
721 XUndefineCursor(fl_get_display(), workarea_.getWin());
722 using_xterm_cursor = false;
727 void BufferView::Pimpl::workAreaButtonRelease(int x, int y,
730 if (!buffer_ || !screen_.get()) return;
732 // If we hit an inset, we have the inset coordinates in these
733 // and inset_hit points to the inset. If we do not hit an
734 // inset, inset_hit is 0, and inset_x == x, inset_y == y.
735 Inset * inset_hit = checkInsetHit(bv_->text, x, y, button);
737 if (bv_->theLockingInset()) {
738 // We are in inset locking mode.
740 /* LyX does a kind of work-area grabbing for insets.
741 Only a ButtonPress Event outside the inset will
742 force a insetUnlock. */
743 bv_->theLockingInset()->
744 insetButtonRelease(bv_, x, y, button);
748 selection_possible = false;
756 // Did we hit an editable inset?
758 // Inset like error, notes and figures
759 selection_possible = false;
761 // CHECK fix this proper in 0.13
763 // Following a ref shouldn't issue
764 // a push on the undo-stack
765 // anylonger, now that we have
766 // keybindings for following
767 // references and returning from
768 // references. IMHO though, it
769 // should be the inset's own business
770 // to push or not push on the undo
771 // stack. They don't *have* to
772 // alter the document...
774 // ...or maybe the SetCursorParUndo()
775 // below isn't necessary at all anylonger?
776 if (inset_hit->lyxCode() == Inset::REF_CODE) {
777 bv_->text->setCursorParUndo(buffer_);
780 owner_->message(inset_hit->editMessage());
782 if (inset_hit->editable()==Inset::HIGHLY_EDITABLE) {
783 // Highly editable inset, like math
784 UpdatableInset *inset = (UpdatableInset *)inset_hit;
785 inset->insetButtonRelease(bv_, x, y, button);
787 inset_hit->insetButtonRelease(bv_, x, y, button);
788 inset_hit->edit(bv_, x, y, button);
793 // check whether we want to open a float
797 if (bv_->text->cursor.pos() <
798 bv_->text->cursor.par()->size()) {
799 c = bv_->text->cursor.par()->
800 getChar(bv_->text->cursor.pos());
802 if (bv_->text->cursor.pos() - 1 >= 0) {
803 c = bv_->text->cursor.par()->
804 getChar(bv_->text->cursor.pos() - 1);
807 selection_possible = false;
812 // Maybe we want to edit a bibitem ale970302
813 if (bv_->text->cursor.par()->bibkey && x < 20 +
814 bibitemMaxWidth(bv_, textclasslist.
816 params.textclass).defaultfont())) {
817 bv_->text->cursor.par()->bibkey->edit(bv_, 0, 0, 0);
825 * Returns an inset if inset was hit. 0 otherwise.
826 * If hit, the coordinates are changed relative to the inset.
827 * Otherwise coordinates are not changed, and false is returned.
829 Inset * BufferView::Pimpl::checkInsetHit(LyXText * text, int & x, int & y,
830 unsigned int /* button */)
835 int y_tmp = y + text->first;
838 text->setCursorFromCoordinates(bv_, cursor, x, y_tmp);
839 text->setCursor(bv_, cursor, cursor.par(),cursor.pos(),true);
842 if (cursor.pos() < cursor.par()->size()
843 && cursor.par()->getChar(cursor.pos()) == Paragraph::META_INSET
844 && cursor.par()->getInset(cursor.pos())
845 && cursor.par()->getInset(cursor.pos())->editable()) {
847 // Check whether the inset really was hit
848 Inset * tmpinset = cursor.par()->getInset(cursor.pos());
849 LyXFont font = text->getFont(buffer_,
850 cursor.par(), cursor.pos());
851 int const width = tmpinset->width(bv_, font);
852 int const inset_x = font.isVisibleRightToLeft()
853 ? cursor.x() - width : cursor.x();
854 int const start_x = inset_x + tmpinset->scroll();
855 int const end_x = inset_x + width;
857 if (x > start_x && x < end_x
858 && y_tmp > cursor.y() - tmpinset->ascent(bv_, font)
859 && y_tmp < cursor.y() + tmpinset->descent(bv_, font)) {
860 text->setCursor(bv_, cursor.par(),cursor.pos(), true);
862 // The origin of an inset is on the baseline
863 y = y_tmp - (text->cursor.y());
868 if ((cursor.pos() - 1 >= 0) &&
869 (cursor.par()->getChar(cursor.pos()-1) == Paragraph::META_INSET) &&
870 (cursor.par()->getInset(cursor.pos() - 1)) &&
871 (cursor.par()->getInset(cursor.pos() - 1)->editable())) {
872 Inset * tmpinset = cursor.par()->getInset(cursor.pos()-1);
873 LyXFont font = text->getFont(buffer_, cursor.par(),
875 int const width = tmpinset->width(bv_, font);
876 int const inset_x = font.isVisibleRightToLeft()
877 ? cursor.x() : cursor.x() - width;
878 int const start_x = inset_x + tmpinset->scroll();
879 int const end_x = inset_x + width;
881 if (x > start_x && x < end_x
882 && y_tmp > cursor.y() - tmpinset->ascent(bv_, font)
883 && y_tmp < cursor.y() + tmpinset->descent(bv_, font)) {
885 if (move_cursor && (tmpinset != bv_->theLockingInset()))
887 text->setCursor(bv_, cursor.par(),
888 cursor.pos() - 1, true);
890 // The origin of an inset is on the baseline
891 y = y_tmp - (text->cursor.y());
899 void BufferView::Pimpl::workAreaExpose()
901 static int work_area_width;
902 static unsigned int work_area_height;
904 bool const widthChange = workarea_.workWidth() != work_area_width;
905 bool const heightChange = workarea_.height() != work_area_height;
907 // update from work area
908 work_area_width = workarea_.workWidth();
909 work_area_height = workarea_.height();
912 // The visible LyXView need a resize
915 // Remove all texts from the textcache
916 // This is not _really_ what we want to do. What
917 // we really want to do is to delete in textcache
918 // that does not have a BufferView with matching
919 // width, but as long as we have only one BufferView
920 // deleting all gives the same result.
921 if (lyxerr.debugging())
922 textcache.show(lyxerr, "Expose delete all");
924 } else if (heightChange) {
925 // Rebuild image of current screen
927 // fitCursor() ensures we don't jump back
928 // to the start of the document on vertical
930 fitCursor(bv_->text);
932 // The main window size has changed, repaint most stuff
934 } else if (screen_.get())
935 screen_->redraw(bv_->text, bv_);
937 // Grey box when we don't have a buffer
941 // always make sure that the scrollbar is sane.
943 owner_->updateLayoutChoice();
948 void BufferView::Pimpl::update()
951 (!bv_->theLockingInset() || !bv_->theLockingInset()->nodraw()))
953 screen_->update(bv_->text, bv_);
957 // Values used when calling update:
959 // -2 - update, move sel_cursor if selection, fitcursor
960 // -1 - update, move sel_cursor if selection, fitcursor, mark dirty
961 // 0 - update, move sel_cursor if selection, fitcursor
962 // 1 - update, move sel_cursor if selection, fitcursor, mark dirty
963 // 3 - update, move sel_cursor if selection
966 // a simple redraw of the parts that need refresh
968 // move sel_cursor if selection -
969 // the text's sel_cursor is moved if there is selection is progress
972 // fitCursor() is called and the scrollbar updated
975 // the buffer is marked dirty.
984 // UPDATE_ONLY = UPDATE;
985 // UPDATE_SELECT = UPDATE | SELECT;
986 // UPDATE_SELECT_MOVE = UPDATE | SELECT | FITCUR;
987 // UPDATE_SELECT_MOVE_AFTER_CHANGE = UPDATE | SELECT | FITCUR | CHANGE;
989 // update(-3) -> update(0) -> update(0) -> update(UPDATE)
990 // update(-2) -> update(1 + 2) -> update(3) -> update(SELECT|FITCUR)
991 // update(-1) -> update(1 + 2 + 4) -> update(7) -> update(SELECT|FITCUR|CHANGE)
992 // update(1) -> update(1 + 2 + 4) -> update(7) -> update(SELECT|FITCUR|CHANGE)
993 // update(3) -> update(1) -> update(1) -> update(SELECT)
995 void BufferView::Pimpl::update(LyXText * text, BufferView::UpdateCodes f)
997 owner_->updateLayoutChoice();
999 if (!text->selection.set() && (f & SELECT)) {
1000 text->selection.cursor = text->cursor;
1003 text->fullRebreak(bv_);
1005 if (text->inset_owner) {
1006 text->inset_owner->setUpdateStatus(bv_, InsetText::NONE);
1007 updateInset(text->inset_owner, true);
1016 buffer_->markDirty();
1021 // Callback for cursor timer
1022 void BufferView::Pimpl::cursorToggle()
1024 // Quite a nice place for asyncron Inset updating, isn't it?
1025 // Actually no! This is run even if no buffer exist... so (Lgb)
1027 cursor_timeout.restart();
1032 int const pid = waitpid(static_cast<pid_t>(0), &status, WNOHANG);
1033 if (pid == -1) // error find out what is wrong
1034 ; // ignore it for now.
1036 sigchldhandler(pid, &status);
1038 updatelist.update(bv_);
1040 if (!screen_.get()) {
1041 cursor_timeout.restart();
1045 if (!bv_->theLockingInset()) {
1046 screen_->cursorToggle(bv_->text, bv_);
1048 bv_->theLockingInset()->toggleInsetCursor(bv_);
1051 cursor_timeout.restart();
1055 void BufferView::Pimpl::cursorPrevious(LyXText * text)
1057 if (!text->cursor.row()->previous())
1060 int y = text->first;
1061 if (text->inset_owner)
1062 y += bv_->text->first;
1063 Row * cursorrow = text->cursor.row();
1064 text->setCursorFromCoordinates(bv_, bv_->text->cursor.x_fix(), y);
1065 bv_->text->finishUndo();
1066 // This is to allow jumping over large insets
1067 if ((cursorrow == text->cursor.row()))
1068 text->cursorUp(bv_);
1070 if (text->inset_owner ||
1071 text->cursor.row()->height() < workarea_.height())
1072 screen_->draw(bv_->text, bv_,
1074 - text->cursor.row()->baseline()
1075 + text->cursor.row()->height()
1076 - workarea_.height() + 1 );
1081 void BufferView::Pimpl::cursorNext(LyXText * text)
1083 if (!text->cursor.row()->next())
1086 int y = text->first + workarea_.height();
1087 // if (text->inset_owner)
1088 // y += bv_->text->first;
1089 text->getRowNearY(y);
1091 Row * cursorrow = text->cursor.row();
1092 text->setCursorFromCoordinates(bv_, text->cursor.x_fix(), y); // + workarea_->height());
1093 bv_->text->finishUndo();
1094 // This is to allow jumping over large insets
1095 if ((cursorrow == bv_->text->cursor.row()))
1096 text->cursorDown(bv_);
1098 if (text->inset_owner ||
1099 text->cursor.row()->height() < workarea_.height())
1100 screen_->draw(bv_->text, bv_, text->cursor.y() -
1101 text->cursor.row()->baseline());
1106 bool BufferView::Pimpl::available() const
1108 if (buffer_ && bv_->text) return true;
1113 void BufferView::Pimpl::beforeChange(LyXText * text)
1116 text->clearSelection(bv_);
1120 void BufferView::Pimpl::savePosition(unsigned int i)
1122 if (i >= saved_positions_num)
1124 saved_positions[i] = Position(buffer_->fileName(),
1125 bv_->text->cursor.par()->id(),
1126 bv_->text->cursor.pos());
1129 str << _("Saved bookmark") << ' ' << i;
1130 owner_->message(str.str().c_str());
1135 void BufferView::Pimpl::restorePosition(unsigned int i)
1137 if (i >= saved_positions_num)
1140 string const fname = saved_positions[i].filename;
1142 beforeChange(bv_->text);
1144 if (fname != buffer_->fileName()) {
1145 Buffer * b = bufferlist.exists(fname) ?
1146 bufferlist.getBuffer(fname) :
1147 bufferlist.loadLyXFile(fname); // don't ask, just load it
1148 if (b != 0 ) buffer(b);
1151 Paragraph * par = bv_->text->getParFromID(saved_positions[i].par_id);
1155 bv_->text->setCursor(bv_, par,
1156 min(par->size(), saved_positions[i].par_pos));
1158 update(bv_->text, BufferView::SELECT|BufferView::FITCUR);
1161 str << _("Moved to bookmark") << ' ' << i;
1162 owner_->message(str.str().c_str());
1167 bool BufferView::Pimpl::isSavedPosition(unsigned int i)
1169 if (i >= saved_positions_num)
1172 return !saved_positions[i].filename.empty();
1176 void BufferView::Pimpl::setState()
1178 if (!lyxrc.rtl_support)
1181 LyXText * text = bv_->getLyXText();
1182 if (text->real_current_font.isRightToLeft()
1185 text->real_current_font.latex() != LyXFont::ON
1188 if (owner_->getIntl()->keymap == Intl::PRIMARY)
1189 owner_->getIntl()->KeyMapSec();
1191 if (owner_->getIntl()->keymap == Intl::SECONDARY)
1192 owner_->getIntl()->KeyMapPrim();
1197 void BufferView::Pimpl::insetSleep()
1199 if (bv_->theLockingInset() && !inset_slept) {
1200 bv_->theLockingInset()->getCursorPos(bv_, bv_->slx, bv_->sly);
1201 bv_->theLockingInset()->insetUnlock(bv_);
1207 void BufferView::Pimpl::insetWakeup()
1209 if (bv_->theLockingInset() && inset_slept) {
1210 bv_->theLockingInset()->edit(bv_, bv_->slx, bv_->sly, 0);
1211 inset_slept = false;
1216 void BufferView::Pimpl::insetUnlock()
1218 if (bv_->theLockingInset()) {
1220 bv_->theLockingInset()->insetUnlock(bv_);
1221 bv_->theLockingInset(0);
1222 bv_->text->finishUndo();
1223 inset_slept = false;
1228 bool BufferView::Pimpl::focus() const
1230 return workarea_.hasFocus();
1234 void BufferView::Pimpl::focus(bool f)
1236 if (f) workarea_.setFocus();
1240 bool BufferView::Pimpl::active() const
1242 return workarea_.active();
1246 bool BufferView::Pimpl::belowMouse() const
1248 return workarea_.belowMouse();
1252 void BufferView::Pimpl::showCursor()
1255 screen_->showCursor(bv_->text, bv_);
1259 void BufferView::Pimpl::hideCursor()
1262 screen_->hideCursor();
1266 void BufferView::Pimpl::toggleSelection(bool b)
1269 screen_->toggleSelection(bv_->text, bv_, b);
1273 void BufferView::Pimpl::toggleToggle()
1276 screen_->toggleToggle(bv_->text, bv_);
1280 void BufferView::Pimpl::center()
1282 beforeChange(bv_->text);
1283 if (bv_->text->cursor.y() > static_cast<int>((workarea_.height() / 2))) {
1284 screen_->draw(bv_->text, bv_, bv_->text->cursor.y() - workarea_.height() / 2);
1286 screen_->draw(bv_->text, bv_, 0);
1288 update(bv_->text, BufferView::SELECT|BufferView::FITCUR);
1293 void BufferView::Pimpl::pasteClipboard(bool asPara)
1295 if (!buffer_) return;
1297 screen_->hideCursor();
1298 beforeChange(bv_->text);
1300 string const clip(workarea_.getClipboard());
1302 if (clip.empty()) return;
1305 bv_->text->insertStringAsParagraphs(bv_, clip);
1307 bv_->text->insertStringAsLines(bv_, clip);
1309 update(bv_->text, BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1313 void BufferView::Pimpl::stuffClipboard(string const & stuff) const
1315 workarea_.putClipboard(stuff);
1320 * Dispatch functions for actions which can be valid for BufferView->text
1321 * and/or InsetText->text!!!
1326 void BufferView::Pimpl::moveCursorUpdate(bool selecting)
1328 LyXText * lt = bv_->getLyXText();
1330 if (selecting || lt->selection.mark()) {
1331 lt->setSelection(bv_);
1335 update(lt, BufferView::SELECT|BufferView::FITCUR);
1338 /* ---> Everytime the cursor is moved, show the current font state. */
1339 // should this too me moved out of this func?
1340 //owner->showState();
1345 Inset * BufferView::Pimpl::getInsetByCode(Inset::Code code)
1347 LyXCursor cursor = bv_->getLyXText()->cursor;
1348 Buffer::inset_iterator it =
1349 find_if(Buffer::inset_iterator(
1350 cursor.par(), cursor.pos()),
1351 buffer_->inset_iterator_end(),
1352 lyx::compare_memfun(&Inset::lyxCode, code));
1353 return it != buffer_->inset_iterator_end() ? (*it) : 0;
1357 void BufferView::Pimpl::MenuInsertLyXFile(string const & filen)
1359 string filename = filen;
1361 if (filename.empty()) {
1362 // Launch a file browser
1363 string initpath = lyxrc.document_path;
1366 string const trypath = owner_->buffer()->filepath;
1367 // If directory is writeable, use this as default.
1368 if (IsDirWriteable(trypath) == 1)
1372 FileDialog fileDlg(bv_->owner(),
1373 _("Select LyX document to insert"),
1375 make_pair(string(_("Documents")),
1376 string(lyxrc.document_path)),
1377 make_pair(string(_("Examples")),
1378 string(AddPath(system_lyxdir, "examples"))));
1380 FileDialog::Result result =
1381 fileDlg.Select(initpath,
1382 _("*.lyx| LyX Documents (*.lyx)"));
1384 if (result.first == FileDialog::Later)
1387 filename = result.second;
1389 // check selected filename
1390 if (filename.empty()) {
1391 owner_->message(_("Canceled."));
1396 // get absolute path of file and add ".lyx" to the filename if
1398 filename = FileSearch(string(), filename, "lyx");
1400 string const disp_fn(MakeDisplayPath(filename));
1403 s1 << _("Inserting document") << ' '
1404 << disp_fn << " ...";
1405 owner_->message(s1.str().c_str());
1406 bool const res = bv_->insertLyXFile(filename);
1409 str << _("Document") << ' ' << disp_fn
1410 << ' ' << _("inserted.");
1411 owner_->message(str.str().c_str());
1414 str << _("Could not insert document") << ' '
1416 owner_->message(str.str().c_str());
1421 bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument)
1423 lyxerr[Debug::ACTION] << "BufferView::Pimpl::Dispatch: action["
1424 << action <<"] arg[" << argument << "]" << endl;
1427 // --- Misc -------------------------------------------
1431 LyXText * lt = bv_->getLyXText();
1432 lt->toggleAppendix(bv_);
1435 | BufferView::FITCUR
1436 | BufferView::CHANGE);
1441 case LFUN_TOC_INSERT:
1443 InsetCommandParams p;
1444 p.setCmdName("tableofcontents");
1445 Inset * inset = new InsetTOC(p);
1446 if (!insertInset(inset, "Standard"))
1451 case LFUN_TABULAR_FEATURE:
1452 case LFUN_SCROLL_INSET:
1453 // this is not handled here as this funktion is only aktive
1454 // if we have a locking_inset and that one is (or contains)
1458 case LFUN_INSET_GRAPHICS:
1460 Inset * new_inset = new InsetGraphics;
1461 if (!insertInset(new_inset)) {
1464 // this is need because you don't use a inset->Edit()
1465 updateInset(new_inset, true);
1466 new_inset->edit(bv_, 0, 0, 0);
1476 case LFUN_PASTESELECTION:
1478 bool asPara = false;
1479 if (argument == "paragraph") asPara = true;
1480 pasteClipboard(asPara);
1492 case LFUN_LAYOUT_COPY:
1493 bv_->copyEnvironment();
1496 case LFUN_LAYOUT_PASTE:
1497 bv_->pasteEnvironment();
1501 case LFUN_GOTOERROR:
1502 gotoInset(Inset::ERROR_CODE, false);
1506 gotoInset(Inset::IGNORE_CODE, false);
1509 case LFUN_REFERENCE_GOTO:
1511 vector<Inset::Code> tmp;
1512 tmp.push_back(Inset::LABEL_CODE);
1513 tmp.push_back(Inset::REF_CODE);
1514 gotoInset(tmp, true);
1518 case LFUN_HYPHENATION:
1526 case LFUN_END_OF_SENTENCE:
1530 case LFUN_MENU_SEPARATOR:
1539 changeDepth(bv_, bv_->getLyXText(), 0);
1542 case LFUN_DEPTH_MIN:
1543 changeDepth(bv_, bv_->getLyXText(), -1);
1546 case LFUN_DEPTH_PLUS:
1547 changeDepth(bv_, bv_->getLyXText(), 1);
1551 owner_->getDialogs()->setUserFreeFont();
1558 owner_->showState();
1562 case LFUN_FILE_INSERT:
1564 MenuInsertLyXFile(argument);
1568 case LFUN_FILE_INSERT_ASCII_PARA:
1569 InsertAsciiFile(bv_, argument, true);
1572 case LFUN_FILE_INSERT_ASCII:
1573 InsertAsciiFile(bv_, argument, false);
1578 lyxerr[Debug::INFO] << "LFUN_LAYOUT: (arg) "
1579 << argument << endl;
1581 // Derive layout number from given argument (string)
1582 // and current buffer's textclass (number). */
1583 LyXTextClassList::ClassList::size_type tclass =
1584 buffer_->params.textclass;
1585 pair <bool, LyXTextClass::size_type> layout =
1586 textclasslist.NumberOfLayout(tclass, argument);
1588 // If the entry is obsolete, use the new one instead.
1590 string obs = textclasslist.Style(tclass,layout.second)
1594 textclasslist.NumberOfLayout(tclass, obs);
1597 // see if we found the layout number:
1598 if (!layout.first) {
1599 owner_->getLyXFunc()->setErrorMessage(
1600 string(N_("Layout ")) + argument +
1605 if (current_layout != layout.second) {
1606 LyXText * lt = bv_->getLyXText();
1608 current_layout = layout.second;
1611 | BufferView::FITCUR);
1612 lt->setLayout(bv_, layout.second);
1613 owner_->setLayout(layout.second);
1616 | BufferView::FITCUR
1617 | BufferView::CHANGE);
1624 Lang(bv_, argument);
1626 owner_->showState();
1631 owner_->showState();
1636 owner_->showState();
1641 owner_->showState();
1646 owner_->showState();
1651 owner_->showState();
1656 owner_->showState();
1661 owner_->showState();
1664 case LFUN_UNDERLINE:
1666 owner_->showState();
1669 case LFUN_FONT_SIZE:
1670 FontSize(bv_, argument);
1671 owner_->showState();
1674 case LFUN_FONT_STATE:
1675 owner_->getLyXFunc()->setMessage(CurrentState(bv_));
1678 case LFUN_UPCASE_WORD:
1680 LyXText * lt = bv_->getLyXText();
1684 | BufferView::FITCUR);
1685 lt->changeCase(bv_, LyXText::text_uppercase);
1686 if (lt->inset_owner)
1687 updateInset(lt->inset_owner, true);
1690 | BufferView::FITCUR
1691 | BufferView::CHANGE);
1695 case LFUN_LOWCASE_WORD:
1697 LyXText * lt = bv_->getLyXText();
1699 update(lt, BufferView::SELECT|BufferView::FITCUR);
1700 lt->changeCase(bv_, LyXText::text_lowercase);
1701 if (lt->inset_owner)
1702 updateInset(lt->inset_owner, true);
1705 | BufferView::FITCUR
1706 | BufferView::CHANGE);
1710 case LFUN_CAPITALIZE_WORD:
1712 LyXText * lt = bv_->getLyXText();
1714 update(lt, BufferView::SELECT|BufferView::FITCUR);
1715 lt->changeCase(bv_, LyXText::text_capitalization);
1716 if (lt->inset_owner)
1717 updateInset(lt->inset_owner, true);
1720 | BufferView::FITCUR
1721 | BufferView::CHANGE);
1725 case LFUN_TRANSPOSE_CHARS:
1727 LyXText * lt = bv_->getLyXText();
1729 update(lt, BufferView::SELECT|BufferView::FITCUR);
1730 lt->transposeChars(*bv_);
1731 if (lt->inset_owner)
1732 updateInset(lt->inset_owner, true);
1735 | BufferView::FITCUR
1736 | BufferView::CHANGE);
1741 case LFUN_INSERT_LABEL:
1742 MenuInsertLabel(bv_, argument);
1745 case LFUN_REF_INSERT:
1746 if (argument.empty()) {
1747 InsetCommandParams p("ref");
1748 owner_->getDialogs()->createRef(p.getAsString());
1750 InsetCommandParams p;
1751 p.setFromString(argument);
1753 InsetRef * inset = new InsetRef(p, *buffer_);
1754 if (!insertInset(inset))
1757 updateInset(inset, true);
1761 case LFUN_BOOKMARK_SAVE:
1762 savePosition(strToUnsignedInt(argument));
1765 case LFUN_BOOKMARK_GOTO:
1766 restorePosition(strToUnsignedInt(argument));
1771 string label(argument);
1772 if (label.empty()) {
1774 static_cast<InsetRef*>(getInsetByCode(Inset::REF_CODE));
1776 label = inset->getContents();
1781 if (!label.empty()) {
1782 //bv_->savePosition(0);
1783 if (!bv_->gotoLabel(label))
1784 WriteAlert(_("Error"),
1785 _("Couldn't find this label"),
1786 _("in current document."));
1791 // --- Cursor Movements -----------------------------
1794 LyXText * lt = bv_->getLyXText();
1796 bool is_rtl = lt->cursor.par()->isRightToLeftPar(buffer_->params);
1797 if (!lt->selection.mark())
1799 update(lt, BufferView::SELECT|BufferView::FITCUR);
1801 lt->cursorLeft(bv_, false);
1802 if (lt->cursor.pos() < lt->cursor.par()->size()
1803 && lt->cursor.par()->getChar(lt->cursor.pos())
1804 == Paragraph::META_INSET
1805 && lt->cursor.par()->getInset(lt->cursor.pos())
1806 && lt->cursor.par()->getInset(lt->cursor.pos())->editable() == Inset::HIGHLY_EDITABLE){
1807 Inset * tmpinset = lt->cursor.par()->getInset(lt->cursor.pos());
1808 owner_->getLyXFunc()->setMessage(tmpinset->editMessage());
1811 LyXFont const font =
1812 lt->getFont(buffer_,
1815 y = tmpinset->descent(bv_,font);
1817 tmpinset->edit(bv_, 0, y, 0);
1821 lt->cursorRight(bv_, false);
1823 moveCursorUpdate(false);
1824 owner_->showState();
1830 // This is soooo ugly. Isn`t it possible to make
1831 // it simpler? (Lgb)
1832 LyXText * lt = bv_->getLyXText();
1833 bool is_rtl = lt->cursor.par()->isRightToLeftPar(buffer_->params);
1834 if (!lt->selection.mark())
1836 update(lt, BufferView::SELECT|BufferView::FITCUR);
1837 LyXCursor const cur = lt->cursor;
1839 lt->cursorLeft(bv_, false);
1840 if ((is_rtl || cur != lt->cursor) && // only if really moved!
1841 lt->cursor.pos() < lt->cursor.par()->size() &&
1842 (lt->cursor.par()->getChar(lt->cursor.pos()) ==
1843 Paragraph::META_INSET) &&
1844 lt->cursor.par()->getInset(lt->cursor.pos()) &&
1845 (lt->cursor.par()->getInset(lt->cursor.pos())->editable()
1846 == Inset::HIGHLY_EDITABLE))
1848 Inset * tmpinset = lt->cursor.par()->getInset(lt->cursor.pos());
1849 owner_->getLyXFunc()->setMessage(tmpinset->editMessage());
1850 LyXFont const font = lt->getFont(buffer_,
1854 : tmpinset->descent(bv_,font);
1857 tmpinset->width(bv_,font),
1862 lt->cursorRight(bv_, false);
1865 moveCursorUpdate(false);
1866 owner_->showState();
1872 LyXText * lt = bv_->getLyXText();
1874 if (!lt->selection.mark())
1876 update(lt, BufferView::UPDATE);
1879 moveCursorUpdate(false);
1880 owner_->showState();
1886 LyXText * lt = bv_->getLyXText();
1888 if (!lt->selection.mark())
1890 update(lt, BufferView::UPDATE);
1891 lt->cursorDown(bv_);
1893 moveCursorUpdate(false);
1894 owner_->showState();
1898 case LFUN_UP_PARAGRAPH:
1900 LyXText * lt = bv_->getLyXText();
1902 if (!lt->selection.mark())
1904 update(lt, BufferView::UPDATE);
1905 lt->cursorUpParagraph(bv_);
1907 moveCursorUpdate(false);
1908 owner_->showState();
1912 case LFUN_DOWN_PARAGRAPH:
1914 LyXText * lt = bv_->getLyXText();
1916 if (!lt->selection.mark())
1918 update(lt, BufferView::UPDATE);
1919 lt->cursorDownParagraph(bv_);
1921 moveCursorUpdate(false);
1922 owner_->showState();
1928 LyXText * lt = bv_->getLyXText();
1930 if (!lt->selection.mark())
1932 update(lt, BufferView::UPDATE);
1935 moveCursorUpdate(false);
1936 owner_->showState();
1942 LyXText * lt = bv_->getLyXText();
1944 if (!lt->selection.mark())
1946 update(lt, BufferView::UPDATE);
1949 moveCursorUpdate(false);
1950 owner_->showState();
1956 LyXText * lt = bv_->getLyXText();
1958 if (!lt->selection.mark())
1960 update(lt, BufferView::SELECT|BufferView::FITCUR);
1961 lt->cursorHome(bv_);
1963 moveCursorUpdate(false);
1964 owner_->showState();
1970 LyXText * lt = bv_->getLyXText();
1972 if (!lt->selection.mark())
1975 BufferView::SELECT|BufferView::FITCUR);
1978 moveCursorUpdate(false);
1979 owner_->showState();
1983 case LFUN_SHIFT_TAB:
1986 LyXText * lt = bv_->getLyXText();
1988 if (!lt->selection.mark())
1991 BufferView::SELECT|BufferView::FITCUR);
1994 moveCursorUpdate(false);
1995 owner_->showState();
1999 case LFUN_WORDRIGHT:
2001 LyXText * lt = bv_->getLyXText();
2003 if (!lt->selection.mark())
2005 update(lt, BufferView::SELECT|BufferView::FITCUR);
2006 if (lt->cursor.par()->isRightToLeftPar(buffer_->params))
2007 lt->cursorLeftOneWord(bv_);
2009 lt->cursorRightOneWord(bv_);
2011 moveCursorUpdate(false);
2012 owner_->showState();
2018 LyXText * lt = bv_->getLyXText();
2020 if (!lt->selection.mark())
2022 update(lt, BufferView::SELECT|BufferView::FITCUR);
2023 if (lt->cursor.par()->isRightToLeftPar(buffer_->params))
2024 lt->cursorRightOneWord(bv_);
2026 lt->cursorLeftOneWord(bv_);
2028 moveCursorUpdate(false);
2029 owner_->showState();
2033 case LFUN_BEGINNINGBUF:
2035 LyXText * lt = bv_->getLyXText();
2037 if (!lt->selection.mark())
2040 BufferView::SELECT|BufferView::FITCUR);
2043 moveCursorUpdate(false);
2044 owner_->showState();
2050 LyXText * lt = bv_->getLyXText();
2052 if (!lt->selection.mark())
2055 BufferView::SELECT|BufferView::FITCUR);
2056 lt->cursorBottom(bv_);
2058 moveCursorUpdate(false);
2059 owner_->showState();
2063 /* cursor selection ---------------------------- */
2066 LyXText * lt = bv_->getLyXText();
2069 BufferView::SELECT|BufferView::FITCUR);
2070 if (lt->cursor.par()->isRightToLeftPar(buffer_->params))
2071 lt->cursorLeft(bv_);
2073 lt->cursorRight(bv_);
2075 moveCursorUpdate(true);
2076 owner_->showState();
2082 LyXText * lt = bv_->getLyXText();
2085 BufferView::SELECT|BufferView::FITCUR);
2086 if (lt->cursor.par()->isRightToLeftPar(buffer_->params))
2087 lt->cursorRight(bv_);
2089 lt->cursorLeft(bv_);
2091 moveCursorUpdate(true);
2092 owner_->showState();
2098 LyXText * lt = bv_->getLyXText();
2101 BufferView::SELECT|BufferView::FITCUR);
2104 moveCursorUpdate(true);
2105 owner_->showState();
2111 LyXText * lt = bv_->getLyXText();
2114 BufferView::SELECT|BufferView::FITCUR);
2115 lt->cursorDown(bv_);
2117 moveCursorUpdate(true);
2118 owner_->showState();
2122 case LFUN_UP_PARAGRAPHSEL:
2124 LyXText * lt = bv_->getLyXText();
2127 BufferView::SELECT|BufferView::FITCUR);
2128 lt->cursorUpParagraph(bv_);
2130 moveCursorUpdate(true);
2131 owner_->showState();
2135 case LFUN_DOWN_PARAGRAPHSEL:
2137 LyXText * lt = bv_->getLyXText();
2140 BufferView::SELECT|BufferView::FITCUR);
2141 lt->cursorDownParagraph(bv_);
2143 moveCursorUpdate(true);
2144 owner_->showState();
2150 LyXText * lt = bv_->getLyXText();
2152 update(lt, BufferView::SELECT|BufferView::FITCUR);
2155 moveCursorUpdate(true);
2156 owner_->showState();
2162 LyXText * lt = bv_->getLyXText();
2164 update(lt, BufferView::SELECT|BufferView::FITCUR);
2167 moveCursorUpdate(true);
2168 owner_->showState();
2174 LyXText * lt = bv_->getLyXText();
2176 update(lt, BufferView::SELECT|BufferView::FITCUR);
2177 lt->cursorHome(bv_);
2179 moveCursorUpdate(true);
2180 owner_->showState();
2186 LyXText * lt = bv_->getLyXText();
2188 update(lt, BufferView::SELECT|BufferView::FITCUR);
2191 moveCursorUpdate(true);
2192 owner_->showState();
2196 case LFUN_WORDRIGHTSEL:
2198 LyXText * lt = bv_->getLyXText();
2200 update(lt, BufferView::SELECT|BufferView::FITCUR);
2201 if (lt->cursor.par()->isRightToLeftPar(buffer_->params))
2202 lt->cursorLeftOneWord(bv_);
2204 lt->cursorRightOneWord(bv_);
2206 moveCursorUpdate(true);
2207 owner_->showState();
2211 case LFUN_WORDLEFTSEL:
2213 LyXText * lt = bv_->getLyXText();
2215 update(lt, BufferView::SELECT|BufferView::FITCUR);
2216 if (lt->cursor.par()->isRightToLeftPar(buffer_->params))
2217 lt->cursorRightOneWord(bv_);
2219 lt->cursorLeftOneWord(bv_);
2221 moveCursorUpdate(true);
2222 owner_->showState();
2226 case LFUN_BEGINNINGBUFSEL:
2228 LyXText * lt = bv_->getLyXText();
2230 if (lt->inset_owner)
2232 update(lt, BufferView::SELECT|BufferView::FITCUR);
2235 moveCursorUpdate(true);
2236 owner_->showState();
2240 case LFUN_ENDBUFSEL:
2242 LyXText * lt = bv_->getLyXText();
2244 if (lt->inset_owner)
2247 BufferView::SELECT|BufferView::FITCUR);
2248 lt->cursorBottom(bv_);
2250 moveCursorUpdate(true);
2251 owner_->showState();
2255 // --- text changing commands ------------------------
2256 case LFUN_BREAKLINE:
2258 LyXText * lt = bv_->getLyXText();
2261 lt->insertChar(bv_, Paragraph::META_NEWLINE);
2264 | BufferView::FITCUR
2265 | BufferView::CHANGE);
2266 moveCursorUpdate(false);
2270 case LFUN_PROTECTEDSPACE:
2272 LyXText * lt = bv_->getLyXText();
2274 LyXLayout const & style = textclasslist
2275 .Style(buffer_->params.textclass,
2276 lt->cursor.par()->getLayout());
2278 if (style.free_spacing) {
2279 lt->insertChar(bv_, ' ');
2282 | BufferView::FITCUR
2283 | BufferView::CHANGE);
2287 moveCursorUpdate(false);
2293 LyXText * lt = bv_->getLyXText();
2295 if (lt->selection.mark()) {
2299 | BufferView::FITCUR);
2300 owner_->getLyXFunc()->setMessage(N_("Mark removed"));
2303 lt->selection.mark(true);
2306 | BufferView::FITCUR);
2307 owner_->getLyXFunc()->setMessage(N_("Mark set"));
2309 lt->selection.cursor = lt->cursor;
2315 LyXText * lt = bv_->getLyXText();
2317 if (!lt->selection.set()) {
2319 lt->selection.cursor = lt->cursor;
2322 | BufferView::FITCUR
2323 | BufferView::CHANGE);
2324 // It is possible to make it a lot faster still
2325 // just comment out the line below...
2330 moveCursorUpdate(false);
2331 owner_->showState();
2336 case LFUN_DELETE_SKIP:
2338 LyXText * lt = bv_->getLyXText();
2340 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
2342 LyXCursor cursor = lt->cursor;
2344 if (!lt->selection.set()) {
2345 if (cursor.pos() == cursor.par()->size()) {
2346 lt->cursorRight(bv_);
2347 cursor = lt->cursor;
2348 if (cursor.pos() == 0
2349 && !(cursor.par()->params().spaceTop()
2350 == VSpace (VSpace::NONE))) {
2353 cursor.par()->params().lineTop(),
2354 cursor.par()->params().lineBottom(),
2355 cursor.par()->params().pagebreakTop(),
2356 cursor.par()->params().pagebreakBottom(),
2357 VSpace(VSpace::NONE),
2358 cursor.par()->params().spaceBottom(),
2359 cursor.par()->params().align(),
2360 cursor.par()->params().labelWidthString(), 0);
2361 lt->cursorLeft(bv_);
2364 | BufferView::FITCUR
2365 | BufferView::CHANGE);
2367 lt->cursorLeft(bv_);
2369 lt->selection.cursor = lt->cursor;
2372 | BufferView::FITCUR
2373 | BufferView::CHANGE);
2377 lt->selection.cursor = lt->cursor;
2380 | BufferView::FITCUR
2381 | BufferView::CHANGE);
2389 /* -------> Delete word forward. */
2390 case LFUN_DELETE_WORD_FORWARD:
2391 update(bv_->getLyXText(), BufferView::SELECT|BufferView::FITCUR);
2392 bv_->getLyXText()->deleteWordForward(bv_);
2393 update(bv_->getLyXText(), BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2394 moveCursorUpdate(false);
2395 owner_->showState();
2398 /* -------> Delete word backward. */
2399 case LFUN_DELETE_WORD_BACKWARD:
2401 LyXText * lt = bv_->getLyXText();
2403 update(lt, BufferView::SELECT|BufferView::FITCUR);
2404 lt->deleteWordBackward(bv_);
2407 | BufferView::FITCUR
2408 | BufferView::CHANGE);
2409 moveCursorUpdate(false);
2410 owner_->showState();
2414 /* -------> Kill to end of line. */
2415 case LFUN_DELETE_LINE_FORWARD:
2417 LyXText * lt = bv_->getLyXText();
2419 update(lt, BufferView::SELECT|BufferView::FITCUR);
2420 lt->deleteLineForward(bv_);
2423 | BufferView::FITCUR
2424 | BufferView::CHANGE);
2425 moveCursorUpdate(false);
2429 /* -------> Set mark off. */
2432 LyXText * lt = bv_->getLyXText();
2435 update(lt, BufferView::SELECT|BufferView::FITCUR);
2436 lt->selection.cursor = lt->cursor;
2437 owner_->getLyXFunc()->setMessage(N_("Mark off"));
2441 /* -------> Set mark on. */
2444 LyXText * lt = bv_->getLyXText();
2447 lt->selection.mark(true);
2448 update(lt, BufferView::SELECT|BufferView::FITCUR);
2449 lt->selection.cursor = lt->cursor;
2450 owner_->getLyXFunc()->setMessage(N_("Mark on"));
2454 case LFUN_BACKSPACE:
2456 LyXText * lt = bv_->getLyXText();
2458 if (!lt->selection.set()) {
2459 if (owner_->getIntl()->getTrans().backspace()) {
2461 lt->selection.cursor = lt->cursor;
2464 | BufferView::FITCUR
2465 | BufferView::CHANGE);
2466 // It is possible to make it a lot faster still
2467 // just comment out the line below...
2473 owner_->showState();
2478 case LFUN_BACKSPACE_SKIP:
2480 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
2481 LyXText * lt = bv_->getLyXText();
2483 LyXCursor cursor = lt->cursor;
2485 if (!lt->selection.set()) {
2486 if (cursor.pos() == 0
2487 && !(cursor.par()->params().spaceTop()
2488 == VSpace (VSpace::NONE))) {
2491 cursor.par()->params().lineTop(),
2492 cursor.par()->params().lineBottom(),
2493 cursor.par()->params().pagebreakTop(),
2494 cursor.par()->params().pagebreakBottom(),
2495 VSpace(VSpace::NONE), cursor.par()->params().spaceBottom(),
2496 cursor.par()->params().align(),
2497 cursor.par()->params().labelWidthString(), 0);
2500 | BufferView::FITCUR
2501 | BufferView::CHANGE);
2504 lt->selection.cursor = cursor;
2507 | BufferView::FITCUR
2508 | BufferView::CHANGE);
2515 case LFUN_BREAKPARAGRAPH:
2517 LyXText * lt = bv_->getLyXText();
2520 lt->breakParagraph(bv_, 0);
2523 | BufferView::FITCUR
2524 | BufferView::CHANGE);
2525 lt->selection.cursor = lt->cursor;
2527 owner_->showState();
2531 case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
2533 LyXText * lt = bv_->getLyXText();
2536 lt->breakParagraph(bv_, 1);
2539 | BufferView::FITCUR
2540 | BufferView::CHANGE);
2541 lt->selection.cursor = lt->cursor;
2543 owner_->showState();
2547 case LFUN_BREAKPARAGRAPH_SKIP:
2549 // When at the beginning of a paragraph, remove
2550 // indentation and add a "defskip" at the top.
2551 // Otherwise, do the same as LFUN_BREAKPARAGRAPH.
2552 LyXText * lt = bv_->getLyXText();
2554 LyXCursor cursor = lt->cursor;
2557 if (cursor.pos() == 0) {
2558 if (cursor.par()->params().spaceTop() == VSpace(VSpace::NONE)) {
2561 cursor.par()->params().lineTop(),
2562 cursor.par()->params().lineBottom(),
2563 cursor.par()->params().pagebreakTop(),
2564 cursor.par()->params().pagebreakBottom(),
2565 VSpace(VSpace::DEFSKIP), cursor.par()->params().spaceBottom(),
2566 cursor.par()->params().align(),
2567 cursor.par()->params().labelWidthString(), 1);
2568 //update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2572 lt->breakParagraph(bv_, 0);
2573 //update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2578 | BufferView::FITCUR
2579 | BufferView::CHANGE);
2580 lt->selection.cursor = cursor;
2582 owner_->showState();
2586 case LFUN_PARAGRAPH_SPACING:
2588 LyXText * lt = bv_->getLyXText();
2590 Paragraph * par = lt->cursor.par();
2591 Spacing::Space cur_spacing = par->params().spacing().getSpace();
2592 float cur_value = 1.0;
2593 if (cur_spacing == Spacing::Other) {
2594 cur_value = par->params().spacing().getValue();
2597 istringstream istr(argument.c_str());
2601 Spacing::Space new_spacing = cur_spacing;
2602 float new_value = cur_value;
2604 lyxerr << "Missing argument to `paragraph-spacing'"
2606 } else if (tmp == "single") {
2607 new_spacing = Spacing::Single;
2608 } else if (tmp == "onehalf") {
2609 new_spacing = Spacing::Onehalf;
2610 } else if (tmp == "double") {
2611 new_spacing = Spacing::Double;
2612 } else if (tmp == "other") {
2613 new_spacing = Spacing::Other;
2616 lyxerr << "new_value = " << tmpval << endl;
2619 } else if (tmp == "default") {
2620 new_spacing = Spacing::Default;
2622 lyxerr << _("Unknown spacing argument: ")
2623 << argument << endl;
2625 if (cur_spacing != new_spacing || cur_value != new_value) {
2626 par->params().spacing(Spacing(new_spacing, new_value));
2627 lt->redoParagraph(bv_);
2630 | BufferView::FITCUR
2631 | BufferView::CHANGE);
2637 bv_->insertCorrectQuote();
2643 InsetCommandParams p;
2644 if (action == LFUN_HTMLURL)
2645 p.setCmdName("htmlurl");
2647 p.setCmdName("url");
2648 owner_->getDialogs()->createUrl( p.getAsString() );
2652 case LFUN_INSERT_URL:
2654 InsetCommandParams p;
2655 p.setFromString( argument );
2657 InsetUrl * inset = new InsetUrl( p );
2658 if (!insertInset(inset))
2661 updateInset( inset, true );
2665 case LFUN_INSET_TEXT:
2667 InsetText * new_inset = new InsetText;
2668 if (insertInset(new_inset))
2669 new_inset->edit(bv_, 0, 0, 0);
2675 case LFUN_INSET_ERT:
2677 InsetERT * new_inset = new InsetERT;
2678 if (insertInset(new_inset))
2679 new_inset->edit(bv_, 0, 0, 0);
2685 case LFUN_INSET_EXTERNAL:
2687 InsetExternal * new_inset = new InsetExternal;
2688 if (insertInset(new_inset))
2689 new_inset->edit(bv_, 0, 0, 0);
2695 case LFUN_INSET_FOOTNOTE:
2697 InsetFoot * new_inset = new InsetFoot;
2698 if (insertInset(new_inset))
2699 new_inset->edit(bv_, 0, 0, 0);
2705 case LFUN_INSET_MARGINAL:
2707 InsetMarginal * new_inset = new InsetMarginal;
2708 if (insertInset(new_inset))
2709 new_inset->edit(bv_, 0, 0, 0);
2715 case LFUN_INSET_MINIPAGE:
2717 InsetMinipage * new_inset = new InsetMinipage;
2718 if (insertInset(new_inset))
2719 new_inset->edit(bv_, 0, 0, 0);
2725 case LFUN_INSET_FLOAT:
2727 // check if the float type exist
2728 if (floatList.typeExist(argument)) {
2729 InsetFloat * new_inset = new InsetFloat(argument);
2730 if (insertInset(new_inset))
2731 new_inset->edit(bv_, 0, 0, 0);
2735 lyxerr << "Non-existant float type: "
2736 << argument << endl;
2742 case LFUN_INSET_WIDE_FLOAT:
2744 // check if the float type exist
2745 if (floatList.typeExist(argument)) {
2746 InsetFloat * new_inset = new InsetFloat(argument);
2747 new_inset->wide(true);
2748 if (insertInset(new_inset))
2749 new_inset->edit(bv_, 0, 0, 0);
2753 lyxerr << "Non-existant float type: "
2754 << argument << endl;
2760 case LFUN_INSET_LIST:
2762 InsetList * new_inset = new InsetList;
2763 if (insertInset(new_inset))
2764 new_inset->edit(bv_, 0, 0, 0);
2770 case LFUN_INSET_THEOREM:
2772 InsetTheorem * new_inset = new InsetTheorem;
2773 if (insertInset(new_inset))
2774 new_inset->edit(bv_, 0, 0, 0);
2780 case LFUN_INSET_CAPTION:
2782 // Do we have a locking inset...
2783 if (bv_->theLockingInset()) {
2784 lyxerr << "Locking inset code: "
2785 << static_cast<int>(bv_->theLockingInset()->lyxCode());
2786 InsetCaption * new_inset = new InsetCaption;
2787 new_inset->setOwner(bv_->theLockingInset());
2788 new_inset->setAutoBreakRows(true);
2789 new_inset->setDrawFrame(0, InsetText::LOCKED);
2790 new_inset->setFrameColor(0, LColor::captionframe);
2791 if (insertInset(new_inset))
2792 new_inset->edit(bv_, 0, 0, 0);
2799 case LFUN_INSET_TABULAR:
2803 if (!argument.empty())
2804 ::sscanf(argument.c_str(),"%d%d", &r, &c);
2805 InsetTabular * new_inset =
2806 new InsetTabular(*buffer_, r, c);
2808 bv_->getLyXText()->real_current_font.isRightToLeft();
2809 if (!open_new_inset(new_inset, rtl))
2814 // --- lyxserver commands ----------------------------
2816 case LFUN_CHARATCURSOR:
2818 Paragraph::size_type pos = bv_->getLyXText()->cursor.pos();
2819 if (pos < bv_->getLyXText()->cursor.par()->size())
2820 owner_->getLyXFunc()->setMessage(
2821 tostr(bv_->getLyXText()->cursor.par()->getChar(pos)));
2823 owner_->getLyXFunc()->setMessage("EOF");
2828 owner_->getLyXFunc()->setMessage(tostr(bv_->getLyXText()->cursor.x())
2830 + tostr(bv_->getLyXText()->cursor.y()));
2837 if (::sscanf(argument.c_str(), " %d %d", &x, &y) != 2) {
2838 lyxerr << "SETXY: Could not parse coordinates in '"
2839 << argument << std::endl;
2841 bv_->getLyXText()->setCursorFromCoordinates(bv_, x, y);
2845 case LFUN_GETLAYOUT:
2846 owner_->getLyXFunc()->setMessage(tostr(bv_->getLyXText()->cursor.par()->layout));
2851 LyXFont & font = bv_->getLyXText()->current_font;
2852 if (font.shape() == LyXFont::ITALIC_SHAPE)
2853 owner_->getLyXFunc()->setMessage("E");
2854 else if (font.shape() == LyXFont::SMALLCAPS_SHAPE)
2855 owner_->getLyXFunc()->setMessage("N");
2857 owner_->getLyXFunc()->setMessage("0");
2865 LyXFont & font = bv_->getLyXText()->current_font;
2866 if (font.latex() == LyXFont::ON)
2867 owner_->getLyXFunc()->setMessage("L");
2870 owner_->getLyXFunc()->setMessage("0");
2874 // --- accented characters ---------------------------
2877 case LFUN_CIRCUMFLEX:
2887 case LFUN_SPECIAL_CARON:
2890 case LFUN_HUNG_UMLAUT:
2893 if (argument.empty()) {
2895 owner_->getLyXFunc()->handleKeyFunc(action);
2897 owner_->getLyXFunc()->handleKeyFunc(action);
2898 owner_->getIntl()->getTrans()
2899 .TranslateAndInsert(argument[0], bv_->getLyXText());
2900 update(bv_->getLyXText(),
2902 | BufferView::FITCUR
2903 | BufferView::CHANGE);
2907 case LFUN_MATH_MACRO:
2908 mathDispatchMathMacro(bv_, argument);
2911 case LFUN_MATH_DELIM:
2912 mathDispatchMathDelim(bv_, argument);
2915 case LFUN_INSERT_MATRIX:
2916 mathDispatchInsertMatrix(bv_, argument);
2919 case LFUN_INSERT_MATH:
2920 mathDispatchInsertMath(bv_, argument);
2923 case LFUN_MATH_IMPORT_SELECTION: // Imports LaTeX from the X selection
2924 mathDispatchMathImportSelection(bv_, argument);
2927 case LFUN_MATH_DISPLAY: // Open or create a displayed math inset
2928 mathDispatchMathDisplay(bv_, argument);
2931 case LFUN_MATH_MODE: // Open or create an inlined math inset
2932 mathDispatchMathMode(bv_, argument);
2935 case LFUN_CITATION_INSERT:
2937 InsetCommandParams p;
2938 p.setFromString( argument );
2940 InsetCitation * inset = new InsetCitation( p );
2941 if (!insertInset(inset))
2944 updateInset( inset, true );
2948 case LFUN_INSERT_BIBTEX:
2950 // ale970405+lasgoutt970425
2951 // The argument can be up to two tokens separated
2952 // by a space. The first one is the bibstyle.
2953 string const db = token(argument, ' ', 0);
2954 string bibstyle = token(argument, ' ', 1);
2955 if (bibstyle.empty())
2958 InsetCommandParams p( "BibTeX", db, bibstyle );
2959 InsetBibtex * inset = new InsetBibtex(p);
2961 if (insertInset(inset)) {
2962 if (argument.empty())
2963 inset->edit(bv_, 0, 0, 0);
2969 // BibTeX data bases
2970 case LFUN_BIBDB_ADD:
2972 InsetBibtex * inset =
2973 static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
2975 inset->addDatabase(argument);
2980 case LFUN_BIBDB_DEL:
2982 InsetBibtex * inset =
2983 static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
2985 inset->delDatabase(argument);
2990 case LFUN_BIBTEX_STYLE:
2992 InsetBibtex * inset =
2993 static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
2995 inset->setOptions(argument);
3000 case LFUN_INDEX_CREATE:
3002 InsetCommandParams p( "index" );
3004 if (argument.empty()) {
3005 // Get the word immediately preceding the cursor
3006 Paragraph::size_type curpos =
3007 bv_->getLyXText()->cursor.pos() - 1;
3011 curstring = bv_->getLyXText()
3012 ->cursor.par()->getWord(curpos);
3014 p.setContents( curstring );
3016 p.setContents( argument );
3019 owner_->getDialogs()->createIndex( p.getAsString() );
3023 case LFUN_INDEX_INSERT:
3025 InsetCommandParams p;
3026 p.setFromString(argument);
3027 InsetIndex * inset = new InsetIndex(p);
3029 if (!insertInset(inset))
3032 updateInset(inset, true);
3036 case LFUN_INDEX_INSERT_LAST:
3038 // Get word immediately preceding the cursor
3039 Paragraph::size_type curpos =
3040 bv_->getLyXText()->cursor.pos() - 1;
3041 // Can't do that at the beginning of a paragraph
3042 if (curpos < 0) break;
3044 string const curstring(bv_->getLyXText()
3045 ->cursor.par()->getWord(curpos));
3047 InsetCommandParams p("index", curstring);
3048 InsetIndex * inset = new InsetIndex(p);
3050 if (!insertInset(inset))
3053 updateInset(inset, true);
3057 case LFUN_INDEX_PRINT:
3059 InsetCommandParams p("printindex");
3060 Inset * inset = new InsetPrintIndex(p);
3061 if (!insertInset(inset, "Standard"))
3066 case LFUN_PARENTINSERT:
3068 lyxerr << "arg " << argument << endl;
3069 InsetCommandParams p( "lyxparent", argument );
3070 Inset * inset = new InsetParent(p, *buffer_);
3071 if (!insertInset(inset, "Standard"))
3077 case LFUN_CHILD_INSERT:
3079 InsetInclude::Params p;
3080 p.cparams.setFromString(argument);
3081 p.masterFilename_ = buffer_->fileName();
3083 InsetInclude * inset = new InsetInclude(p);
3084 if (!insertInset(inset))
3087 updateInset(inset, true);
3088 bv_->owner()->getDialogs()->showInclude(inset);
3093 case LFUN_FLOAT_LIST:
3095 // We should check the argument for validity. (Lgb)
3096 Inset * inset = new InsetFloatList(argument);
3097 if (!insertInset(inset, "Standard"))
3102 case LFUN_INSERT_NOTE:
3106 case LFUN_SELFINSERT:
3108 if (argument.empty()) break;
3110 /* Automatically delete the currently selected
3111 * text and replace it with what is being
3112 * typed in now. Depends on lyxrc settings
3113 * "auto_region_delete", which defaults to
3116 LyXText * lt = bv_->getLyXText();
3118 if (lyxrc.auto_region_delete) {
3119 if (lt->selection.set()) {
3120 lt->cutSelection(bv_, false);
3123 | BufferView::FITCUR
3124 | BufferView::CHANGE);
3128 bv_->beforeChange(lt);
3129 LyXFont const old_font(lt->real_current_font);
3131 string::const_iterator cit = argument.begin();
3132 string::const_iterator end = argument.end();
3133 for (; cit != end; ++cit) {
3134 if (greek_kb_flag) {
3135 if (!math_insert_greek(bv_, *cit))
3136 owner_->getIntl()->getTrans().TranslateAndInsert(*cit, lt);
3138 owner_->getIntl()->getTrans().TranslateAndInsert(*cit, lt);
3143 | BufferView::FITCUR
3144 | BufferView::CHANGE);
3146 lt->selection.cursor = lt->cursor;
3147 moveCursorUpdate(false);
3149 // real_current_font.number can change so we need to
3150 // update the minibuffer
3151 if (old_font != lt->real_current_font)
3152 owner_->showState();
3157 case LFUN_DATE_INSERT: // jdblair: date-insert cmd
3159 time_t now_time_t = time(NULL);
3160 struct tm * now_tm = localtime(&now_time_t);
3161 setlocale(LC_TIME, "");
3163 if (!argument.empty())
3166 arg = lyxrc.date_insert_format;
3168 int const datetmp_len =
3169 ::strftime(datetmp, 32, arg.c_str(), now_tm);
3171 LyXText * lt = bv_->getLyXText();
3173 for (int i = 0; i < datetmp_len; i++) {
3174 lt->insertChar(bv_, datetmp[i]);
3177 | BufferView::FITCUR
3178 | BufferView::CHANGE);
3181 lt->selection.cursor = lt->cursor;
3182 moveCursorUpdate(false);
3186 case LFUN_UNKNOWN_ACTION:
3187 owner_->getLyXFunc()->setErrorMessage(N_("Unknown function!"));
3198 void BufferView::Pimpl::newline()
3201 LyXText * lt = bv_->getLyXText();
3205 | BufferView::FITCUR);
3206 lt->insertChar(bv_, Paragraph::META_NEWLINE);
3209 | BufferView::FITCUR
3210 | BufferView::CHANGE);
3215 void BufferView::Pimpl::hfill()
3218 LyXText * lt = bv_->getLyXText();
3222 | BufferView::FITCUR);
3223 lt->insertChar(bv_, Paragraph::META_HFILL);
3226 | BufferView::FITCUR
3227 | BufferView::CHANGE);
3232 void BufferView::Pimpl::protectedBlank(LyXText * lt)
3236 update(lt, BufferView::SELECT|BufferView::FITCUR);
3237 InsetSpecialChar * new_inset =
3238 new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
3239 if (!insertInset(new_inset))
3242 updateInset(new_inset, true);
3247 void BufferView::Pimpl::menuSeparator()
3250 LyXText * lt = bv_->getLyXText();
3253 update(lt, BufferView::SELECT|BufferView::FITCUR);
3254 InsetSpecialChar * new_inset =
3255 new InsetSpecialChar(InsetSpecialChar::MENU_SEPARATOR);
3256 insertInset(new_inset);
3261 void BufferView::Pimpl::endOfSentenceDot()
3265 update(bv_->getLyXText(), BufferView::SELECT|BufferView::FITCUR);
3266 InsetSpecialChar * new_inset =
3267 new InsetSpecialChar(InsetSpecialChar::END_OF_SENTENCE);
3268 insertInset(new_inset);
3273 void BufferView::Pimpl::ldots()
3277 update(bv_->getLyXText(), BufferView::SELECT|BufferView::FITCUR);
3278 InsetSpecialChar * new_inset =
3279 new InsetSpecialChar(InsetSpecialChar::LDOTS);
3280 insertInset(new_inset);
3285 void BufferView::Pimpl::hyphenationPoint()
3289 update(bv_->getLyXText(), BufferView::SELECT|BufferView::FITCUR);
3290 InsetSpecialChar * new_inset =
3291 new InsetSpecialChar(InsetSpecialChar::HYPHENATION);
3292 insertInset(new_inset);
3297 void BufferView::Pimpl::insertNote()
3299 InsetInfo * new_inset = new InsetInfo();
3300 insertInset(new_inset);
3301 new_inset->edit(bv_, 0, 0, 0);
3305 // Open and lock an updatable inset
3306 bool BufferView::Pimpl::open_new_inset(UpdatableInset * new_inset, bool behind)
3308 LyXText * lt = bv_->getLyXText();
3312 if (!insertInset(new_inset)) {
3317 LyXFont & font = lt->real_current_font;
3318 new_inset->edit(bv_, new_inset->width(bv_, font), 0, 0);
3320 new_inset->edit(bv_, 0, 0, 0);
3325 bool BufferView::Pimpl::insertInset(Inset * inset, string const & lout)
3327 // if we are in a locking inset we should try to insert the
3328 // inset there otherwise this is a illegal function now
3329 if (bv_->theLockingInset()) {
3330 if (bv_->theLockingInset()->insertInsetAllowed(inset))
3331 return bv_->theLockingInset()->insertInset(bv_, inset);
3335 // not quite sure if we want this...
3336 bv_->text->setCursorParUndo(buffer_);
3337 bv_->text->freezeUndo();
3339 beforeChange(bv_->text);
3340 if (!lout.empty()) {
3341 update(bv_->text, BufferView::SELECT|BufferView::FITCUR);
3342 bv_->text->breakParagraph(bv_);
3343 update(bv_->text, BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
3345 if (bv_->text->cursor.par()->size()) {
3346 bv_->text->cursorLeft(bv_);
3348 bv_->text->breakParagraph(bv_);
3349 update(bv_->text, BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
3352 pair<bool, LyXTextClass::size_type> lres =
3353 textclasslist.NumberOfLayout(buffer_->params
3355 LyXTextClass::size_type lay;
3356 if (lres.first != false) {
3360 // layout not fount using default "Standard" (0)
3364 bv_->text->setLayout(bv_, lay);
3366 bv_->text->setParagraph(bv_, 0, 0,
3368 VSpace(VSpace::NONE), VSpace(VSpace::NONE),
3372 update(bv_->text, BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
3374 bv_->text->current_font.setLatex(LyXFont::OFF);
3378 bv_->text->insertInset(bv_, inset);
3379 update(bv_->text, BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
3381 bv_->text->unFreezeUndo();
3386 void BufferView::Pimpl::updateInset(Inset * inset, bool mark_dirty)
3391 // first check for locking insets
3392 if (bv_->theLockingInset()) {
3393 if (bv_->theLockingInset() == inset) {
3394 if (bv_->text->updateInset(bv_, inset)) {
3397 buffer_->markDirty();
3402 } else if (bv_->theLockingInset()->updateInsetInInset(bv_, inset)) {
3403 if (bv_->text->updateInset(bv_,
3404 bv_->theLockingInset())) {
3407 buffer_->markDirty();
3415 // then check the current buffer
3418 update(bv_->text, BufferView::UPDATE);
3419 if (bv_->text->updateInset(bv_, inset)) {
3423 | BufferView::FITCUR
3424 | BufferView::CHANGE);
3426 update(bv_->text, SELECT);
3434 void BufferView::Pimpl::gotoInset(vector<Inset::Code> const & codes,
3437 if (!available()) return;
3440 beforeChange(bv_->text);
3441 update(bv_->text, BufferView::SELECT|BufferView::FITCUR);
3445 bv_->text->cursor.par()->getChar(bv_->text->cursor.pos()) == Paragraph::META_INSET) {
3446 Inset const * inset = bv_->text->cursor.par()->getInset(bv_->text->cursor.pos());
3447 if (find(codes.begin(), codes.end(), inset->lyxCode())
3450 static_cast<InsetCommand const *>(inset)->getContents();
3453 if (!bv_->text->gotoNextInset(bv_, codes, contents)) {
3454 if (bv_->text->cursor.pos()
3455 || bv_->text->cursor.par() != bv_->text->firstParagraph()) {
3456 LyXCursor tmp = bv_->text->cursor;
3457 bv_->text->cursor.par(bv_->text->firstParagraph());
3458 bv_->text->cursor.pos(0);
3459 if (!bv_->text->gotoNextInset(bv_, codes, contents)) {
3460 bv_->text->cursor = tmp;
3461 bv_->owner()->message(_("No more insets"));
3464 bv_->owner()->message(_("No more insets"));
3467 update(bv_->text, BufferView::SELECT|BufferView::FITCUR);
3468 bv_->text->selection.cursor = bv_->text->cursor;
3472 void BufferView::Pimpl::gotoInset(Inset::Code code, bool same_content)
3474 gotoInset(vector<Inset::Code>(1, code), same_content);