]> git.lyx.org Git - lyx.git/blobdiff - src/text3.C
27 moved, 19 killed...
[lyx.git] / src / text3.C
index baf7d7318195020b307eb2b2301d9ea5c888fa43..007e0ab6e066d463e24fcf184c1c0748d03d7714 100644 (file)
 #include "ParagraphParameters.h"
 #include "gettext.h"
 #include "intl.h"
+#include "language.h"
 #include "support/lstrings.h"
 #include "frontends/LyXView.h"
+#include "frontends/screen.h"
 #include "frontends/WorkArea.h"
 #include "insets/insetspecialchar.h"
 #include "insets/insettext.h"
+#include "insets/insetquotes.h"
+#include "insets/insetcommand.h"
+#include "undo_funcs.h"
+
+#include <ctime>
+#include <clocale>
 
 using std::endl;
 
 extern string current_layout;
 
+namespace {
+
+       void finishChange(BufferView * bv, bool fitcur = false)
+       {
+               finishUndo();
+               bv->moveCursorUpdate(fitcur);
+               bv->owner()->view_state_changed();
+       }
+
+}
+
+
+bool LyXText::gotoNextInset(BufferView * bv,
+       vector<Inset::Code> const & codes, string const & contents) const
+{
+       LyXCursor res = cursor;
+       Inset * inset;
+       do {
+               if (res.pos() < res.par()->size() - 1) {
+                       res.pos(res.pos() + 1);
+               } else  {
+                       res.par(res.par()->next());
+                       res.pos(0);
+               }
+
+       } while (res.par() &&
+                !(res.par()->isInset(res.pos())
+                  && (inset = res.par()->getInset(res.pos())) != 0
+                  && find(codes.begin(), codes.end(), inset->lyxCode())
+                  != codes.end()
+                  && (contents.empty() ||
+                      static_cast<InsetCommand *>(
+                                                       res.par()->getInset(res.pos()))->getContents()
+                      == contents)));
+
+       if (res.par()) {
+               setCursor(bv, res.par(), res.pos(), false);
+               return true;
+       }
+       return false;
+}
+
+
+void LyXText::gotoInset(BufferView * bv, vector<Inset::Code> const & codes,
+                                 bool same_content)
+{
+       bv->hideCursor();
+       bv->beforeChange(this);
+       update(bv, false);
+
+       string contents;
+       if (same_content && cursor.par()->isInset(cursor.pos())) {
+               Inset const * inset = cursor.par()->getInset(cursor.pos());
+               if (find(codes.begin(), codes.end(), inset->lyxCode())
+                   != codes.end())
+                       contents = static_cast<InsetCommand const *>(inset)->getContents();
+       }
+
+       if (!gotoNextInset(bv, codes, contents)) {
+               if (cursor.pos() || cursor.par() != ownerParagraph()) {
+                       LyXCursor tmp = cursor;
+                       cursor.par(ownerParagraph());
+                       cursor.pos(0);
+                       if (!gotoNextInset(bv, codes, contents)) {
+                               cursor = tmp;
+                               bv->owner()->message(_("No more insets"));
+                       }
+               } else {
+                       bv->owner()->message(_("No more insets"));
+               }
+       }
+       update(bv, false);
+       selection.cursor = cursor;
+}
+
+
+void LyXText::gotoInset(BufferView * bv, Inset::Code code, bool same_content)
+{
+       gotoInset(bv, vector<Inset::Code>(1, code), same_content);
+}
+
+
+void LyXText::cursorPrevious(BufferView * bv)
+{
+       if (!cursor.row()->previous()) {
+               if (first_y > 0) {
+                       int new_y = bv->text->first_y - bv->workarea().workHeight();
+                       bv->screen().draw(bv->text, bv, new_y < 0 ? 0 : new_y);
+                       bv->updateScrollbar();
+               }
+               return;
+       }
+
+       int y = first_y;
+       Row * cursorrow = cursor.row();
+
+       setCursorFromCoordinates(bv, cursor.x_fix(), y);
+       finishUndo();
+
+       int new_y;
+       if (cursorrow == bv->text->cursor.row()) {
+               // we have a row which is higher than the workarea so we leave the
+               // cursor on the start of the row and move only the draw up as soon
+               // as we move the cursor or do something while inside the row (it may
+               // span several workarea-heights) we'll move to the top again, but this
+               // is better than just jump down and only display part of the row.
+               new_y = bv->text->first_y - bv->workarea().workHeight();
+       } else {
+               if (inset_owner) {
+                       new_y = bv->text->cursor.iy()
+                               + bv->theLockingInset()->insetInInsetY() + y
+                               + cursor.row()->height()
+                               - bv->workarea().workHeight() + 1;
+               } else {
+                       new_y = cursor.y()
+                               - cursor.row()->baseline()
+                               + cursor.row()->height()
+                               - bv->workarea().workHeight() + 1;
+               }
+       }
+       bv->screen().draw(bv->text, bv, new_y < 0 ? 0 : new_y);
+       if (cursor.row()->previous()) {
+               LyXCursor cur;
+               setCursor(bv, cur, cursor.row()->previous()->par(),
+                                               cursor.row()->previous()->pos(), false);
+               if (cur.y() > first_y) {
+                       cursorUp(bv, true);
+               }
+       }
+       bv->updateScrollbar();
+}
+
+
+void LyXText::cursorNext(BufferView * bv)
+{
+       if (!cursor.row()->next()) {
+               int y = cursor.y() - cursor.row()->baseline() +
+                       cursor.row()->height();
+               if (y > int(first_y + bv->workarea().workHeight())) {
+                       bv->screen().draw(bv->text, bv,
+                                                 bv->text->first_y + bv->workarea().workHeight());
+                       bv->updateScrollbar();
+               }
+               return;
+       }
+
+       int y = first_y + bv->workarea().workHeight();
+       if (inset_owner && !first_y) {
+               y -= (bv->text->cursor.iy()
+                         - bv->text->first_y
+                         + bv->theLockingInset()->insetInInsetY());
+       }
+
+       getRowNearY(y);
+
+       Row * cursorrow = cursor.row();
+       setCursorFromCoordinates(bv, cursor.x_fix(), y);
+       // + workarea().workHeight());
+       finishUndo();
+
+       int new_y;
+       if (cursorrow == bv->text->cursor.row()) {
+               // we have a row which is higher than the workarea so we leave the
+               // cursor on the start of the row and move only the draw down as soon
+               // as we move the cursor or do something while inside the row (it may
+               // span several workarea-heights) we'll move to the top again, but this
+               // is better than just jump down and only display part of the row.
+               new_y = bv->text->first_y + bv->workarea().workHeight();
+       } else {
+               if (inset_owner) {
+                       new_y = bv->text->cursor.iy()
+                               + bv->theLockingInset()->insetInInsetY()
+                               + y - cursor.row()->baseline();
+               } else {
+                       new_y =  cursor.y() - cursor.row()->baseline();
+               }
+       }
+       bv->screen().draw(bv->text, bv, new_y);
+       if (cursor.row()->next()) {
+               LyXCursor cur;
+               setCursor(bv, cur, cursor.row()->next()->par(),
+                                               cursor.row()->next()->pos(), false);
+               if (cur.y() < int(first_y + bv->workarea().workHeight())) {
+                       cursorDown(bv, true);
+               }
+       }
+       bv->updateScrollbar();
+}
+
 
 void LyXText::update(BufferView * bv, bool changed)
 {
@@ -57,6 +254,9 @@ void specialChar(LyXText * lt, BufferView * bv, InsetSpecialChar::Kind kind)
 
 Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
 {
+       lyxerr[Debug::ACTION] << "LyXFunc::dispatch: action[" << cmd.action
+                             <<"] arg[" << cmd.argument << "]" << endl;
+
        BufferView * bv = cmd.view();
 
        switch (cmd.action) {
@@ -87,7 +287,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                update(bv, false);
                deleteWordForward(bv);
                update(bv);
-               bv->finishChange();
+               finishChange(bv);
                break;
 
        case LFUN_DELETE_WORD_BACKWARD:
@@ -95,7 +295,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                update(bv, false);
                deleteWordBackward(bv);
                update(bv, true);
-               bv->finishChange();
+               finishChange(bv);
                break;
 
        case LFUN_DELETE_LINE_FORWARD:
@@ -103,7 +303,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                update(bv, false);
                deleteLineForward(bv);
                update(bv);
-               bv->finishChange();
+               finishChange(bv);
                break;
 
        case LFUN_SHIFT_TAB:
@@ -112,7 +312,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        bv->beforeChange(this);
                update(bv, false);
                cursorTab(bv);
-               bv->finishChange();
+               finishChange(bv);
                break;
 
        case LFUN_WORDRIGHT:
@@ -123,7 +323,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        cursorLeftOneWord(bv);
                else
                        cursorRightOneWord(bv);
-               bv->finishChange();
+               finishChange(bv);
                break;
 
        case LFUN_WORDLEFT:
@@ -134,7 +334,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        cursorRightOneWord(bv);
                else
                        cursorLeftOneWord(bv);
-               bv->finishChange();
+               finishChange(bv);
                break;
 
        case LFUN_BEGINNINGBUF:
@@ -142,7 +342,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        bv->beforeChange(this);
                update(bv, false);
                cursorTop(bv);
-               bv->finishChange();
+               finishChange(bv);
                break;
 
        case LFUN_ENDBUF:
@@ -150,7 +350,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        bv->beforeChange(this);
                update(bv, false);
                cursorBottom(bv);
-               bv->finishChange();
+               finishChange(bv);
                break;
 
        case LFUN_RIGHTSEL:
@@ -159,7 +359,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        cursorLeft(bv);
                else
                        cursorRight(bv);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_LEFTSEL:
@@ -168,55 +368,55 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        cursorRight(bv);
                else
                        cursorLeft(bv);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_UPSEL:
                update(bv, false);
                cursorUp(bv, true);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_DOWNSEL:
                update(bv, false);
                cursorDown(bv, true);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_UP_PARAGRAPHSEL:
                update(bv, false);
                cursorUpParagraph(bv);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_DOWN_PARAGRAPHSEL:
                update(bv, false);
                cursorDownParagraph(bv);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_PRIORSEL:
                update(bv, false);
-               bv->cursorPrevious(this);
-               bv->finishChange(true);
+               cursorPrevious(bv);
+               finishChange(bv, true);
                break;
 
        case LFUN_NEXTSEL:
                update(bv, false);
-               bv->cursorNext(this);
-               bv->finishChange();
+               cursorNext(bv);
+               finishChange(bv, true);
                break;
 
        case LFUN_HOMESEL:
                update(bv, false);
                cursorHome(bv);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_ENDSEL:
                update(bv, false);
                cursorEnd(bv);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_WORDRIGHTSEL:
@@ -225,7 +425,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        cursorLeftOneWord(bv);
                else
                        cursorRightOneWord(bv);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_WORDLEFTSEL:
@@ -234,7 +434,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        cursorRightOneWord(bv);
                else
                        cursorLeftOneWord(bv);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_RIGHT: {
@@ -254,7 +454,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                }
                if (!is_rtl)
                        cursorRight(bv, false);
-               bv->finishChange(false);
+               finishChange(bv);
                break;
        }
 
@@ -279,7 +479,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                }
                if (is_rtl)
                        cursorRight(bv, false);
-               bv->finishChange(false);
+               finishChange(bv);
                break;
        }
 
@@ -288,7 +488,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        bv->beforeChange(this);
                bv->update(this, BufferView::UPDATE);
                cursorUp(bv);
-               bv->finishChange(false);
+               finishChange(bv);
                break;
 
        case LFUN_DOWN:
@@ -296,7 +496,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        bv->beforeChange(this);
                bv->update(this, BufferView::UPDATE);
                cursorDown(bv);
-               bv->finishChange();
+               finishChange(bv);
                break;
 
        case LFUN_UP_PARAGRAPH:
@@ -304,7 +504,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        bv->beforeChange(this);
                bv->update(this, BufferView::UPDATE);
                cursorUpParagraph(bv);
-               bv->finishChange();
+               finishChange(bv);
                break;
 
        case LFUN_DOWN_PARAGRAPH:
@@ -312,15 +512,15 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        bv->beforeChange(this);
                bv->update(this, BufferView::UPDATE);
                cursorDownParagraph(bv);
-               bv->finishChange(false);
+               finishChange(bv, false);
                break;
 
        case LFUN_PRIOR:
                if (!selection.mark())
                        bv->beforeChange(this);
                bv->update(this, BufferView::UPDATE);
-               bv->cursorPrevious(this);
-               bv->finishChange(false);
+               cursorPrevious(bv);
+               finishChange(bv, false);
                // was:
                // finishUndo();
                // moveCursorUpdate(false, false);
@@ -331,8 +531,8 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                if (!selection.mark())
                        bv->beforeChange(this);
                bv->update(this, BufferView::UPDATE);
-               bv->cursorNext(this);
-               bv->finishChange(false);
+               cursorNext(bv);
+               finishChange(bv, false);
                break;
 
        case LFUN_HOME:
@@ -340,7 +540,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        bv->beforeChange(this);
                update(bv);
                cursorHome(bv);
-               bv->finishChange(false);
+               finishChange(bv, false);
                break;
 
        case LFUN_END:
@@ -348,7 +548,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        bv->beforeChange(this);
                update(bv);
                cursorEnd(bv);
-               bv->finishChange(false);
+               finishChange(bv, false);
                break;
 
        case LFUN_BREAKLINE:
@@ -368,7 +568,9 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        // just comment out the line below...
                        bv->showCursor();
                } else {
-                       bv->cut(false);
+                       update(bv, false);
+                       cutSelection(bv, true);
+                       update(bv);
                }
                bv->moveCursorUpdate(false);
                bv->owner()->view_state_changed();
@@ -401,15 +603,16 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                                        cursorLeft(bv);
                                        Delete(bv);
                                        selection.cursor = cursor;
-                                       update(bv);
                                }
                        } else {
                                Delete(bv);
                                selection.cursor = cursor;
-                               update(bv);
                        }
-               } else
-                       bv->cut(false);
+               } else {
+                       update(bv, false);
+                       cutSelection(bv, true);
+               }
+               update(bv);
                break;
 
 
@@ -423,8 +626,11 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                                // just comment out the line below...
                                bv->showCursor();
                        }
-               } else
-                       bv->cut(false);
+               } else {
+                       update(bv, false);
+                       cutSelection(bv, true);
+                       update(bv);
+               }
                bv->owner()->view_state_changed();
                bv->switchKeyMap();
                break;
@@ -445,14 +651,15 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                                         cur.par()->params().spacing(),
                                         cur.par()->params().align(),
                                         cur.par()->params().labelWidthString(), 0);
-                               update(bv);
                        } else {
                                backspace(bv);
                                selection.cursor = cur;
-                               update(bv);
                        }
-               } else
-                       bv->cut(false);
+               } else {
+                       update(bv, false);
+                       cutSelection(bv, true);
+               }
+               update(bv);
                break;
 
        case LFUN_BREAKPARAGRAPH:
@@ -652,12 +859,39 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                update(bv);
                break;
 
+       case LFUN_PASTE:
+               cmd.message(_("Paste"));
+               bv->hideCursor();
+               // clear the selection
+               bv->toggleSelection();
+               clearSelection();
+               update(bv, false);
+               pasteSelection(bv);
+               clearSelection(); // bug 393
+               update(bv, false);
+               update(bv);
+               bv->switchKeyMap();
+               break;
+
+       case LFUN_CUT:
+               bv->hideCursor();
+               update(bv, false);
+               cutSelection(bv, true);
+               update(bv);
+               cmd.message(_("Cut"));
+               break;
+
+       case LFUN_COPY:
+               copySelection(bv);
+               cmd.message(_("Copy"));
+               break;
+
        case LFUN_BEGINNINGBUFSEL:
                if (inset_owner)
                        return Inset::UNDISPATCHED;
                update(bv, false);
                cursorTop(bv);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_ENDBUFSEL:
@@ -665,7 +899,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                        return Inset::UNDISPATCHED;
                update(bv, false);
                cursorBottom(bv);
-               bv->finishChange(true);
+               finishChange(bv, true);
                break;
 
        case LFUN_GETXY:
@@ -675,10 +909,13 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
        case LFUN_SETXY: {
                int x = 0;
                int y = 0;
-               if (::sscanf(cmd.argument.c_str(), " %d %d", &x, &y) != 2)
+               istringstream is(cmd.argument.c_str());
+               is >> x >> y;
+               if (!is)
                        lyxerr << "SETXY: Could not parse coordinates in '"
                               << cmd.argument << std::endl;
-               setCursorFromCoordinates(bv, x, y);
+               else 
+                       setCursorFromCoordinates(bv, x, y);
                break;
        }
 
@@ -772,6 +1009,68 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
                break;
        }
 
+       case LFUN_GOTOERROR:
+               gotoInset(bv, Inset::ERROR_CODE, false);
+               break;
+
+       case LFUN_GOTONOTE:
+               gotoInset(bv, Inset::NOTE_CODE, false);
+               break;
+
+       case LFUN_REFERENCE_GOTO:
+       {
+               vector<Inset::Code> tmp;
+               tmp.push_back(Inset::LABEL_CODE);
+               tmp.push_back(Inset::REF_CODE);
+               gotoInset(bv, tmp, true);
+               break;
+       }
+
+       case LFUN_QUOTE: {
+               Paragraph const * par = cursor.par();
+               lyx::pos_type pos = cursor.pos();
+               char c;
+
+               if (!pos)
+                       c = ' ';
+               else if (par->isInset(pos - 1) && par->getInset(pos - 1)->isSpace())
+                       c = ' ';
+               else
+                       c = par->getChar(pos - 1);
+
+               bv->hideCursor();
+               LyXLayout_ptr const & style = par->layout();
+
+               if (style->pass_thru ||
+                               par->getFontSettings(bv->buffer()->params,
+                                        pos).language()->lang() == "hebrew" ||
+                       (!bv->insertInset(new InsetQuotes(c, bv->buffer()->params))))
+                       bv->owner()->dispatch(FuncRequest(LFUN_SELFINSERT, "\""));
+               break;
+       }
+
+       case LFUN_DATE_INSERT:  { // jdblair: date-insert cmd
+               time_t now_time_t = time(NULL);
+               struct tm * now_tm = localtime(&now_time_t);
+               setlocale(LC_TIME, "");
+               string arg;
+               if (!cmd.argument.empty())
+                       arg = cmd.argument;
+               else
+                       arg = lyxrc.date_insert_format;
+               char datetmp[32];
+               int const datetmp_len =
+                       ::strftime(datetmp, 32, arg.c_str(), now_tm);
+
+               for (int i = 0; i < datetmp_len; i++) {
+                       insertChar(bv, datetmp[i]);
+                       update(bv, true);
+               }
+               selection.cursor = cursor;
+               bv->moveCursorUpdate(false);
+               break;
+       }
+
        case LFUN_SELFINSERT: {
                if (cmd.argument.empty())
                        break;