diff --git a/development/MacOSX/lyxrc.dist.in b/development/MacOSX/lyxrc.dist.in index c67f0afa6e..0ee4aac593 100644 --- a/development/MacOSX/lyxrc.dist.in +++ b/development/MacOSX/lyxrc.dist.in @@ -28,6 +28,7 @@ \screen_font_sans "Helvetica" \screen_font_typewriter "Courier" \open_buffers_in_tabs false +\mac_like_word_movement true # # COLOR SECTION ################################### diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp index 64d18fa590..3f9366cb04 100644 --- a/src/LyXRC.cpp +++ b/src/LyXRC.cpp @@ -111,6 +111,7 @@ LexerKeyword lyxrcTags[] = { { "\\language_package", LyXRC::RC_LANGUAGE_PACKAGE }, { "\\language_use_babel", LyXRC::RC_LANGUAGE_USE_BABEL }, { "\\load_session", LyXRC::RC_LOADSESSION }, + { "\\mac_like_word_movement", LyXRC::RC_MAC_LIKE_WORD_MOVEMENT }, { "\\macro_edit_style", LyXRC::RC_MACRO_EDIT_STYLE }, { "\\make_backup", LyXRC::RC_MAKE_BACKUP }, { "\\mark_foreign_language", LyXRC::RC_MARK_FOREIGN_LANGUAGE }, @@ -285,6 +286,7 @@ void LyXRC::setDefaults() tex_allows_spaces = false; date_insert_format = "%x"; cursor_follows_scrollbar = false; + mac_like_word_movement = false; macro_edit_style = MACRO_EDIT_INLINE_BOX; dialogs_iconify_with_main = false; label_init_length = 3; @@ -800,6 +802,10 @@ int LyXRC::read(Lexer & lexrc) lexrc >> cursor_follows_scrollbar; break; + case RC_MAC_LIKE_WORD_MOVEMENT: + lexrc >> mac_like_word_movement; + break; + case RC_MACRO_EDIT_STYLE: if (lexrc.next()) { switch (lexrc.getInteger()) { @@ -1488,6 +1494,15 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c } if (tag != RC_LAST) break; + case RC_MAC_LIKE_WORD_MOVEMENT: + if (ignore_system_lyxrc || + mac_like_word_movement + != system_lyxrc.mac_like_word_movement) { + os << "\\mac_like_word_movement " + << convert(mac_like_word_movement) << '\n'; + } + if (tag != RC_LAST) + break; case RC_MACRO_EDIT_STYLE: if (ignore_system_lyxrc || macro_edit_style @@ -2457,6 +2472,10 @@ string const LyXRC::getDescription(LyXRCTags tag) str = _("LyX normally doesn't update the cursor position if you move the scrollbar. Set to true if you'd prefer to always have the cursor on screen."); break; + case RC_MAC_LIKE_WORD_MOVEMENT: + str = _("Use the Mac OS X conventions for the word-level cursor movement"); + break; + case RC_SHOW_MACRO_LABEL: str = _("Show a small box around a Math Macro with the macro name when the cursor is inside."); break; diff --git a/src/LyXRC.h b/src/LyXRC.h index e51c233ed9..ae9ab388c9 100644 --- a/src/LyXRC.h +++ b/src/LyXRC.h @@ -62,6 +62,7 @@ public: RC_CONVERTER_CACHE_MAXAGE, RC_COPIER, RC_CURSOR_FOLLOWS_SCROLLBAR, + RC_MAC_LIKE_WORD_MOVEMENT, RC_CUSTOM_EXPORT_COMMAND, RC_CUSTOM_EXPORT_FORMAT, RC_DATE_INSERT_FORMAT, @@ -365,6 +366,8 @@ public: /// std::string gui_language; /// + bool mac_like_word_movement; + /// bool cursor_follows_scrollbar; /// enum MacroEditStyle { diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index 5eb3a67462..5fae6cf97e 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -2273,7 +2273,16 @@ bool Paragraph::isChar(pos_type pos) const if (Inset const * inset = getInset(pos)) return inset->isChar(); char_type const c = d->text_[pos]; - return !isLetterChar(c) && !isDigit(c); + return !isLetterChar(c) && !isDigit(c) && !lyx::isSpace(c); +} + + +bool Paragraph::isSpace(pos_type pos) const +{ + if (Inset const * inset = getInset(pos)) + return inset->isSpace(); + char_type const c = d->text_[pos]; + return lyx::isSpace(c); } diff --git a/src/Paragraph.h b/src/Paragraph.h index 267fc8de60..ac95de18e8 100644 --- a/src/Paragraph.h +++ b/src/Paragraph.h @@ -336,6 +336,8 @@ public: bool isLetter(pos_type pos) const; /// True if the element at this point is a character that is not a letter. bool isChar(pos_type pos) const; + /// True if the element at this point is a space + bool isSpace(pos_type pos) const; /// returns true if at least one line break or line separator has been deleted /// at the beginning of the paragraph (either physically or logically) diff --git a/src/Text.cpp b/src/Text.cpp index b655830651..44de33c46a 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -590,18 +590,37 @@ bool Text::cursorForwardOneWord(Cursor & cur) Paragraph const & par = cur.paragraph(); // Paragraph boundary is a word boundary - if (pos == lastpos && pit != cur.lastpit()) - return setCursor(cur, pit + 1, 0); + if (pos == lastpos) + if (pit != cur.lastpit()) + return setCursor(cur, pit + 1, 0); + else + return false; - // Skip over either a non-char inset or a full word - if (pos != lastpos && !par.isLetter(pos) && !par.isChar(pos)) - ++pos; - else while (pos != lastpos && par.isLetter(pos)) + if (lyxrc.mac_like_word_movement) { + // Skip through trailing punctuation and spaces. + while (pos != lastpos && par.isChar(pos)) + ++pos; + + // Skip over either a non-char inset or a full word + if (pos != lastpos && !par.isLetter(pos)) + ++pos; + else while (pos != lastpos && par.isLetter(pos)) + ++pos; + } else { + LASSERT(pos < lastpos, /**/); // see above + if (par.isLetter(pos)) + while (pos != lastpos && par.isLetter(pos)) + ++pos; + else if (par.isChar(pos)) + while (pos != lastpos && par.isChar(pos)) + ++pos; + else if (!par.isSpace(pos)) // non-char inset ++pos; - // Skip through trailing punctuation and spaces. - while (pos != lastpos && par.isChar(pos)) - ++pos; + // Skip over white space + while (pos != lastpos && par.isSpace(pos)) + ++pos; + } return setCursor(cur, pit, pos); } @@ -619,16 +638,31 @@ bool Text::cursorBackwardOneWord(Cursor & cur) if (pos == 0 && pit != 0) return setCursor(cur, pit - 1, getPar(pit - 1).size()); - // Skip through puctuation and spaces. - while (pos != 0 && par.isChar(pos - 1)) - --pos; - - // Skip over either a non-char inset or a full word - if (pos != 0 && !par.isLetter(pos - 1) && !par.isChar(pos - 1)) - --pos; - else while (pos != 0 && par.isLetter(pos - 1)) + if (lyxrc.mac_like_word_movement) { + // Skip through puctuation and spaces. + while (pos != 0 && par.isChar(pos - 1)) --pos; + // Skip over either a non-char inset or a full word + if (pos != 0 && !par.isLetter(pos - 1) && !par.isChar(pos - 1)) + --pos; + else while (pos != 0 && par.isLetter(pos - 1)) + --pos; + } else { + // Skip over white space + while (pos != 0 && par.isSpace(pos - 1)) + --pos; + + if (pos != 0 && par.isLetter(pos - 1)) + while (pos != 0 && par.isLetter(pos - 1)) + --pos; + else if (pos != 0 && par.isChar(pos - 1)) + while (pos != 0 && par.isChar(pos - 1)) + --pos; + else if (pos != 0 && !par.isSpace(pos - 1)) // non-char inset + --pos; + } + return setCursor(cur, pit, pos); }