+
+bool Document::IsWordPartSeparator(char ch) {
+ return (WordCharClass(ch) == CharClassify::ccWord) && IsPunctuation(ch);
+}
+
+int Document::WordPartLeft(int pos) {
+ if (pos > 0) {
+ --pos;
+ char startChar = cb.CharAt(pos);
+ if (IsWordPartSeparator(startChar)) {
+ while (pos > 0 && IsWordPartSeparator(cb.CharAt(pos))) {
+ --pos;
+ }
+ }
+ if (pos > 0) {
+ startChar = cb.CharAt(pos);
+ --pos;
+ if (IsLowerCase(startChar)) {
+ while (pos > 0 && IsLowerCase(cb.CharAt(pos)))
+ --pos;
+ if (!IsUpperCase(cb.CharAt(pos)) && !IsLowerCase(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsUpperCase(startChar)) {
+ while (pos > 0 && IsUpperCase(cb.CharAt(pos)))
+ --pos;
+ if (!IsUpperCase(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsADigit(startChar)) {
+ while (pos > 0 && IsADigit(cb.CharAt(pos)))
+ --pos;
+ if (!IsADigit(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsPunctuation(startChar)) {
+ while (pos > 0 && IsPunctuation(cb.CharAt(pos)))
+ --pos;
+ if (!IsPunctuation(cb.CharAt(pos)))
+ ++pos;
+ } else if (isspacechar(startChar)) {
+ while (pos > 0 && isspacechar(cb.CharAt(pos)))
+ --pos;
+ if (!isspacechar(cb.CharAt(pos)))
+ ++pos;
+ } else if (!isascii(startChar)) {
+ while (pos > 0 && !isascii(cb.CharAt(pos)))
+ --pos;
+ if (isascii(cb.CharAt(pos)))
+ ++pos;
+ } else {
+ ++pos;
+ }
+ }
+ }
+ return pos;
+}
+
+int Document::WordPartRight(int pos) {
+ char startChar = cb.CharAt(pos);
+ int length = Length();
+ if (IsWordPartSeparator(startChar)) {
+ while (pos < length && IsWordPartSeparator(cb.CharAt(pos)))
+ ++pos;
+ startChar = cb.CharAt(pos);
+ }
+ if (!isascii(startChar)) {
+ while (pos < length && !isascii(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsLowerCase(startChar)) {
+ while (pos < length && IsLowerCase(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsUpperCase(startChar)) {
+ if (IsLowerCase(cb.CharAt(pos + 1))) {
+ ++pos;
+ while (pos < length && IsLowerCase(cb.CharAt(pos)))
+ ++pos;
+ } else {
+ while (pos < length && IsUpperCase(cb.CharAt(pos)))
+ ++pos;
+ }
+ if (IsLowerCase(cb.CharAt(pos)) && IsUpperCase(cb.CharAt(pos - 1)))
+ --pos;
+ } else if (IsADigit(startChar)) {
+ while (pos < length && IsADigit(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsPunctuation(startChar)) {
+ while (pos < length && IsPunctuation(cb.CharAt(pos)))
+ ++pos;
+ } else if (isspacechar(startChar)) {
+ while (pos < length && isspacechar(cb.CharAt(pos)))
+ ++pos;
+ } else {
+ ++pos;
+ }
+ return pos;
+}
+
+bool IsLineEndChar(char c) {
+ return (c == '\n' || c == '\r');
+}
+
+int Document::ExtendStyleRange(int pos, int delta, bool singleLine) {
+ int sStart = cb.StyleAt(pos);
+ if (delta < 0) {
+ while (pos > 0 && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))) )
+ pos--;
+ pos++;
+ } else {
+ while (pos < (Length()) && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))) )
+ pos++;
+ }
+ return pos;
+}
+
+static char BraceOpposite(char ch) {
+ switch (ch) {
+ case '(':
+ return ')';
+ case ')':
+ return '(';
+ case '[':
+ return ']';
+ case ']':
+ return '[';
+ case '{':
+ return '}';
+ case '}':
+ return '{';
+ case '<':
+ return '>';
+ case '>':
+ return '<';
+ default:
+ return '\0';
+ }
+}
+
+// TODO: should be able to extend styled region to find matching brace
+int Document::BraceMatch(int position, int /*maxReStyle*/) {
+ char chBrace = CharAt(position);
+ char chSeek = BraceOpposite(chBrace);
+ if (chSeek == '\0')
+ return - 1;
+ char styBrace = static_cast<char>(StyleAt(position) & stylingBitsMask);
+ int direction = -1;
+ if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<')
+ direction = 1;
+ int depth = 1;
+ position = position + direction;
+ while ((position >= 0) && (position < Length())) {
+ position = MovePositionOutsideChar(position, direction);
+ char chAtPos = CharAt(position);
+ char styAtPos = static_cast<char>(StyleAt(position) & stylingBitsMask);
+ if ((position > GetEndStyled()) || (styAtPos == styBrace)) {
+ if (chAtPos == chBrace)
+ depth++;
+ if (chAtPos == chSeek)
+ depth--;
+ if (depth == 0)
+ return position;
+ }
+ position = position + direction;
+ }
+ return - 1;
+}