Files
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

124 lines
3.3 KiB
C#

// RichTextKit
// Copyright © 2019-2020 Topten Software. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this product except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
// Ported from: https://github.com/foliojs/linebreak
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Topten.RichTextKit.Utils;
namespace Topten.RichTextKit
{
/// <summary>
/// Implementation of the word boundary algorithm
/// </summary>
internal class WordBoundaryAlgorithm
{
/// <summary>
/// Locate the start of each "word" in a unicode string. Used for Ctrl+Left/Right
/// in editor and different to the line break algorithm.
/// </summary>
public static IEnumerable<int> FindWordBoundaries( Slice<int> codePoints )
{
// Start is always a word boundary
yield return 0;
// Find all boundaries
bool inWord = false;
var wordGroup = WordBoundaryClass.Ignore;
for ( int i = 0; i < codePoints.Length; i++ )
{
// Get group
var bg = UnicodeClasses.BoundaryGroup( codePoints[i] );
// Ignore?
if ( bg == WordBoundaryClass.Ignore )
continue;
// Ignore spaces before word
if ( !inWord )
{
// Ignore spaces before word
if ( bg == WordBoundaryClass.Space )
continue;
// Found start of word
if ( i != 0 )
yield return i;
// We're now in the word
inWord = true;
wordGroup = bg;
continue;
}
// We're in a word group, check for change of kind
if ( wordGroup != bg )
{
if ( bg == WordBoundaryClass.Space )
{
inWord = false;
}
else
{
// Switch to a different word kind without a space
// just emit a word boundary here
yield return i;
}
}
}
if ( !inWord && codePoints.Length > 0 )
{
yield return codePoints.Length;
}
}
/// <summary>
/// Check if the characters at the boundary between strings is a word boundary
/// </summary>
/// <param name="a">The first string</param>
/// <param name="b">The second string</param>
/// <returns>True if this is a word boundary</returns>
public static bool IsWordBoundary( Slice<int> a, Slice<int> b )
{
// If either empty, assume it's a boundary
if ( a.Length == 0 )
return true;
if ( b.Length == 0 )
return true;
// Get the last non-ignore character from 'first string
var aGroup = WordBoundaryClass.Ignore;
for ( int i = a.Length - 1; i >= 0 && aGroup == WordBoundaryClass.Ignore; i-- )
{
aGroup = UnicodeClasses.BoundaryGroup( a[i] );
}
// Get the first non-ignore character from second string
var bGroup = WordBoundaryClass.Ignore;
for ( int i = 0; i < b.Length && bGroup == WordBoundaryClass.Ignore; i++ )
{
bGroup = UnicodeClasses.BoundaryGroup( b[i] );
}
// Check if boundary
return aGroup != bGroup && bGroup != WordBoundaryClass.Space;
}
}
}