public bool NextBreak(out LineBreak lineBreak) { // get the first char if we're at the beginning of the string if (_first) { _first = false; var firstClass = nextCharClass(); _curClass = mapFirst(firstClass); _nextClass = firstClass; _LB8a = (firstClass == LineBreakClass.ZWJ); _LB30a = 0; } while (_pos < _codePoints.Length) { _lastPos = _pos; var lastClass = _nextClass; _nextClass = nextCharClass(); // explicit newline if ((_curClass == LineBreakClass.BK) || ((_curClass == LineBreakClass.CR) && (_nextClass != LineBreakClass.LF))) { _curClass = mapFirst(mapClass(_nextClass)); lineBreak = new LineBreak(findPriorNonWhitespace(_lastPos), _lastPos, true); return(true); } bool?shouldBreak = getSimpleBreak(); if (!shouldBreak.HasValue) { shouldBreak = getPairTableBreak(lastClass); } // Rule LB8a _LB8a = (_nextClass == LineBreakClass.ZWJ); if (shouldBreak.Value) { lineBreak = new LineBreak(findPriorNonWhitespace(_lastPos), _lastPos, false); return(true); } } if (_lastPos < _codePoints.Length) { _lastPos = _codePoints.Length; var required = (_curClass == LineBreakClass.BK) || ((_curClass == LineBreakClass.CR) && (_nextClass != LineBreakClass.LF)); lineBreak = new LineBreak(findPriorNonWhitespace(_codePoints.Length), _lastPos, required); return(true); } else { lineBreak = new LineBreak(0, 0, false); return(false); } }
/// <summary> /// Get the next line break info /// </summary> /// <param name="lineBreak">A LineBreak structure returned by this method</param> /// <returns>True if there was another line break</returns> public bool NextBreak(out LineBreak lineBreak) { // get the first char if we're at the beginning of the string if (!_curClass.HasValue) { if (this.peekCharClass() == LineBreakClass.SP) { this._curClass = LineBreakClass.WJ; } else { this._curClass = mapFirst(this.readCharClass()); } } while (_pos < _codePoints.Length) { _lastPos = _pos; var lastClass = _nextClass; _nextClass = this.readCharClass(); // explicit newline if (_curClass.HasValue && ((_curClass == LineBreakClass.BK) || ((_curClass == LineBreakClass.CR) && (this._nextClass != LineBreakClass.LF)))) { _curClass = mapFirst(mapClass(_nextClass.Value)); lineBreak = new LineBreak(findPriorNonWhitespace(_lastPos), _lastPos, true); return(true); } // handle classes not handled by the pair table LineBreakClass?cur = null; switch (_nextClass.Value) { case LineBreakClass.SP: cur = _curClass; break; case LineBreakClass.BK: case LineBreakClass.LF: case LineBreakClass.NL: cur = LineBreakClass.BK; break; case LineBreakClass.CR: cur = LineBreakClass.CR; break; case LineBreakClass.CB: cur = LineBreakClass.BA; break; } if (cur != null) { _curClass = cur; if (_nextClass.HasValue && _nextClass.Value == LineBreakClass.CB) { lineBreak = new LineBreak(findPriorNonWhitespace(_lastPos), _lastPos); return(true); } continue; } // if not handled already, use the pair table var shouldBreak = false; switch (LineBreakPairTable.table[(int)this._curClass.Value][(int)this._nextClass.Value]) { case LineBreakPairTable.DI_BRK: // Direct break shouldBreak = true; break; case LineBreakPairTable.IN_BRK: // possible indirect break shouldBreak = lastClass.HasValue && lastClass.Value == LineBreakClass.SP; break; case LineBreakPairTable.CI_BRK: shouldBreak = lastClass.HasValue && lastClass.Value == LineBreakClass.SP; if (!shouldBreak) { continue; } break; case LineBreakPairTable.CP_BRK: // prohibited for combining marks if (!lastClass.HasValue || lastClass.Value != LineBreakClass.SP) { continue; } break; } _curClass = _nextClass; if (shouldBreak) { lineBreak = new LineBreak(findPriorNonWhitespace(_lastPos), _lastPos); return(true); } } if (_pos >= _codePoints.Length) { if (_lastPos < _codePoints.Length) { _lastPos = _codePoints.Length; var cls = UnicodeClasses.LineBreakClass(_codePoints[_codePoints.Length - 1]); bool required = cls == LineBreakClass.BK || cls == LineBreakClass.LF || cls == LineBreakClass.CR; lineBreak = new LineBreak(findPriorNonWhitespace(_codePoints.Length), _codePoints.Length, required); return(true); } } lineBreak = new LineBreak(0, 0, false); return(false); }