This commit is contained in:
muqing 2024-08-11 19:16:42 +08:00
parent 5a48d4041d
commit 66a3c6526f
98 changed files with 6629 additions and 28465 deletions

View File

@ -1,3 +0,0 @@
{
"help":"https://go.microsoft.com/fwlink/?linkid=866610"
}

View File

@ -5,15 +5,17 @@ VisualStudioVersion = 17.10.34928.147
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RustTools", "RustTools\RustTools.csproj", "{2B938A8C-2116-4961-A9D7-5A755FFC1943}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RustTools", "RustTools\RustTools.csproj", "{2B938A8C-2116-4961-A9D7-5A755FFC1943}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{64F47B2C-DECA-42CB-AE37-EE7DC9F0035E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TextControlBox", "TextControlBox\TextControlBox.csproj", "{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|arm64 = Debug|arm64 Debug|arm64 = Debug|arm64
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
Debug|x86 = Debug|x86 Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|arm64 = Release|arm64 Release|arm64 = Release|arm64
Release|x64 = Release|x64 Release|x64 = Release|x64
Release|x86 = Release|x86 Release|x86 = Release|x86
@ -22,6 +24,9 @@ Global
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|Any CPU.ActiveCfg = Debug|x64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|Any CPU.ActiveCfg = Debug|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|Any CPU.Build.0 = Debug|x64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|Any CPU.Build.0 = Debug|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|Any CPU.Deploy.0 = Debug|x64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|Any CPU.Deploy.0 = Debug|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|ARM.ActiveCfg = Debug|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|ARM.Build.0 = Debug|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|ARM.Deploy.0 = Debug|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|arm64.ActiveCfg = Debug|arm64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|arm64.ActiveCfg = Debug|arm64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|arm64.Build.0 = Debug|arm64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|arm64.Build.0 = Debug|arm64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|arm64.Deploy.0 = Debug|arm64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Debug|arm64.Deploy.0 = Debug|arm64
@ -34,6 +39,9 @@ Global
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|Any CPU.ActiveCfg = Release|x64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|Any CPU.ActiveCfg = Release|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|Any CPU.Build.0 = Release|x64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|Any CPU.Build.0 = Release|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|Any CPU.Deploy.0 = Release|x64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|Any CPU.Deploy.0 = Release|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|ARM.ActiveCfg = Release|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|ARM.Build.0 = Release|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|ARM.Deploy.0 = Release|x64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|arm64.ActiveCfg = Release|arm64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|arm64.ActiveCfg = Release|arm64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|arm64.Build.0 = Release|arm64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|arm64.Build.0 = Release|arm64
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|arm64.Deploy.0 = Release|arm64 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|arm64.Deploy.0 = Release|arm64
@ -43,6 +51,26 @@ Global
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|x86.ActiveCfg = Release|x86 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|x86.ActiveCfg = Release|x86
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|x86.Build.0 = Release|x86 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|x86.Build.0 = Release|x86
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|x86.Deploy.0 = Release|x86 {2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|x86.Deploy.0 = Release|x86
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|ARM.ActiveCfg = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|ARM.Build.0 = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|arm64.ActiveCfg = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|arm64.Build.0 = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|x64.ActiveCfg = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|x64.Build.0 = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|x86.ActiveCfg = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|x86.Build.0 = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|Any CPU.Build.0 = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|ARM.ActiveCfg = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|ARM.Build.0 = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|arm64.ActiveCfg = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|arm64.Build.0 = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|x64.ActiveCfg = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|x64.Build.0 = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|x86.ActiveCfg = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -47,10 +47,6 @@ public partial class App : Microsoft.UI.Xaml.Application
public App() public App()
{ {
InitializeComponent(); InitializeComponent();
//if (!Directory.Exists(wj.CD))
//{
// Directory.CreateDirectory(wj.CD);
//}
// 注册激活事件处理程序 // 注册激活事件处理程序
Host = Microsoft.Extensions.Hosting.Host. Host = Microsoft.Extensions.Hosting.Host.
CreateDefaultBuilder(). CreateDefaultBuilder().
@ -136,26 +132,18 @@ public partial class App : Microsoft.UI.Xaml.Application
} }
return; return;
} }
// If this is the first instance launched, then register it as the "main" instance.
// If this isn't the first instance launched, then "main" will already be registered,
// so retrieve it.
var mainInstance = Microsoft.Windows.AppLifecycle.AppInstance.FindOrRegisterForKey("main"); var mainInstance = Microsoft.Windows.AppLifecycle.AppInstance.FindOrRegisterForKey("main");
// If the instance that's executing the OnLaunched handler right now
// isn't the "main" instance.
if (!mainInstance.IsCurrent) if (!mainInstance.IsCurrent)
{ {
// Redirect the activation (and args) to the "main" instance, and exit.
await mainInstance.RedirectActivationToAsync(activatedEventArgs); await mainInstance.RedirectActivationToAsync(activatedEventArgs);
System.Diagnostics.Process.GetCurrentProcess().Kill(); System.Diagnostics.Process.GetCurrentProcess().Kill();
return; return;
} }
else else
{ {
//MainWindow.Activate(); new Editor.EditorWin().Activate();
//MainWindow = new MainWindow(); //MainWindow = new MainWindow();
//new Editor.EditorWin().Activate(); //await App.GetService<IActivationService>().ActivateAsync(args);
MainWindow = new MainWindow();
await App.GetService<IActivationService>().ActivateAsync(args);
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1721905357214" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="26869" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M298.666667 896a32 32 0 0 1 32-32h362.666666a32 32 0 0 1 0 64h-362.666666A32 32 0 0 1 298.666667 896zM382.72 340.053333a32 32 0 0 1 45.226667 0L512 424.106667l84.053333-84.053334a32 32 0 1 1 45.226667 45.226667l-97.28 97.28v136.106667a32 32 0 0 1-64 0v-136.106667L382.72 385.28a32 32 0 0 1 0-45.226667z" fill="#777A80" p-id="26870"></path><path d="M661.333333 662.4l23.978667-19.2a277.333333 277.333333 0 1 0-346.624 0l23.978667 19.2V725.333333a21.333333 21.333333 0 0 0 21.333333 21.333334h256a21.333333 21.333333 0 0 0 21.333333-21.333334v-62.933333z m64 30.72V725.333333a85.333333 85.333333 0 0 1-85.333333 85.333334H384a85.333333 85.333333 0 0 1-85.333333-85.333334v-32.213333a341.333333 341.333333 0 1 1 426.666666 0z" fill="#777A80" p-id="26871"></path></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -73,6 +73,7 @@
Grid.Column="0" Grid.Column="0"
Margin="16,0,0,0" /> Margin="16,0,0,0" />
</Grid> </Grid>
<ScrollViewer <ScrollViewer
Grid.Row="2" Grid.Row="2"
Grid.Column="0" Grid.Column="0"
@ -96,7 +97,48 @@
SelectionMode="Single" /> SelectionMode="Single" />
</ScrollViewer> </ScrollViewer>
<Grid Grid.Row="1" Grid.Column="1" /> <ScrollViewer
Grid.Row="1"
Grid.Column="1"
HorizontalScrollBarVisibility="Visible"
HorizontalScrollMode="Auto"
IsHorizontalRailEnabled="True"
IsHorizontalScrollChainingEnabled="True">
<Grid
x:Name="gridedit"
Grid.Row="1"
Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox
Grid.Column="0"
Margin="0,0,10,0"
Background="Transparent"
ItemsSource="{x:Bind lineNumberList}"
ScrollViewer.IsVerticalRailEnabled="False">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Padding" Value="0" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Name="listboxtext" Text="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<RichEditBox
x:Name="editor"
Grid.Column="1"
Background="Transparent"
TextChanged="editor_TextChanged" />
</Grid>
</ScrollViewer>
</Grid> </Grid>
</Page> </Page>
</windowex:WindowEx> </windowex:WindowEx>

View File

@ -3,27 +3,14 @@ using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using Microsoft.UI; using Microsoft.UI;
using Microsoft.UI.Text;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Documents; using Microsoft.UI.Xaml.Documents;
using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using RustTools.muqing; using RustTools.muqing;
using Windows.ApplicationModel.Core;
using Windows.ApplicationModel.DataTransfer; using Windows.ApplicationModel.DataTransfer;
using Windows.Foundation;
using Windows.Graphics.Imaging;
using Windows.Storage.Pickers;
using Windows.Storage;
using Windows.UI.Core;
using Windows.UI.Core.Preview;
using Windows.UI.Popups;
using Windows.UI.WindowManagement;
using WinRT.Interop; using WinRT.Interop;
namespace RustTools.Editor; namespace RustTools.Editor;
/// <summary> /// <summary>
@ -31,9 +18,10 @@ namespace RustTools.Editor;
/// </summary> /// </summary>
public sealed partial class EditorWin : WindowEx public sealed partial class EditorWin : WindowEx
{ {
private readonly ObservableCollection<string> lineNumberList = new();
//目录列表 //目录列表
public ObservableCollection<ExplorerItem> DataSource=new (); public ObservableCollection<ExplorerItem> DataSource=new ();
private Microsoft.UI.Windowing.AppWindow? app;
public EditorWin() public EditorWin()
{ {
InitializeComponent(); InitializeComponent();
@ -45,7 +33,8 @@ public sealed partial class EditorWin : WindowEx
gj.UpdateTitleBar(this, frame.ActualTheme); gj.UpdateTitleBar(this, frame.ActualTheme);
page.RequestedTheme = frame.ActualTheme; page.RequestedTheme = frame.ActualTheme;
} }
//new CodeEditorControl();
//new Editor.
//WindowManager.Get(this).IsMinimizable = false; //WindowManager.Get(this).IsMinimizable = false;
//app = GetAppWindowForCurrentWindow(); //app = GetAppWindowForCurrentWindow();
//app.Closing += OnClosing; //app.Closing += OnClosing;
@ -56,14 +45,38 @@ public sealed partial class EditorWin : WindowEx
TitleText.Text = directoryInfo.Name; TitleText.Text = directoryInfo.Name;
Closed += EditorWin_Closed; Closed += EditorWin_Closed;
var v = wj.dqwb("D:\\steam\\steamapps\\common\\Rusted Warfare\\mods\\units\\赤道·联合进攻0.9补丁版0.2\\侵蚀者共和国\\指挥中心\\corrode_command.ini"); var v = wj.dqwb("D:\\steam\\steamapps\\common\\Rusted Warfare\\mods\\units\\赤道·联合进攻0.9补丁版0.2\\侵蚀者共和国\\指挥中心\\corrode_command.ini");
//CodeEditor.Document.SetText(TextSetOptions.None,v); editor.Document.SetText(Microsoft.UI.Text.TextSetOptions.None,v);
//EditorView.Editor.SetText(v);
//CodeEditorControl.HighlightingLanguage.
// »ñÈ¡µÚÒ»¸ö¶ÎÂä
//listboxtext
gj.sc(editor.Document.Selection.CharacterFormat.Size);
TextLine();
}
private void editor_TextChanged(object sender, RoutedEventArgs e)
{
TextLine();
}
public void TextLine()
{
lineNumberList.Clear();
editor.Document.GetText(Microsoft.UI.Text.TextGetOptions.NoHidden, out var a);
var lineCount = a.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None).Length;
if (lineCount < 1)
{
return;
}
for (var i = 1; i <= lineCount; i++)
{
lineNumberList.Add((i).ToString());
}
} }
//用户有没有保存 //用户有没有保存
private bool IsSave = false; private bool IsSave = true;
private ContentDialog? ClosedDialog; private ContentDialog? ClosedDialog;
private async void EditorWin_Closed(object sender, WindowEventArgs e) private async void EditorWin_Closed(object sender, WindowEventArgs e)
{ {
@ -211,5 +224,4 @@ public sealed partial class EditorWin : WindowEx
{ {
sender.TabItems.Remove(args.Tab); sender.TabItems.Remove(args.Tab);
} }
} }

View File

@ -6,6 +6,7 @@
<RootNamespace>RustTools</RootNamespace> <RootNamespace>RustTools</RootNamespace>
<Platform>x64</Platform> <Platform>x64</Platform>
<Platforms>x86;x64;arm64</Platforms> <Platforms>x86;x64;arm64</Platforms>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained> <WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
@ -28,14 +29,11 @@
<GenerateTestArtifacts>True</GenerateTestArtifacts> <GenerateTestArtifacts>True</GenerateTestArtifacts>
<AppxBundle>Never</AppxBundle> <AppxBundle>Never</AppxBundle>
<AppxPackageDir>D:\RustTools</AppxPackageDir> <AppxPackageDir>D:\RustTools</AppxPackageDir>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.231008000" /> <PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.231008000" />
@ -48,15 +46,19 @@
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" /> <PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240227000" /> <PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240227000" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.3233" /> <PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.3233" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Assets\**"> <Content Include="Assets\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TextControlBox\TextControlBox.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'"> <ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" /> <ProjectCapability Include="Msix" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,28 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the three default line endings: LF (Line Feed), CRLF (Carriage Return + Line Feed), and CR (Carriage Return).
/// </summary>
/// <remarks>
/// The LineEnding enum represents the different line ending formats that can be used in the textbox.
/// The enum defines three values: LF, CRLF, and CR, corresponding to the different line ending formats.
/// - LF: Represents the Line Feed character '\n' used for line breaks in Unix-based systems.
/// - CRLF: Represents the Carriage Return + Line Feed sequence '\r\n' used for line breaks in Windows-based systems.
/// - CR: Represents the Carriage Return character '\r' used for line breaks in older Macintosh systems.
/// </remarks>
public enum LineEnding
{
/// <summary>
/// Line Feed ('\n')
/// </summary>
LF,
/// <summary>
/// Carriage Return + Line Feed ('\r\n')
/// </summary>
CRLF,
/// <summary>
/// Carriage Return ('\r')
/// </summary>
CR
}
}

View File

@ -0,0 +1,7 @@
namespace TextControlBoxNS
{
internal enum LineMoveDirection
{
Up, Down
}
}

View File

@ -0,0 +1,39 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the result of a search operation in the textbox.
/// </summary>
public enum SearchResult
{
/// <summary>
/// The target text was found during the search operation.
/// </summary>
Found,
/// <summary>
/// The target text was not found during the search operation.
/// </summary>
NotFound,
/// <summary>
/// The search input provided for the search operation was invalid or empty.
/// </summary>
InvalidInput,
/// <summary>
/// The search operation reached the beginning of the text without finding the target text.
/// </summary>
ReachedBegin,
/// <summary>
/// The search operation reached the end of the text without finding the target text.
/// </summary>
ReachedEnd,
/// <summary>
/// The search operation was attempted, but the search was not started.
/// </summary>
SearchNotOpened
}
}

View File

@ -0,0 +1,13 @@
using Windows.UI;
namespace TextControlBoxNS.Extensions
{
internal static class ColorExtension
{
public static Windows.UI.Color ToMediaColor(this System.Drawing.Color drawingColor)
{
return Windows.UI.Color.FromArgb(drawingColor.A, drawingColor.R, drawingColor.G, drawingColor.B);
}
public static string ToHex(this Color c) => $"#{c.R:X2}{c.G:X2}{c.B:X2}";
}
}

View File

@ -0,0 +1,10 @@
namespace TextControlBoxNS.Extensions
{
internal static class IntExtension
{
public static bool IsInRange(this int value, int start, int count)
{
return value >= start && value <= start + count;
}
}
}

View File

@ -0,0 +1,137 @@
using Collections.Pooled;
using System;
using System.Collections.Generic;
using System.Linq;
using TextControlBoxNS.Helper;
namespace TextControlBoxNS.Extensions
{
internal static class ListExtension
{
private static int CurrentLineIndex = 0;
public static string GetLineText(this PooledList<string> list, int index)
{
if (list.Count == 0)
return "";
if (index == -1 && list.Count > 0)
return list[list.Count - 1];
index = index >= list.Count ? list.Count - 1 : index > 0 ? index : 0;
return list[index];
}
public static int GetLineLength(this PooledList<string> list, int index)
{
return GetLineText(list, index).Length;
}
public static void AddLine(this PooledList<string> list, string content = "")
{
list.Add(content);
}
public static void SetLineText(this PooledList<string> list, int line, string text)
{
if (line == -1)
line = list.Count - 1;
line = Math.Clamp(line, 0, list.Count - 1);
list[line] = text;
}
public static string GetCurrentLineText(this PooledList<string> list)
{
return list[CurrentLineIndex < list.Count ? CurrentLineIndex : list.Count - 1 < 0 ? 0 : list.Count - 1];
}
public static void SetCurrentLineText(this PooledList<string> list, string text)
{
list[CurrentLineIndex < list.Count ? CurrentLineIndex : list.Count - 1] = text;
}
public static int CurrentLineLength(this PooledList<string> list)
{
return GetCurrentLineText(list).Length;
}
public static void UpdateCurrentLine(this PooledList<string> _, int currentLine)
{
CurrentLineIndex = currentLine;
}
public static void String_AddToEnd(this PooledList<string> list, int line, string add)
{
list[line] = list[line] + add;
}
public static void InsertOrAdd(this PooledList<string> list, int index, string lineText)
{
if (index >= list.Count || index == -1)
list.Add(lineText);
else
list.Insert(index, lineText);
}
public static void InsertOrAddRange(this PooledList<string> list, IEnumerable<string> lines, int index)
{
if (index >= list.Count)
list.AddRange(lines);
else
list.InsertRange(index < 0 ? 0 : index, lines);
}
public static void InsertNewLine(this PooledList<string> list, int index, string content = "")
{
list.InsertOrAdd(index, content);
}
public static void DeleteAt(this PooledList<string> list, int index)
{
if (index >= list.Count)
index = list.Count - 1 < 0 ? list.Count - 1 : 0;
list.RemoveAt(index);
list.TrimExcess();
}
private static IEnumerable<string> GetLines_Small(this PooledList<string> totalLines, int start, int count)
{
var res = ListHelper.CheckValues(totalLines, start, count);
for (int i = 0; i < res.Count; i++)
{
yield return totalLines[i + res.Index];
}
}
public static IEnumerable<string> GetLines(this PooledList<string> totalLines, int start, int count)
{
//use different algorithm for small amount of lines:
if (start + count < 400)
{
return GetLines_Small(totalLines, start, count);
}
return totalLines.Skip(start).Take(count);
}
public static string GetString(this IEnumerable<string> lines, string NewLineCharacter)
{
return string.Join(NewLineCharacter, lines);
}
public static void Safe_RemoveRange(this PooledList<string> totalLines, int index, int count)
{
var res = ListHelper.CheckValues(totalLines, index, count);
totalLines.RemoveRange(res.Index, res.Count);
totalLines.TrimExcess();
//clear up the memory of the list when more than 1mio items are removed
if (res.Count > 1_000_000)
ListHelper.GCList(totalLines);
}
public static string[] GetLines(this string[] lines, int start, int count)
{
return lines.Skip(start).Take(count).ToArray();
}
public static void SwapLines(this PooledList<string> lines, int originalindex, int newindex)
{
string oldLine = lines.GetLineText(originalindex);
lines.SetLineText(originalindex, lines.GetLineText(newindex));
lines.SetLineText(newindex, oldLine);
}
}
}

View File

@ -0,0 +1,16 @@
using Windows.Foundation;
namespace TextControlBoxNS.Extensions
{
internal static class PointExtension
{
public static Point Subtract(this Point point, double subtractX, double subtractY)
{
return new Point(point.X - subtractX, point.Y - subtractY);
}
public static Point Subtract(this Point point, Point subtract)
{
return new Point(point.X - subtract.X, point.Y - subtract.Y);
}
}
}

View File

@ -0,0 +1,63 @@
using System;
using System.Text.RegularExpressions;
using TextControlBoxNS.Helper;
namespace TextControlBoxNS.Extensions
{
internal static class StringExtension
{
public static string RemoveFirstOccurence(this string value, string removeString)
{
int index = value.IndexOf(removeString, StringComparison.Ordinal);
return index < 0 ? value : value.Remove(index, removeString.Length);
}
public static string AddToEnd(this string text, string add)
{
return text + add;
}
public static string AddToStart(this string text, string add)
{
return add + text;
}
public static string AddText(this string text, string add, int position)
{
if (position < 0)
position = 0;
if (position >= text.Length || text.Length <= 0)
return text + add;
else
return text.Insert(position, add);
}
public static string SafeRemove(this string text, int start, int count = -1)
{
if (start >= text.Length || start < 0)
return text;
if (count <= -1)
return text.Remove(start);
else
return text.Remove(start, count);
}
public static bool Contains(this string text, SearchParameter parameter)
{
if (parameter.WholeWord)
return Regex.IsMatch(text, parameter.SearchExpression, RegexOptions.Compiled);
if (parameter.MatchCase)
return text.Contains(parameter.Word, StringComparison.Ordinal);
else
return text.Contains(parameter.Word, StringComparison.OrdinalIgnoreCase);
}
public static string Safe_Substring(this string text, int index, int count = -1)
{
if (index >= text.Length)
return "";
else if (count == -1)
return text.Substring(index);
else
return text.Substring(index, count);
}
}
}

View File

@ -0,0 +1,41 @@
using Microsoft.Graphics.Canvas.UI.Xaml;
using Windows.UI.Core;
namespace TextControlBoxNS.Helper
{
internal class CanvasHelper
{
public CanvasControl Canvas_Selection = null;
public CanvasControl Canvas_Linenumber = null;
public CanvasControl Canvas_Text = null;
public CanvasControl Canvas_Cursor = null;
public CanvasHelper(CanvasControl canvas_selection, CanvasControl canvas_linenumber, CanvasControl canvas_text, CanvasControl canvas_cursor)
{
this.Canvas_Text = canvas_text;
this.Canvas_Linenumber = canvas_linenumber;
this.Canvas_Cursor = canvas_cursor;
this.Canvas_Selection = canvas_selection;
}
public void UpdateCursor()
{
Canvas_Cursor.Invalidate();
}
public void UpdateText()
{
//TODO: Utils.ChangeCursor(CoreCursorType.IBeam);
Canvas_Text.Invalidate();
}
public void UpdateSelection()
{
Canvas_Selection.Invalidate();
}
public void UpdateAll()
{
UpdateText();
UpdateSelection();
UpdateCursor();
}
}
}

View File

@ -0,0 +1,41 @@
using Microsoft.UI.Xaml.Controls;
using System;
namespace TextControlBoxNS.Helper
{
internal class FlyoutHelper
{
public MenuFlyout MenuFlyout;
public FlyoutHelper(TextControlBox sender)
{
CreateFlyout(sender);
}
public void CreateFlyout(TextControlBox sender)
{
MenuFlyout = new MenuFlyout();
MenuFlyout.Items.Add(CreateItem(() => { sender.Copy(); }, "Copy", Symbol.Copy, "Ctrl + C"));
MenuFlyout.Items.Add(CreateItem(() => { sender.Paste(); }, "Paste", Symbol.Paste, "Ctrl + V"));
MenuFlyout.Items.Add(CreateItem(() => { sender.Cut(); }, "Cut", Symbol.Cut, "Ctrl + X"));
MenuFlyout.Items.Add(new MenuFlyoutSeparator());
MenuFlyout.Items.Add(CreateItem(() => { sender.Undo(); }, "Undo", Symbol.Undo, "Ctrl + Z"));
MenuFlyout.Items.Add(CreateItem(() => { sender.Redo(); }, "Redo", Symbol.Redo, "Ctrl + Y"));
}
public MenuFlyoutItem CreateItem(Action action, string text, Symbol icon, string key)
{
var item = new MenuFlyoutItem
{
Text = text,
KeyboardAcceleratorTextOverride = key,
Icon = new SymbolIcon { Symbol = icon }
};
item.Click += delegate
{
action();
};
return item;
}
}
}

View File

@ -0,0 +1,13 @@
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
namespace TextControlBoxNS.Helper
{
internal class InputHandlerControl : TextBox
{
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
return;
}
}
}

View File

@ -0,0 +1,75 @@
using Collections.Pooled;
using System;
using System.Linq;
namespace TextControlBoxNS.Helper
{
internal class ListHelper
{
public struct ValueResult
{
public ValueResult(int index, int count)
{
this.Index = index;
this.Count = count;
}
public int Index;
public int Count;
}
public static ValueResult CheckValues(PooledList<string> totalLines, int index, int count)
{
if (index >= totalLines.Count)
{
index = totalLines.Count - 1 < 0 ? 0 : totalLines.Count - 1;
count = 0;
}
if (index + count >= totalLines.Count)
{
int difference = totalLines.Count - index;
if (difference >= 0)
count = difference;
}
if (count < 0)
count = 0;
if (index < 0)
index = 0;
return new ValueResult(index, count);
}
public static void GCList(PooledList<string> totalLines)
{
int id = GC.GetGeneration(totalLines);
GC.Collect(id, GCCollectionMode.Forced);
}
public static void Clear(PooledList<string> totalLines, bool addNewLine = false)
{
totalLines.Clear();
GCList(totalLines);
if (addNewLine)
totalLines.Add("");
}
public static string GetLinesAsString(PooledList<string> lines, string newLineCharacter)
{
return string.Join(newLineCharacter, lines);
}
public static string[] GetLinesFromString(string content, string newLineCharacter)
{
return content.Split(newLineCharacter);
}
public static string[] CreateLines(string[] lines, int start, string beginning, string end)
{
if (start > 0)
lines = lines.Skip(start).ToArray();
lines[0] = beginning + lines[0];
if (lines.Length - 1 > 0)
lines[lines.Length - 1] = lines[lines.Length - 1] + end;
return lines;
}
}
}

View File

@ -0,0 +1,218 @@
using Collections.Pooled;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using TextControlBoxNS.Extensions;
using TextControlBoxNS.Text;
namespace TextControlBoxNS.Helper
{
internal class SearchHelper
{
public int CurrentSearchLine = 0;
public int CurrentSearchArrayIndex = 0;
public int OldSearchArrayIndex = 0;
public int[] MatchingSearchLines = null;
public bool IsSearchOpen = false;
public SearchParameter SearchParameter = null;
public MatchCollection CurrentLineMatches = null;
private int RegexIndexInLine = 0;
private int CheckIndexValue(int i)
{
return i >= MatchingSearchLines.Length ? MatchingSearchLines.Length - 1 : i < 0 ? 0 : i;
}
public InternSearchResult FindNext(PooledList<string> totalLines, CursorPosition cursorPosition)
{
if (IsSearchOpen && MatchingSearchLines != null && MatchingSearchLines.Length > 0)
{
CurrentSearchLine = cursorPosition.LineNumber;
int indexInList = Array.IndexOf(MatchingSearchLines, CurrentSearchLine);
//When in a line without a match search for the next line with a match
if (indexInList == -1)
{
for (int i = 0; i < MatchingSearchLines.Length; i++)
{
if (MatchingSearchLines[i] > CurrentSearchLine)
{
CurrentSearchArrayIndex = i - 1 < 0 ? 0 : i - 1;
CurrentSearchLine = MatchingSearchLines[CurrentSearchArrayIndex];
break;
}
}
}
else
{
CurrentSearchArrayIndex = indexInList;
CurrentSearchLine = MatchingSearchLines[CurrentSearchArrayIndex];
if (OldSearchArrayIndex != CurrentSearchArrayIndex)
{
OldSearchArrayIndex = CurrentSearchArrayIndex;
CurrentLineMatches = null;
}
}
//Search went through all matches in the current line:
if (CurrentLineMatches == null || RegexIndexInLine >= CurrentLineMatches.Count)
{
RegexIndexInLine = 0;
//back at start
if (CurrentSearchLine < MatchingSearchLines[MatchingSearchLines.Length - 1])
{
CurrentSearchArrayIndex++;
CurrentSearchLine = cursorPosition.LineNumber = MatchingSearchLines[CurrentSearchArrayIndex];
CurrentLineMatches = Regex.Matches(totalLines[CurrentSearchLine], SearchParameter.SearchExpression);
}
else
return new InternSearchResult(SearchResult.ReachedEnd, null);
}
RegexIndexInLine = Math.Clamp(RegexIndexInLine, 0, CurrentLineMatches.Count - 1);
RegexIndexInLine++;
if (RegexIndexInLine > CurrentLineMatches.Count || RegexIndexInLine < 0)
return new InternSearchResult(SearchResult.NotFound, null);
return new InternSearchResult(SearchResult.Found, new TextSelection(
new CursorPosition(CurrentLineMatches[RegexIndexInLine - 1].Index, cursorPosition.LineNumber),
new CursorPosition(CurrentLineMatches[RegexIndexInLine - 1].Index + CurrentLineMatches[RegexIndexInLine - 1].Length, cursorPosition.LineNumber)));
}
return new InternSearchResult(SearchResult.NotFound, null);
}
public InternSearchResult FindPrevious(PooledList<string> totalLines, CursorPosition cursorPosition)
{
if (IsSearchOpen && MatchingSearchLines != null)
{
//Find the next linnenumber with a match if the line is not in the array of matching lines
CurrentSearchLine = cursorPosition.LineNumber;
int indexInList = Array.IndexOf(MatchingSearchLines, CurrentSearchLine);
if (indexInList == -1)
{
//Find the first line with matches which is smaller than the current line:
var lines = MatchingSearchLines.Where(x => x < CurrentSearchLine);
if (lines.Count() < 1)
{
return new InternSearchResult(SearchResult.ReachedBegin, null);
}
CurrentSearchArrayIndex = Array.IndexOf(MatchingSearchLines, lines.Last());
CurrentSearchLine = MatchingSearchLines[CurrentSearchArrayIndex];
CurrentLineMatches = null;
}
else
{
CurrentSearchArrayIndex = indexInList;
CurrentSearchLine = MatchingSearchLines[CurrentSearchArrayIndex];
if (OldSearchArrayIndex != CurrentSearchArrayIndex)
{
OldSearchArrayIndex = CurrentSearchArrayIndex;
CurrentLineMatches = null;
}
}
//Search went through all matches in the current line:
if (CurrentLineMatches == null || RegexIndexInLine < 0)
{
//back at start
if (CurrentSearchLine == MatchingSearchLines[0])
{
return new InternSearchResult(SearchResult.ReachedBegin, null);
}
if (CurrentSearchLine < MatchingSearchLines[MatchingSearchLines.Length - 1])
{
CurrentSearchLine = cursorPosition.LineNumber = MatchingSearchLines[CheckIndexValue(CurrentSearchArrayIndex - 1)];
CurrentLineMatches = Regex.Matches(totalLines[CurrentSearchLine], SearchParameter.SearchExpression);
RegexIndexInLine = CurrentLineMatches.Count - 1;
CurrentSearchArrayIndex--;
}
}
if (CurrentLineMatches == null)
return new InternSearchResult(SearchResult.NotFound, null);
RegexIndexInLine = Math.Clamp(RegexIndexInLine, 0, CurrentLineMatches.Count - 1);
//RegexIndexInLine--;
if (RegexIndexInLine >= CurrentLineMatches.Count || RegexIndexInLine < 0)
return new InternSearchResult(SearchResult.NotFound, null);
return new InternSearchResult(SearchResult.Found, new TextSelection(
new CursorPosition(CurrentLineMatches[RegexIndexInLine].Index, cursorPosition.LineNumber),
new CursorPosition(CurrentLineMatches[RegexIndexInLine].Index + CurrentLineMatches[RegexIndexInLine--].Length, cursorPosition.LineNumber)));
}
return new InternSearchResult(SearchResult.NotFound, null);
}
public void UpdateSearchLines(PooledList<string> totalLines)
{
MatchingSearchLines = FindIndexes(totalLines);
}
public SearchResult BeginSearch(PooledList<string> totalLines, string word, bool matchCase, bool wholeWord)
{
SearchParameter = new SearchParameter(word, wholeWord, matchCase);
UpdateSearchLines(totalLines);
if (word == "" || word == null)
return SearchResult.InvalidInput;
//A result was found
if (MatchingSearchLines.Length > 0)
{
IsSearchOpen = true;
}
return MatchingSearchLines.Length > 0 ? SearchResult.Found : SearchResult.NotFound;
}
public void EndSearch()
{
IsSearchOpen = false;
MatchingSearchLines = null;
}
private int[] FindIndexes(PooledList<string> totalLines)
{
List<int> results = new List<int>();
for (int i = 0; i < totalLines.Count; i++)
{
if (totalLines[i].Contains(SearchParameter))
results.Add(i);
};
return results.ToArray();
}
}
internal class SearchParameter
{
public SearchParameter(string word, bool wholeWord = false, bool matchCase = false)
{
this.Word = word;
this.WholeWord = wholeWord;
this.MatchCase = matchCase;
if (wholeWord)
SearchExpression += @"\b" + (matchCase ? "" : "(?i)") + Regex.Escape(word) + @"\b";
else
SearchExpression += (matchCase ? "" : "(?i)") + Regex.Escape(word);
}
public bool WholeWord { get; set; }
public bool MatchCase { get; set; }
public string Word { get; set; }
public string SearchExpression { get; set; } = "";
}
internal struct InternSearchResult
{
public InternSearchResult(SearchResult result, TextSelection selection)
{
this.Result = result;
this.Selection = selection;
}
public TextSelection Selection;
public SearchResult Result;
}
}

View File

@ -0,0 +1,74 @@
using Collections.Pooled;
using System;
namespace TextControlBoxNS.Helper
{
internal class TabSpaceHelper
{
private int _NumberOfSpaces = 4;
private string OldSpaces = " ";
public int NumberOfSpaces
{
get => _NumberOfSpaces;
set
{
if (value != _NumberOfSpaces)
{
OldSpaces = Spaces;
_NumberOfSpaces = value;
Spaces = new string(' ', _NumberOfSpaces);
}
}
}
public bool UseSpacesInsteadTabs = false;
public string TabCharacter { get => UseSpacesInsteadTabs ? Spaces : Tab; }
private string Spaces = " ";
private string Tab = "\t";
public void UpdateNumberOfSpaces(PooledList<string> totalLines)
{
ReplaceSpacesToSpaces(totalLines);
}
public void UpdateTabs(PooledList<string> totalLines)
{
if (UseSpacesInsteadTabs)
ReplaceTabsToSpaces(totalLines);
else
ReplaceSpacesToTabs(totalLines);
}
public string UpdateTabs(string input)
{
if (UseSpacesInsteadTabs)
return Replace(input, Tab, Spaces);
return Replace(input, Spaces, Tab);
}
private void ReplaceSpacesToSpaces(PooledList<string> totalLines)
{
for (int i = 0; i < totalLines.Count; i++)
{
totalLines[i] = Replace(totalLines[i], OldSpaces, Spaces);
}
}
private void ReplaceSpacesToTabs(PooledList<string> TotalLines)
{
for (int i = 0; i < TotalLines.Count; i++)
{
TotalLines[i] = Replace(TotalLines[i], Spaces, Tab);
}
}
private void ReplaceTabsToSpaces(PooledList<string> totalLines)
{
for (int i = 0; i < totalLines.Count; i++)
{
totalLines[i] = Replace(totalLines[i], "\t", Spaces);
}
}
public string Replace(string input, string find, string replace)
{
return input.Replace(find, replace, StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@ -0,0 +1,64 @@
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.UI.Xaml.Media;
using Windows.Foundation;
namespace TextControlBoxNS.Helper
{
internal class TextLayoutHelper
{
public static CanvasTextLayout CreateTextResource(ICanvasResourceCreatorWithDpi resourceCreator, CanvasTextLayout textLayout, CanvasTextFormat textFormat, string text, Size targetSize)
{
if (textLayout != null)
textLayout.Dispose();
textLayout = CreateTextLayout(resourceCreator, textFormat, text, targetSize);
textLayout.Options = CanvasDrawTextOptions.EnableColorFont;
return textLayout;
}
public static CanvasTextFormat CreateCanvasTextFormat(float zoomedFontSize, FontFamily fontFamily)
{
return CreateCanvasTextFormat(zoomedFontSize, zoomedFontSize + 2, fontFamily);
}
public static CanvasTextFormat CreateCanvasTextFormat(float zoomedFontSize, float lineSpacing, FontFamily fontFamily)
{
CanvasTextFormat textFormat = new CanvasTextFormat()
{
FontSize = zoomedFontSize,
HorizontalAlignment = CanvasHorizontalAlignment.Left,
VerticalAlignment = CanvasVerticalAlignment.Top,
WordWrapping = CanvasWordWrapping.NoWrap,
LineSpacing = lineSpacing,
};
textFormat.IncrementalTabStop = zoomedFontSize * 3; //default 137px
textFormat.FontFamily = fontFamily.Source;
textFormat.TrimmingGranularity = CanvasTextTrimmingGranularity.None;
textFormat.TrimmingSign = CanvasTrimmingSign.None;
return textFormat;
}
public static CanvasTextLayout CreateTextLayout(ICanvasResourceCreator resourceCreator, CanvasTextFormat textFormat, string text, Size canvasSize)
{
return new CanvasTextLayout(resourceCreator, text, textFormat, (float)canvasSize.Width, (float)canvasSize.Height);
}
public static CanvasTextLayout CreateTextLayout(ICanvasResourceCreator resourceCreator, CanvasTextFormat textFormat, string text, float width, float height)
{
return new CanvasTextLayout(resourceCreator, text, textFormat, width, height);
}
public static CanvasTextFormat CreateLinenumberTextFormat(float fontSize, FontFamily fontFamily)
{
CanvasTextFormat textFormat = new CanvasTextFormat()
{
FontSize = fontSize,
HorizontalAlignment = CanvasHorizontalAlignment.Right,
VerticalAlignment = CanvasVerticalAlignment.Top,
WordWrapping = CanvasWordWrapping.NoWrap,
LineSpacing = fontSize + 2,
};
textFormat.FontFamily = fontFamily.Source;
textFormat.TrimmingGranularity = CanvasTextTrimmingGranularity.None;
textFormat.TrimmingSign = CanvasTrimmingSign.None;
return textFormat;
}
}
}

View File

@ -0,0 +1,160 @@
using Collections.Pooled;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.UI.Xaml;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using TextControlBoxNS.Extensions;
using Windows.Foundation;
using Windows.System;
using Windows.UI.Core;
using Windows.UI.Popups;
namespace TextControlBoxNS.Helper
{
internal class Utils
{
public static Size MeasureTextSize(CanvasDevice device, string text, CanvasTextFormat textFormat, float limitedToWidth = 0.0f, float limitedToHeight = 0.0f)
{
CanvasTextLayout layout = new CanvasTextLayout(device, text, textFormat, limitedToWidth, limitedToHeight);
return new Size(layout.DrawBounds.Width, layout.DrawBounds.Height);
}
public static Size MeasureLineLenght(CanvasDevice device, string text, CanvasTextFormat textFormat)
{
if (text.Length == 0)
return new Size(0, 0);
//If the text starts with a tab or a whitespace, replace it with the last character of the line, to
//get the actual width of the line, because tabs and whitespaces at the beginning are not counted to the lenght
//Do the same for the end
double placeholderWidth = 0;
if (text.StartsWith('\t') || text.StartsWith(' '))
{
text = text.Insert(0, "|");
placeholderWidth += MeasureTextSize(device, "|", textFormat).Width;
}
if (text.EndsWith('\t') || text.EndsWith(' '))
{
text = text += "|";
placeholderWidth += MeasureTextSize(device, "|", textFormat).Width;
}
CanvasTextLayout layout = new CanvasTextLayout(device, text, textFormat, 0, 0);
return new Size(layout.DrawBounds.Width - placeholderWidth, layout.DrawBounds.Height);
}
//Get the longest line in the textbox
public static int GetLongestLineIndex(PooledList<string> totalLines)
{
int longestIndex = 0;
int oldLenght = 0;
for (int i = 0; i < totalLines.Count; i++)
{
var lenght = totalLines[i].Length;
if (lenght > oldLenght)
{
longestIndex = i;
oldLenght = lenght;
}
}
return longestIndex;
}
public static int GetLongestLineLength(string text)
{
var splitted = text.Split("\n");
int oldLenght = 0;
for (int i = 0; i < splitted.Length; i++)
{
var lenght = splitted[i].Length;
if (lenght > oldLenght)
{
oldLenght = lenght;
}
}
return oldLenght;
}
public static bool CursorPositionsAreEqual(CursorPosition first, CursorPosition second)
{
return first.LineNumber == second.LineNumber && first.CharacterPosition == second.CharacterPosition;
}
public static string[] SplitAt(string text, int index)
{
string first = index < text.Length ? text.SafeRemove(index) : text;
string second = index < text.Length ? text.Safe_Substring(index) : "";
return new string[] { first, second };
}
public static int CountCharacters(PooledList<string> totalLines)
{
int count = 0;
for (int i = 0; i < totalLines.Count; i++)
{
count += totalLines[i].Length + 1;
}
return count - 1;
}
public static bool IsKeyPressed(VirtualKey key)
{
return Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(key).HasFlag(CoreVirtualKeyStates.Down);
}
public static async Task<bool> IsOverTextLimit(int textLength)
{
if (textLength > 100000000)
{
await new MessageDialog("Current textlimit is 100 million characters, but your file has " + textLength + " characters").ShowAsync();
return true;
}
return false;
}
public static void Benchmark(Action action, string text)
{
Stopwatch sw = new Stopwatch();
sw.Start();
action.Invoke();
sw.Stop();
Debug.WriteLine(text + " took " + sw.ElapsedMilliseconds + "::" + sw.ElapsedTicks);
}
public static ApplicationTheme ConvertTheme(ElementTheme theme)
{
switch (theme)
{
case ElementTheme.Light: return ApplicationTheme.Light;
case ElementTheme.Dark: return ApplicationTheme.Dark;
case ElementTheme.Default:
var defaultTheme = new Windows.UI.ViewManagement.UISettings();
return defaultTheme.GetColorValue(Windows.UI.ViewManagement.UIColorType.Background).ToString() == "#FF000000"
? ApplicationTheme.Dark : ApplicationTheme.Light;
default: return ApplicationTheme.Light;
}
}
public static Point GetTextboxstartingPoint(UIElement relativeTo)
{
return relativeTo.TransformToVisual(Window.Current.Content).TransformPoint(new Point(0, 0));
}
public static int CountLines(string text, string newLineCharacter)
{
return (text.Length - text.Replace(newLineCharacter, "").Length) / newLineCharacter.Length + 1;
}
public static Rect CreateRect(Rect rect, float marginLeft = 0, float marginTop = 0)
{
return new Rect(
new Point(
Math.Floor(rect.Left + marginLeft),//X
Math.Floor(rect.Top + marginTop)), //Y
new Point(
Math.Ceiling(rect.Right + marginLeft), //Width
Math.Ceiling(rect.Bottom + marginTop))); //Height
}
}
}

View File

@ -0,0 +1,511 @@
namespace TextControlBoxNS.Languages
{
internal class Batch : CodeLanguage
{
public Batch()
{
this.Name = "Batch";
this.Author = "Julius Kirsch";
this.Filter = new string[1] { ".bat" };
this.Description = "Syntax highlighting for Batch language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),
new SyntaxHighlights("(?i)(set|echo|for|pushd|popd|pause|exit|cd|if|else|goto|del)\\s", "#dd00dd", "#dd00dd"),
new SyntaxHighlights("(:.*)", "#00C000", "#ffff00"),
new SyntaxHighlights("(\\\".+?\\\"|\\'.+?\\')", "#00C000", "#ffff00"),
new SyntaxHighlights("(@|%)", "#dd0077", "#dd0077"),
new SyntaxHighlights("(\\*)", "#dd0077", "#dd0077"),
new SyntaxHighlights("((?i)rem.*)", "#888888", "#888888"),
};
}
}
internal class ConfigFile : CodeLanguage
{
public ConfigFile()
{
this.Name = "ConfigFile";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".ini" };
this.Description = "Syntax highlighting for configuration files";
this.AutoPairingPair = new AutoPairingPair[]
{
new AutoPairingPair("[", "]")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("[\\[\\]]", "#0000FF", "#0000FF"),
new SyntaxHighlights("\\[[\\t\\s]*(\\w+)[\\t\\s]*\\]", "#9900FF", "#9900FF"),
new SyntaxHighlights("(\\w+)\\=", "#DDDD00", "#DDDD00"),
new SyntaxHighlights("\\=(.+)", "#EE0000", "#EE0000"),
new SyntaxHighlights(";.*", "#888888", "#888888"),
};
}
}
internal class Cpp : CodeLanguage
{
public Cpp()
{
this.Name = "C++";
this.Author = "Julius Kirsch";
this.Filter = new string[6] { ".cpp", ".cxx", ".cc", ".hpp", ".h", ".c" };
this.Description = "Syntax highlighting for C++ language";
this.AutoPairingPair = new AutoPairingPair[5]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#00ff00"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#4455ff", "#ffbb00"),
new SyntaxHighlights("\\b(string|uint16_t|uint8_t|alignas|alignof|and|and_eq|asm|auto|bitand|bitor|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|false|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|not|not_eq|nullptr|operator|or|or_eq|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|true|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while|xor|xor_eq)\\b", "#dd00dd", "#dd00dd"),
new SyntaxHighlights("\\B#(define|elif|else|endif|error|ifndef|ifdef|if|import|include|line|pragma|region|undef|using)", "#bbbbbb", "#999999"),
new SyntaxHighlights("(\\\".+?\\\"|\\'.+?\\')", "#ffff00", "#ff000f"),
new SyntaxHighlights("\"[^\\n]*?\"", "#00CA00", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
};
}
}
internal class CSharp : CodeLanguage
{
public CSharp()
{
this.Name = "C#";
this.Author = "Julius Kirsch";
this.Filter = new string[1] { ".cs" };
this.Description = "Syntax highlighting for C# language";
this.AutoPairingPair = new AutoPairingPair[5]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#ff00ff", "#ff00ff"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#880088", "#ffbb00"),
new SyntaxHighlights("\\b(abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|external|false|final|finally|fixed|float|for|foreach|get|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|partial|private|protected|public|readonly|ref|return|sbyte|sealed|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|value|var|virtual|void|volatile|while)\\b", "#0066bb", "#00ffff"),
new SyntaxHighlights("\\b(List|Color|Console|Debug|Dictionary|Stack|Queue|GC)\\b", "#008000", "#ff9900"),
new SyntaxHighlights("\\b(try|catch|finally)\\b", "#9922ff", "#6666ff"),
new SyntaxHighlights("(#region)+(.*?)($|\n)", "#ff0000", "#ff0000", true),
new SyntaxHighlights("#endregion", "#ff0000", "#ff0000", true),
new SyntaxHighlights("\"[^\\n]*?\"", "#ff5500", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
};
}
}
internal class GCode : CodeLanguage
{
public GCode()
{
this.Name = "GCode";
this.Author = "Julius Kirsch";
this.Filter = new string[5] { ".ngc", ".tap", ".gcode", ".nc", ".cnc" };
this.Description = "Syntax highlighting for GCode language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\bY(?=([0-9]|(\\+|\\-)[0-9]))", "#00ff00", "#00ff00"),
new SyntaxHighlights("\\bX(?=([0-9]|(\\+|\\-)[0-9]))", "#ff0000", "#ff0000"),
new SyntaxHighlights("\\bZ(?=([0-9]|(\\+|\\-)[0-9]))", "#0077ff", "#0077ff"),
new SyntaxHighlights("\\bA(?=([0-9]|(\\+|\\-)[0-9]))", "#ff00ff", "#ff00ff"),
new SyntaxHighlights("\\b(E|F)(?=([0-9]|(\\+|\\-)[0-9]))", "#ffAA00", "#ffAA00"),
new SyntaxHighlights("\\b(S|T)(?=([0-9]|(\\+|\\-)[0-9]))", "#ffff00", "#ffff00"),
new SyntaxHighlights("([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?", "#ff00ff", "#9f009f"),
new SyntaxHighlights("[G|M][0-999].*?[\\s|\\n]", "#00aaaa", "#00ffff"),
new SyntaxHighlights("(;|\\/\\/|\\brem\\b).*", "#888888", "#888888"),
};
}
}
internal class HexFile : CodeLanguage
{
public HexFile()
{
this.Name = "HexFile";
this.Author = "Finn Freitag";
this.Filter = new string[2] { ".hex", ".bin" };
this.Description = "Syntaxhighlighting for hex and binary code.";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\:", "#FFFF00", "#FFFF00"),
new SyntaxHighlights("\\:([0-9A-Fa-f]{2})", "#00FF00", "#00FF00"),
new SyntaxHighlights("\\:[0-9A-Fa-f]{2}([0-9A-Fa-f]{4})", "#00FF00", "#00FF00"),
new SyntaxHighlights("\\:[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})", "#FF5500", "#FF5500"),
new SyntaxHighlights("\\:[0-9A-Fa-f]{8}([0-9A-Fa-f]*)[0-9A-Fa-f]{2}", "#00FFFF", "#00FFFF"),
new SyntaxHighlights("\\:[0-9A-Fa-f]{8}[0-9A-Fa-f]*([0-9A-Fa-f]{2})", "#666666", "#666666"),
new SyntaxHighlights("//.*", "#666666", "#666666"),
new SyntaxHighlights("[^0-9A-Fa-f\\:\\n]", "#FF0000", "#FF0000", false, false, true),
};
}
}
internal class Html : CodeLanguage
{
public Html()
{
this.Name = "Html";
this.Author = "Julius Kirsch";
this.Filter = new string[2] { ".html", ".htm" };
this.Description = "Syntax highlighting for Html language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),
new SyntaxHighlights("[-A-Za-z_]+\\=", "#00CA00", "#Ff0000"),
new SyntaxHighlights("<([^ >!\\/]+)[^>]*>", "#969696", "#0099ff"),
new SyntaxHighlights("<+[/]+[a-zA-Z0-9:?\\-_]+>", "#969696", "#0099ff"),
new SyntaxHighlights("<[a-zA-Z0-9:?\\-]+?.*\\/>", "#969696", "#0099ff"),
new SyntaxHighlights("\"[^\\n]*?\"", "#00CA00", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("[0-9]+(px|rem|em|vh|vw|px|pt|pc|in|mm|cm|deg|%)", "#ff00ff", "#dd00dd"),
new SyntaxHighlights("<!--[\\s\\S]*?-->", "#888888", "#888888"),
};
}
}
internal class Java : CodeLanguage
{
public Java()
{
this.Name = "Java";
this.Author = "Julius Kirsch";
this.Filter = new string[2] { ".java", ".class" };
this.Description = "Syntax highlighting for Java language";
this.AutoPairingPair = new AutoPairingPair[5]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#ff00ff", "#ff00ff"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#880088", "#ffbb00"),
new SyntaxHighlights("\\b(System.out|System|Math)\\b", "#008000", "#ff9900"),
new SyntaxHighlights("\\b(abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|try|void|volatile|while|exports|modle|non-sealed|open|opens|permits|provides|record|requires|sealed|to|transitive|uses|var|with|yield|true|false|null)\\b", "#0066bb", "#00ffff"),
new SyntaxHighlights("\"[^\\n]*?\"", "#ff5500", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
};
}
}
internal class Javascript : CodeLanguage
{
public Javascript()
{
this.Name = "Javascript";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".js" };
this.Description = "Syntax highlighting for Javascript language";
this.AutoPairingPair = new AutoPairingPair[6]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("`", "`"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\W", "#990033", "#CC0066"),
new SyntaxHighlights("(\\+|\\-|\\*|/|%|\\=|\\:|\\!|>|\\<|\\?|&|\\||\\~|\\^)", "#77FF77", "#77FF77"),
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#ff00ff", "#ff00ff"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#880088", "#ffbb00"),
new("\\b(goto|in|instanceof|static|arguments|public|do|else|const|function|class|return|let|eval|for|if|this|break|debugger|yield|extends|enum|continue|export|null|switch|private|new|throw|while|case|await|delete|super|default|void|var|protected|package|interface|false|typeof|implements|with|import|true)\\b", "#0066bb", "#00ffff"),
new SyntaxHighlights("\\b(document|window|screen)\\b", "#008000", "#33BB00"),
new SyntaxHighlights("\\b(try|catch|finally)\\b", "#9922ff", "#6666ff"),
new SyntaxHighlights("/[^\\n]*/i{0,1}", "#FFFF00", "#FFFF00"),
new SyntaxHighlights("[\"'][^\\n]*?[\"']", "#ff5500", "#00FF00"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
};
}
}
internal class INI : CodeLanguage
{
public INI()
{
Name = "INI";
Author = "Rust";
Filter = new string[1] { ".ini" };
Description = "Ini语法突出显示";
AutoPairingPair = new AutoPairingPair[]
{
new("[", "]"),
new(" ",":")
};
Highlights = new SyntaxHighlights[]
{
new("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),//数字?
//new("\\b(true|false)\\b","#00AADD", "#0099ff"),//bool值
new("\\[.*?\\]", "#e91e63", "#e91e63"),
new("(.*?):","#2196f3","#00ff00"),
new(":","#000000","#ffffff"),
new("\\b(false|true|if|=)\\b", "#0066bb", "#00ffff"),
new("##.*", "#888888", "#646464"),// 单行注释
};
}
}
internal class Json : CodeLanguage
{
public Json()
{
this.Name = "Json";
this.Author = "Julius Kirsch";
this.Filter = new string[1] { ".json" };
this.Description = "Syntax highlighting for Json language";
this.AutoPairingPair = new AutoPairingPair[4]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),
new SyntaxHighlights("(null|true|false)", "#00AADD", "#0099ff"),
new SyntaxHighlights("(,|{|}|\\[|\\])", "#969696", "#646464"),
new SyntaxHighlights("(\".+\")\\:", "#00CA00", "#dddd00"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("\"[^\\n]*?\"", "#00CA00", "#00FF00"),
};
}
}
internal class PHP : CodeLanguage
{
public PHP()
{
this.Name = "PHP";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".php" };
this.Description = "Syntax highlighting for PHP language";
this.AutoPairingPair = new AutoPairingPair[2]
{
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\<\\?php", "#FF0000", "#FF0000"),
new SyntaxHighlights("\\?\\>", "#FF0000", "#FF0000"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#3300FF", "#aa00FF"),
new SyntaxHighlights("\\b(echo|if|case|while|else|switch|foreach|function|default|break|null|true|false)\\b", "#0077FF", "#0077FF"),
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#ff00ff", "#ff00ff"),
new SyntaxHighlights("(\\+|\\-|\\*|/|%|\\=|\\:|\\!|>|\\<|\\?|&|\\||\\~|\\^)", "#77FF77", "#77FF77"),
new SyntaxHighlights("\\$\\w+", "#440044", "#FFBBFF"),
new SyntaxHighlights("\"[^\\n]*?\"", "#ff5500", "#00FF00"),
new SyntaxHighlights("\\'[^\\n]*?\\'", "#ff5500", "#00FF00"),
new SyntaxHighlights("\"/[^\\n]*/i{0,1}\"", "#ff5500", "#00FF00"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
};
}
}
internal class QSharp : CodeLanguage
{
public QSharp()
{
this.Name = "QSharp";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".qs" };
this.Description = "Syntax highlighting for QSharp language";
this.AutoPairingPair = new AutoPairingPair[5]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\W", "#BB0000", "#BB0000"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
new SyntaxHighlights("\\b(namespace|open|operation|using|let|H|M|Reset|return)\\b", "#0066bb", "#00ffff"),
new SyntaxHighlights("\\b(Qubit|Result)\\b", "#00bb66", "#00ff00"),
};
}
}
internal class XML : CodeLanguage
{
public XML()
{
this.Name = "XML";
this.Author = "Julius Kirsch";
this.Filter = new string[2] { ".xml", ".xaml" };
this.Description = "Syntax highlighting for Xml language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),
new SyntaxHighlights("<([^ >!\\/]+)[^>]*>", "#969696", "#0099ff"),
new SyntaxHighlights("<+[/]+[a-zA-Z0-9:?\\-_]+>", "#969696", "#0099ff"),
new SyntaxHighlights("<[a-zA-Z0-9:?\\-]+?.*\\/>", "#969696", "#0099ff"),
new SyntaxHighlights("[-A-Za-z_]+\\=", "#00CA00", "#Ff0000"),
new SyntaxHighlights("\"[^\\n]*?\"", "#00CA00", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("<!--[\\s\\S]*?-->", "#888888", "#888888"),
};
}
}
internal class Python : CodeLanguage
{
public Python()
{
this.Name = "Python";
this.Author = "Julius Kirsch";
this.Filter = new string[1] { ".py" };
this.Description = "Syntax highlighting for Python language";
this.AutoPairingPair = new AutoPairingPair[6]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("`", "`"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),
new SyntaxHighlights("\\b(and|as|assert|break|class|continue|def|del|elif|else|except|False|finally|for|from|global|if|import|in|is|lambda|None|nonlocal|not|or|pass|raise|return|True|try|while|with|yield)\\b", "#aa00cc", "#cc00ff"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#cc9900", "#ffbb00"),
new SyntaxHighlights("\"[^\\n]*?\"", "#ff5500", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("\\#.*", "#888888", "#646464"),
new SyntaxHighlights("\\\"\"\"(.|[\\r\\n])*\\\"\"\"", "#888888", "#646464"),
};
}
}
internal class CSV : CodeLanguage
{
public CSV()
{
this.Name = "CSV";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".csv" };
this.Description = "Syntax highlighting for CSV language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("[\\:\\,\\;]", "#1b9902", "#1b9902")
};
}
}
internal class LaTex : CodeLanguage
{
public LaTex()
{
this.Name = "LaTex";
this.Author = "Finn Freitag";
this.Filter = new string[2] { ".latex", ".tex" };
this.Description = "Syntax highlighting for LaTex language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\\\[a-z]+", "#0033aa", "#0088ff"),
new SyntaxHighlights("%.*", "#888888", "#646464"),
new SyntaxHighlights("[\\[\\]]", "#FFFF00", "#FFFF00"),
new SyntaxHighlights("[\\{\\}]", "#FF0000", "#FF0000"),
new SyntaxHighlights("\\$", "#00bb00", "#00FF00")
};
}
}
internal class TOML : CodeLanguage
{
public TOML()
{
this.Name = "TOML";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".toml" };
this.Description = "Syntax highlighting for TOML language";
this.AutoPairingPair = new AutoPairingPair[]
{
new AutoPairingPair("[", "]"),
new AutoPairingPair("\""),
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\[.*\\]", "#0000FF", "#0000FF"),
new SyntaxHighlights("\\[[\\t\\s]*(\\w+)[\\t\\s]*\\]", "#9900FF", "#9900FF"),
new SyntaxHighlights("(\\w+)[\\s\\t]*\\=", "#DDDD00", "#DDDD00"),
new SyntaxHighlights("\\=\\s+(.+)", "#EE0000", "#EE0000"),
new SyntaxHighlights("[\\[\\]]", "#FFFF00", "#FFFF00"),
new SyntaxHighlights("\\b(true|false)\\b", "#00bb66", "#00ff00"),
new SyntaxHighlights("[\"'][^\\n]*?[\"']", "#D69D84", "#D69D84"),
new SyntaxHighlights("#.*", "#888888", "#888888")
};
}
}
internal class Markdown : CodeLanguage
{
public Markdown()
{
this.Name = "Markdown";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".md" };
this.Description = "Syntax highlighting for Markdown language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("[>~\"'`\\-\\+|\\^\\!_]", "#FF0000", "#FF0000"),
new SyntaxHighlights("#", "#0000FF", "#0000FF"),
new SyntaxHighlights("\\*.*\\*", "#000000", "#FFFFFF", false, true),
new SyntaxHighlights("_.*_", "#000000", "#FFFFFF", false, true),
new SyntaxHighlights("\\*\\*.*\\*\\*", "#000000", "#FFFFFF", true),
new SyntaxHighlights("__.*__", "#000000", "#FFFFFF", true),
new SyntaxHighlights("\\d+\\.", "#00FF00", "#00FF00"),
new SyntaxHighlights("[\\[\\]\\(\\)]", "#FFFF00", "#FFFF00")
};
}
}
internal class CSS : CodeLanguage
{
public CSS()
{
this.Name = "CSS";
this.Author = "Julius Kirsch";
this.Filter = new string[2] { ".css", ".scss" };
this.Description = "Syntax highlighting for CSS language";
this.AutoPairingPair = new AutoPairingPair[5]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("[a-zA-Z-]+.*;", "#ff5500", "#00ffff"),//properties
new SyntaxHighlights("\\b([a-zA-Z_-][a-zA-Z0-9_-]*)(?=\\()", "#bb00bb", "#00ff99"),//functions
new SyntaxHighlights(":[a-z].*(?={)", "#0033ff", "#fffd00"),//pseudo classes/elements
new SyntaxHighlights("(.|#|^).*\\s*{", "#227700", "#44ff00"),//classname
new SyntaxHighlights("(?<=\\d)(?:px|%|em|rem|in|cm|mm|pt|pc|ex|ch|vw|vh|vmin|vmax|ms|s)", "#cc0000", "#ff0000"),//units
new SyntaxHighlights("\\b-?\\d+(?:\\.\\d+)?", "#0000ff", "#cc00ff"),//numbers
new SyntaxHighlights("@([^ ]+)", "#8800ff", "#ff0000"),//first word after the @
new SyntaxHighlights("#[0-9A-Fa-f]{1,8}\\b", "#00bb55", "#cc00ff"),//hexadecimal
new SyntaxHighlights("(\".+?\"|\'.+?\')", "#00aaff", "#ff8800"),//strings
new SyntaxHighlights("(;|:|{|}|,)", "#777777", "#bbbbbb"),//special characters
new SyntaxHighlights("\\/\\*(.|\\n)*?\\*\\/", "#555555", "#888888"),//comments
};
}
}
}

View File

@ -0,0 +1,45 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents a pair of characters used for auto-pairing in text.
/// </summary>
public class AutoPairingPair
{
/// <summary>
/// Initializes a new instance of the AutoPairingPair class with the same value for both the opening and closing characters.
/// </summary>
/// <param name="value">The character value to be used for both opening and closing.</param>
public AutoPairingPair(string value)
{
this.Value = this.Pair = value;
}
/// <summary>
/// Initializes a new instance of the AutoPairingPair class with different values for the opening and closing characters.
/// </summary>
/// <param name="value">The character value to be used as the opening character.</param>
/// <param name="pair">The character value to be used as the closing character.</param>
public AutoPairingPair(string value, string pair)
{
this.Value = value;
this.Pair = pair;
}
/// <summary>
/// Checks if the provided input contains the opening character of the pair.
/// </summary>
/// <param name="input">The input string to check for the opening character.</param>
/// <returns>True if the input contains the opening character; otherwise, false.</returns>
public bool Matches(string input) => input.Contains(this.Value);
/// <summary>
/// Gets or sets the character value used for the opening part of the auto-pairing pair.
/// </summary>
public string Value { get; set; }
/// <summary>
/// Gets or sets the character value used for the closing part of the auto-pairing pair.
/// </summary>
public string Pair { get; set; }
}
}

View File

@ -0,0 +1,37 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the font style settings for a code element in the text.
/// </summary>
public class CodeFontStyle
{
/// <summary>
/// Initializes a new instance of the CodeFontStyle class with the specified font style settings.
/// </summary>
/// <param name="underlined">true if the code element should be displayed with an underline; otherwise, false.</param>
/// <param name="italic">true if the code element should be displayed in italic font; otherwise, false.</param>
/// <param name="bold">true if the code element should be displayed in bold font; otherwise, false.</param>
public CodeFontStyle(bool underlined, bool italic, bool bold)
{
this.Italic = italic;
this.Bold = bold;
this.Underlined = underlined;
}
/// <summary>
/// Gets or sets a value indicating whether the code element should be displayed with an underline.
/// </summary>
public bool Underlined { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the code element should be displayed in bold font.
/// </summary>
public bool Bold { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the code element should be displayed in italic font.
/// </summary>
public bool Italic { get; set; }
}
}

View File

@ -0,0 +1,39 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents a code language configuration used for syntax highlighting and auto-pairing in the text content.
/// </summary>
public class CodeLanguage
{
/// <summary>
/// Gets or sets the name of the code language.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the description of the code language.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Gets or sets an array of file filters for the code language.
/// </summary>
public string[] Filter { get; set; }
/// <summary>
/// Gets or sets the author of the code language definition.
/// </summary>
public string Author { get; set; }
/// <summary>
/// Gets or sets an array of syntax highlights for the code language.
/// </summary>
public SyntaxHighlights[] Highlights { get; set; }
/// <summary>
/// Gets or sets an array of auto-pairing pairs for the code language.
/// </summary>
public AutoPairingPair[] AutoPairingPair { get; set; }
}
}

View File

@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TextControlBoxNS.Languages;
namespace TextControlBoxNS
{
/// <summary>
/// Represents the unique identifiers for different code languages used for syntax highlighting.
/// </summary>
public enum CodeLanguageId
{
INI,
/// <summary>
/// Identifier for Batch code language.
/// </summary>
Batch,
/// <summary>
/// Identifier for C++ code language.
/// </summary>
Cpp,
/// <summary>
/// Identifier for C# code language.
/// </summary>
CSharp,
/// <summary>
/// Identifier for configuration file code language.
/// </summary>
ConfigFile,
/// <summary>
/// Identifier for CSS code language.
/// </summary>
CSS,
/// <summary>
/// Identifier for CSV code language.
/// </summary>
CSV,
/// <summary>
/// Identifier for GCode code language.
/// </summary>
GCode,
/// <summary>
/// Identifier for HexFile code language.
/// </summary>
HexFile,
/// <summary>
/// Identifier for HTML code language.
/// </summary>
Html,
/// <summary>
/// Identifier for Java code language.
/// </summary>
Java,
/// <summary>
/// Identifier for JavaScript code language.
/// </summary>
Javascript,
/// <summary>
/// Identifier for JSON code language.
/// </summary>
Json,
/// <summary>
/// Identifier for LaTeX code language.
/// </summary>
Latex,
/// <summary>
/// Identifier for Markdown code language.
/// </summary>
Markdown,
/// <summary>
/// Identifier for PHP code language.
/// </summary>
PHP,
/// <summary>
/// Identifier for Python code language.
/// </summary>
Python,
/// <summary>
/// Identifier for Q# code language.
/// </summary>
QSharp,
/// <summary>
/// Identifier for TOML code language.
/// </summary>
TOML,
/// <summary>
/// Identifier for XML code language.
/// </summary>
XML,
/// <summary>
/// Identifier for no code language.
/// </summary>
None,
}
}

View File

@ -0,0 +1,51 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the position of the cursor in the textbox.
/// </summary>
/// <remarks>
/// The CursorPosition class stores the position of the cursor within the textbox.
/// It consists of two properties: CharacterPosition and LineNumber.
/// The CharacterPosition property indicates the index of the cursor within the current line (zero-based index).
/// The LineNumber property represents the line number on which the cursor is currently positioned (zero-based index).
/// </remarks>
public class CursorPosition
{
internal CursorPosition(int characterPosition = 0, int lineNumber = 0)
{
this.CharacterPosition = characterPosition;
this.LineNumber = lineNumber;
}
internal CursorPosition(CursorPosition currentCursorPosition)
{
if (currentCursorPosition == null)
return;
this.CharacterPosition = currentCursorPosition.CharacterPosition;
this.LineNumber = currentCursorPosition.LineNumber;
}
/// <summary>
/// Gets the character position of the cursor within the current line.
/// </summary>
public int CharacterPosition { get; internal set; } = 0;
/// <summary>
/// Gets the line number in which the cursor is currently positioned.
/// </summary>
public int LineNumber { get; internal set; } = 0;
internal void AddToCharacterPos(int add)
{
CharacterPosition += add;
}
internal void SubtractFromCharacterPos(int subtract)
{
CharacterPosition -= subtract;
if (CharacterPosition < 0)
CharacterPosition = 0;
}
internal static CursorPosition ChangeLineNumber(CursorPosition currentCursorPosition, int lineNumber)
{
return new CursorPosition(currentCursorPosition.CharacterPosition, lineNumber);
}
}
}

View File

@ -0,0 +1,43 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the size of the cursor in the textbox.
/// </summary>
public class CursorSize
{
/// <summary>
/// Creates a new instance of the CursorSize class
/// </summary>
/// <param name="width">The width of the cursor</param>
/// <param name="height">The height of the cursor</param>
/// <param name="offsetX">The x-offset from the actual cursor position</param>
/// <param name="offsetY">The y-offset from the actual cursor position</param>
public CursorSize(float width = 0, float height = 0, float offsetX = 0, float offsetY = 0)
{
this.Width = width;
this.Height = height;
this.OffsetX = offsetX;
this.OffsetY = offsetY;
}
/// <summary>
/// The width of the cursor
/// </summary>
public float Width { get; private set; }
/// <summary>
/// The height of the cursor
/// </summary>
public float Height { get; private set; }
/// <summary>
/// The left/right offset from the actual cursor position
/// </summary>
public float OffsetX { get; private set; }
/// <summary>
/// The top/bottom offset from the actual cursor position
/// </summary>
public float OffsetY { get; private set; }
}
}

View File

@ -0,0 +1,11 @@
namespace TextControlBoxNS
{
internal class JsonCodeLanguage
{
public string Name { get; set; }
public string Description { get; set; }
public string Filter { get; set; }
public string Author { get; set; }
public SyntaxHighlights[] Highlights;
}
}

View File

@ -0,0 +1,29 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the result of a JSON load operation for a code language in the textbox.
/// </summary>
public class JsonLoadResult
{
/// <summary>
/// Initializes a new instance of the JsonLoadResult class with the specified loading status and CodeLanguage.
/// </summary>
/// <param name="succeed">true if the loading operation succeeded; otherwise, false.</param>
/// <param name="codeLanguage">The CodeLanguage loaded from the JSON data.</param>
public JsonLoadResult(bool succeed, CodeLanguage codeLanguage)
{
this.Succeed = succeed;
this.CodeLanguage = codeLanguage;
}
/// <summary>
/// Gets or sets a value indicating whether the loading operation succeeded.
/// </summary>
public bool Succeed { get; set; }
/// <summary>
/// Gets or sets the CodeLanguage that was loaded from the JSON data.
/// </summary>
public CodeLanguage CodeLanguage { get; set; }
}
}

View File

@ -0,0 +1,40 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the position of a scrollbar, containing the horizontal and vertical scroll positions.
/// </summary>
public class ScrollBarPosition
{
/// <summary>
/// Initializes a new instance of the ScrollBarPosition class with the provided values.
/// </summary>
/// <param name="scrollBarPosition">The existing ScrollBarPosition object from which to copy the values.</param>
public ScrollBarPosition(ScrollBarPosition scrollBarPosition)
{
this.ValueX = scrollBarPosition.ValueX;
this.ValueY = scrollBarPosition.ValueY;
}
/// <summary>
/// Creates a new instance of the ScrollBarPosition class
/// </summary>
/// <param name="valueX">The horizontal amount scrolled</param>
/// <param name="valueY">The vertical amount scrolled</param>
public ScrollBarPosition(double valueX = 0, double valueY = 0)
{
this.ValueX = valueX;
this.ValueY = valueY;
}
/// <summary>
/// The amount scrolled horizontally
/// </summary>
public double ValueX { get; set; }
/// <summary>
/// The amount scrolled vertically
/// </summary>
public double ValueY { get; set; }
}
}

View File

@ -0,0 +1,28 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the class that will be returned by the SelectionChanged event of the TextControlBox.
/// </summary>
public class SelectionChangedEventHandler
{
/// <summary>
/// Represents the position of the cursor within the current line.
/// </summary>
public int CharacterPositionInLine { get; set; }
/// <summary>
/// Represents the line number where the cursor is currently located.
/// </summary>
public int LineNumber { get; set; }
/// <summary>
/// Represents the starting index of the selection.
/// </summary>
public int SelectionStartIndex { get; set; }
/// <summary>
/// Represents the length of the selection.
/// </summary>
public int SelectionLength { get; set; }
}
}

View File

@ -0,0 +1,71 @@
using System.Drawing;
using TextControlBoxNS.Extensions;
namespace TextControlBoxNS
{
/// <summary>
/// Represents a syntax highlight definition for a specific pattern in the text.
/// </summary>
public class SyntaxHighlights
{
private readonly ColorConverter ColorConverter = new ColorConverter();
/// <summary>
/// Initializes a new instance of the SyntaxHighlights class with the specified pattern, colors, and font styles.
/// </summary>
/// <param name="pattern">The pattern to be highlighted in the text content.</param>
/// <param name="colorLight">The color representation for the pattern in the light theme (e.g., "#RRGGBB" format).</param>
/// <param name="colorDark">The color representation for the pattern in the dark theme (e.g., "#RRGGBB" format).</param>
/// <param name="bold">true if the pattern should be displayed in bold font; otherwise, false.</param>
/// <param name="italic">true if the pattern should be displayed in italic font; otherwise, false.</param>
/// <param name="underlined">true if the pattern should be displayed with an underline; otherwise, false.</param>
public SyntaxHighlights(string pattern, string colorLight, string colorDark, bool bold = false, bool italic = false, bool underlined = false)
{
this.Pattern = pattern;
this.ColorDark = colorDark;
this.ColorLight = colorLight;
if (underlined || italic || bold)
this.CodeStyle = new CodeFontStyle(underlined, italic, bold);
}
/// <summary>
/// Gets or sets the font style for the pattern.
/// </summary>
public CodeFontStyle CodeStyle { get; set; } = null;
/// <summary>
/// Gets or sets the pattern to be highlighted in the text content.
/// </summary>
public string Pattern { get; set; }
/// <summary>
/// Gets the color representation for the pattern in the dark theme.
/// </summary>
public Windows.UI.Color ColorDark_Clr { get; private set; }
/// <summary>
/// Gets the color representation for the pattern in the light theme.
/// </summary>
public Windows.UI.Color ColorLight_Clr { get; private set; }
/// <summary>
/// Sets the color representation for the pattern in the dark theme.
/// </summary>
/// <param name="value">The color representation for the pattern in the dark theme (e.g., "#RRGGBB" format).</param>
public string ColorDark
{
set => ColorDark_Clr = ((Color)ColorConverter.ConvertFromString(value)).ToMediaColor();
}
/// <summary>
/// Sets the color representation for the pattern in the light theme.
/// </summary>
/// <param name="value">The color representation for the pattern in the light theme (e.g., "#RRGGBB" format).</param>
public string ColorLight
{
set => ColorLight_Clr = ((Color)ColorConverter.ConvertFromString(value)).ToMediaColor();
}
}
}

View File

@ -0,0 +1,89 @@
using Microsoft.UI.Xaml.Media;
using Windows.UI;
namespace TextControlBoxNS
{
/// <summary>
/// Represents the design settings for the textbox.
/// </summary>
public class TextControlBoxDesign
{
/// <summary>
/// Create an instance of the TextControlBoxDesign from a given design
/// </summary>
/// <param name="design">The design to create a new instance from</param>
public TextControlBoxDesign(TextControlBoxDesign design)
{
this.Background = design.Background;
this.TextColor = design.TextColor;
this.SelectionColor = design.SelectionColor;
this.CursorColor = design.CursorColor;
this.LineHighlighterColor = design.LineHighlighterColor;
this.LineNumberColor = design.LineNumberColor;
this.LineNumberBackground = design.LineNumberBackground;
}
/// <summary>
/// Create a new instance of the TextControlBoxDesign class
/// </summary>
/// <param name="background">The background color of the textbox</param>
/// <param name="textColor">The color of the text</param>
/// <param name="selectionColor">The color of the selection</param>
/// <param name="cursorColor">The color of the cursor</param>
/// <param name="lineHighlighterColor">The color of the linehighlighter</param>
/// <param name="lineNumberColor">The color of the linenumber</param>
/// <param name="lineNumberBackground">The background color of the linenumbers</param>
/// <param name="searchHighlightColor">The color of the search highlights</param>
public TextControlBoxDesign(Brush background, Color textColor, Color selectionColor, Color cursorColor, Color lineHighlighterColor, Color lineNumberColor, Color lineNumberBackground, Color searchHighlightColor)
{
this.Background = background;
this.TextColor = textColor;
this.SelectionColor = selectionColor;
this.CursorColor = cursorColor;
this.LineHighlighterColor = lineHighlighterColor;
this.LineNumberColor = lineNumberColor;
this.LineNumberBackground = lineNumberBackground;
this.SearchHighlightColor = searchHighlightColor;
}
/// <summary>
/// Gets or sets the background color of the textbox.
/// </summary>
public Brush Background { get; set; }
/// <summary>
/// Gets or sets the text color of the textbox.
/// </summary>
public Color TextColor { get; set; }
/// <summary>
/// Gets or sets the color of the selected text in the textbox.
/// </summary>
public Color SelectionColor { get; set; }
/// <summary>
/// Gets or sets the color of the cursor in the textbox.
/// </summary>
public Color CursorColor { get; set; }
/// <summary>
/// Gets or sets the color of the line highlighter in the textbox.
/// </summary>
public Color LineHighlighterColor { get; set; }
/// <summary>
/// Gets or sets the color of the line numbers in the textbox.
/// </summary>
public Color LineNumberColor { get; set; }
/// <summary>
/// Gets or sets the background color of the line numbers in the textbox.
/// </summary>
public Color LineNumberBackground { get; set; }
/// <summary>
/// Gets or sets the color used to highlight search results in the textbox.
/// </summary>
public Color SearchHighlightColor { get; set; }
}
}

View File

@ -0,0 +1,52 @@
namespace TextControlBoxNS.Text
{
internal class TextSelection
{
public TextSelection()
{
Index = 0;
Length = 0;
StartPosition = null;
EndPosition = null;
}
public TextSelection(int index = 0, int length = 0, CursorPosition startPosition = null, CursorPosition endPosition = null)
{
Index = index;
Length = length;
StartPosition = startPosition;
EndPosition = endPosition;
}
public TextSelection(CursorPosition startPosition = null, CursorPosition endPosition = null)
{
StartPosition = startPosition;
EndPosition = endPosition;
}
public TextSelection(TextSelection textSelection)
{
StartPosition = new CursorPosition(textSelection.StartPosition);
EndPosition = new CursorPosition(textSelection.EndPosition);
Index = textSelection.Index;
Length = textSelection.Length;
}
public int Index { get; set; }
public int Length { get; set; }
public CursorPosition StartPosition { get; set; }
public CursorPosition EndPosition { get; set; }
public bool IsLineInSelection(int line)
{
if (this.StartPosition != null && this.EndPosition != null)
{
if (this.StartPosition.LineNumber > this.EndPosition.LineNumber)
return this.StartPosition.LineNumber < line && this.EndPosition.LineNumber > line;
else if (this.StartPosition.LineNumber == this.EndPosition.LineNumber)
return this.StartPosition.LineNumber != line;
else
return this.StartPosition.LineNumber > line && this.EndPosition.LineNumber < line;
}
return false;
}
}
}

View File

@ -0,0 +1,29 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the position and length of a text selection in the textbox.
/// </summary>
public class TextSelectionPosition
{
/// <summary>
/// Initializes a new instance of the TextSelectionPosition class with the specified index and length.
/// </summary>
/// <param name="index">The start index of the text selection.</param>
/// <param name="length">The length of the text selection.</param>
public TextSelectionPosition(int index = 0, int length = 0)
{
this.Index = index;
this.Length = length;
}
/// <summary>
/// Gets or sets the start index of the text selection.
/// </summary>
public int Index { get; set; }
/// <summary>
/// Gets or sets the length of the text selection.
/// </summary>
public int Length { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using TextControlBoxNS.Text;
namespace TextControlBoxNS.Models
{
internal struct UndoRedoItem
{
public int StartLine { get; set; }
public string UndoText { get; set; }
public string RedoText { get; set; }
public int UndoCount { get; set; }
public int RedoCount { get; set; }
public TextSelection Selection { get; set; }
}
}

View File

@ -0,0 +1,52 @@
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using System.Numerics;
using Windows.Foundation;
namespace TextControlBoxNS.Renderer
{
internal class CursorRenderer
{
public static int GetCursorLineFromPoint(Point point, float singleLineHeight, int numberOfRenderedLines, int numberOfStartLine)
{
//Calculate the relative linenumber, where the pointer was pressed at
int linenumber = (int)(point.Y / singleLineHeight);
linenumber += numberOfStartLine;
return Math.Clamp(linenumber, 0, numberOfStartLine + numberOfRenderedLines - 1);
}
public static int GetCharacterPositionFromPoint(string currentLine, CanvasTextLayout textLayout, Point cursorPosition, float marginLeft)
{
if (currentLine == null || textLayout == null)
return 0;
textLayout.HitTest(
(float)cursorPosition.X - marginLeft, 0,
out var textLayoutRegion);
return textLayoutRegion.CharacterIndex;
}
//Return the position in pixels of the cursor in the current line
public static float GetCursorPositionInLine(CanvasTextLayout currentLineTextLayout, CursorPosition cursorPosition, float xOffset)
{
if (currentLineTextLayout == null)
return 0;
return currentLineTextLayout.GetCaretPosition(cursorPosition.CharacterPosition < 0 ? 0 : cursorPosition.CharacterPosition, false).X + xOffset;
}
//Return the cursor Width
public static void RenderCursor(CanvasTextLayout textLayout, int characterPosition, float xOffset, float y, float fontSize, CursorSize customSize, CanvasDrawEventArgs args, CanvasSolidColorBrush cursorColorBrush)
{
if (textLayout == null)
return;
Vector2 vector = textLayout.GetCaretPosition(characterPosition < 0 ? 0 : characterPosition, false);
if (customSize == null)
args.DrawingSession.FillRectangle(vector.X + xOffset, y, 1, fontSize, cursorColorBrush);
else
args.DrawingSession.FillRectangle(vector.X + xOffset + customSize.OffsetX, y + customSize.OffsetY, (float)customSize.Width, (float)customSize.Height, cursorColorBrush);
}
}
}

View File

@ -0,0 +1,17 @@
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
namespace TextControlBoxNS.Renderer
{
internal class LineHighlighterRenderer
{
public static void Render(float canvasWidth, CanvasTextLayout textLayout, float y, float fontSize, CanvasDrawEventArgs args, CanvasSolidColorBrush backgroundBrush)
{
if (textLayout == null)
return;
args.DrawingSession.FillRectangle(0, y, canvasWidth, fontSize, backgroundBrush);
}
}
}

View File

@ -0,0 +1,47 @@
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using System.Text.RegularExpressions;
using TextControlBoxNS.Helper;
using Windows.UI;
namespace TextControlBoxNS.Renderer
{
internal class SearchHighlightsRenderer
{
public static void RenderHighlights(
CanvasDrawEventArgs args,
CanvasTextLayout drawnTextLayout,
string renderedText,
int[] possibleLines,
string searchRegex,
float scrollOffsetX,
float offsetTop,
Color searchHighlightColor)
{
if (searchRegex == null || possibleLines == null || possibleLines.Length == 0)
return;
MatchCollection matches;
try
{
matches = Regex.Matches(renderedText, searchRegex);
}
catch (ArgumentException)
{
return;
}
for (int j = 0; j < matches.Count; j++)
{
var match = matches[j];
var layoutRegion = drawnTextLayout.GetCharacterRegions(match.Index, match.Length);
if (layoutRegion.Length > 0)
{
args.DrawingSession.FillRectangle(Utils.CreateRect(layoutRegion[0].LayoutBounds, scrollOffsetX, offsetTop), searchHighlightColor);
}
}
return;
}
}
}

View File

@ -0,0 +1,209 @@
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Linq;
using TextControlBoxNS.Helper;
using TextControlBoxNS.Text;
using Windows.Foundation;
using Windows.UI;
namespace TextControlBoxNS.Renderer
{
internal class SelectionRenderer
{
public bool HasSelection = false;
public bool IsSelecting = false;
public bool IsSelectingOverLinenumbers = false;
public CursorPosition SelectionStartPosition = null;
public CursorPosition SelectionEndPosition = null;
public int SelectionLength = 0;
public int SelectionStart = 0;
//Draw the actual selection and return the cursorposition. Return -1 if no selection was drawn
public TextSelection DrawSelection(
CanvasTextLayout textLayout,
IEnumerable<string> renderedLines,
CanvasDrawEventArgs args,
float marginLeft,
float marginTop,
int unrenderedLinesToRenderStart,
int numberOfRenderedLines,
float fontSize,
Color selectionColor
)
{
if (HasSelection && SelectionEndPosition != null && SelectionStartPosition != null)
{
int selStartIndex = 0;
int selEndIndex = 0;
int characterPosStart = SelectionStartPosition.CharacterPosition;
int characterPosEnd = SelectionEndPosition.CharacterPosition;
//Render the selection on position 0 if the user scrolled the start away
if (SelectionEndPosition.LineNumber < SelectionStartPosition.LineNumber)
{
if (SelectionEndPosition.LineNumber < unrenderedLinesToRenderStart)
characterPosEnd = 0;
if (SelectionStartPosition.LineNumber < unrenderedLinesToRenderStart + 1)
characterPosStart = 0;
}
else if (SelectionEndPosition.LineNumber == SelectionStartPosition.LineNumber)
{
if (SelectionStartPosition.LineNumber < unrenderedLinesToRenderStart)
characterPosStart = 0;
if (SelectionEndPosition.LineNumber < unrenderedLinesToRenderStart)
characterPosEnd = 0;
}
else
{
if (SelectionStartPosition.LineNumber < unrenderedLinesToRenderStart)
characterPosStart = 0;
if (SelectionEndPosition.LineNumber < unrenderedLinesToRenderStart + 1)
characterPosEnd = 0;
}
if (SelectionStartPosition.LineNumber == SelectionEndPosition.LineNumber)
{
int lenghtToLine = 0;
for (int i = 0; i < SelectionStartPosition.LineNumber - unrenderedLinesToRenderStart; i++)
{
if (i < numberOfRenderedLines)
{
lenghtToLine += renderedLines.ElementAt(i).Length + 1;
}
}
selStartIndex = characterPosStart + lenghtToLine;
selEndIndex = characterPosEnd + lenghtToLine;
}
else
{
for (int i = 0; i < SelectionStartPosition.LineNumber - unrenderedLinesToRenderStart; i++)
{
if (i >= numberOfRenderedLines) //Out of range of the List (do nothing)
break;
selStartIndex += renderedLines.ElementAt(i).Length + 1;
}
selStartIndex += characterPosStart;
for (int i = 0; i < SelectionEndPosition.LineNumber - unrenderedLinesToRenderStart; i++)
{
if (i >= numberOfRenderedLines) //Out of range of the List (do nothing)
break;
selEndIndex += renderedLines.ElementAt(i).Length + 1;
}
selEndIndex += characterPosEnd;
}
SelectionStart = Math.Min(selStartIndex, selEndIndex);
if (SelectionStart < 0)
SelectionStart = 0;
if (SelectionLength < 0)
SelectionLength = 0;
if (selEndIndex > selStartIndex)
SelectionLength = selEndIndex - selStartIndex;
else
SelectionLength = selStartIndex - selEndIndex;
CanvasTextLayoutRegion[] descriptions = textLayout.GetCharacterRegions(SelectionStart, SelectionLength);
for (int i = 0; i < descriptions.Length; i++)
{
//Change the width if selection in an emty line or starts at a line end
if (descriptions[i].LayoutBounds.Width == 0 && descriptions.Length > 1)
{
var bounds = descriptions[i].LayoutBounds;
descriptions[i].LayoutBounds = new Rect { Width = fontSize / 4, Height = bounds.Height, X = bounds.X, Y = bounds.Y };
}
args.DrawingSession.FillRectangle(Utils.CreateRect(descriptions[i].LayoutBounds, marginLeft, marginTop), selectionColor);
}
return new TextSelection(SelectionStart, SelectionLength, new CursorPosition(SelectionStartPosition), new CursorPosition(SelectionEndPosition));
}
return null;
}
//returns whether the pointer is over a selection
public bool PointerIsOverSelection(Point pointerPosition, TextSelection selection, CanvasTextLayout textLayout)
{
if (textLayout == null || selection == null)
return false;
CanvasTextLayoutRegion[] regions = textLayout.GetCharacterRegions(selection.Index, selection.Length);
for (int i = 0; i < regions.Length; i++)
{
if (regions[i].LayoutBounds.Contains(pointerPosition))
return true;
}
return false;
}
public bool CursorIsInSelection(CursorPosition cursorPosition, TextSelection textSelection)
{
if (textSelection == null)
return false;
textSelection = Selection.OrderTextSelection(textSelection);
//Cursorposition is smaller than the start of selection
if (textSelection.StartPosition.LineNumber > cursorPosition.LineNumber)
return false;
//Selectionend is smaller than Cursorposition -> not in selection
if (textSelection.EndPosition.LineNumber < cursorPosition.LineNumber)
return false;
//Selection-start line equals Cursor line:
if (cursorPosition.LineNumber == textSelection.StartPosition.LineNumber)
return cursorPosition.CharacterPosition > textSelection.StartPosition.CharacterPosition;
//Selection-end line equals Cursor line
else if (cursorPosition.LineNumber == textSelection.EndPosition.LineNumber)
return cursorPosition.CharacterPosition < textSelection.EndPosition.CharacterPosition;
return true;
}
//Clear the selection
public void ClearSelection()
{
HasSelection = false;
IsSelecting = false;
SelectionEndPosition = null;
SelectionStartPosition = null;
}
public void SetSelection(TextSelection selection)
{
if (selection == null)
return;
SetSelection(selection.StartPosition, selection.EndPosition);
}
public void SetSelection(CursorPosition startPosition, CursorPosition endPosition)
{
IsSelecting = true;
SelectionStartPosition = startPosition;
SelectionEndPosition = endPosition;
IsSelecting = false;
HasSelection = true;
}
public void SetSelectionStart(CursorPosition startPosition)
{
IsSelecting = true;
SelectionStartPosition = startPosition;
IsSelecting = false;
HasSelection = true;
}
public void SetSelectionEnd(CursorPosition endPosition)
{
IsSelecting = true;
SelectionEndPosition = endPosition;
IsSelecting = false;
HasSelection = true;
}
}
}

View File

@ -0,0 +1,73 @@
using Microsoft.Graphics.Canvas.Text;
using Microsoft.UI.Xaml;
using Newtonsoft.Json;
using System;
using System.Text.RegularExpressions;
using Windows.UI.Text;
using Windows.UI.Xaml;
namespace TextControlBoxNS.Renderer
{
internal class SyntaxHighlightingRenderer
{
public static FontWeight BoldFont = new FontWeight { Weight = 600 };
public static FontStyle ItalicFont = FontStyle.Italic;
public static void UpdateSyntaxHighlighting(CanvasTextLayout drawnTextLayout, ApplicationTheme theme, CodeLanguage codeLanguage, bool syntaxHighlighting, string renderedText)
{
if (codeLanguage == null || !syntaxHighlighting)
return;
var highlights = codeLanguage.Highlights;
for (int i = 0; i < highlights.Length; i++)
{
var matches = Regex.Matches(renderedText, highlights[i].Pattern, RegexOptions.Compiled);
var highlight = highlights[i];
var color = theme == ApplicationTheme.Light ? highlight.ColorLight_Clr : highlight.ColorDark_Clr;
for (int j = 0; j < matches.Count; j++)
{
var match = matches[j];
int index = match.Index;
int length = match.Length;
drawnTextLayout.SetColor(index, length, color);
if (highlight.CodeStyle != null)
{
if (highlight.CodeStyle.Italic)
drawnTextLayout.SetFontStyle(index, length, ItalicFont);
if (highlight.CodeStyle.Bold)
drawnTextLayout.SetFontWeight(index, length, BoldFont);
if (highlight.CodeStyle.Underlined)
drawnTextLayout.SetUnderline(index, length, true);
}
}
}
}
public static JsonLoadResult GetCodeLanguageFromJson(string json)
{
try
{
var jsonCodeLanguage = JsonConvert.DeserializeObject<JsonCodeLanguage>(json);
//Apply the filter as an array
var codelanguage = new CodeLanguage
{
Author = jsonCodeLanguage.Author,
Description = jsonCodeLanguage.Description,
Highlights = jsonCodeLanguage.Highlights,
Name = jsonCodeLanguage.Name,
Filter = jsonCodeLanguage.Filter.Split("|", StringSplitOptions.RemoveEmptyEntries),
};
return new JsonLoadResult(true, codelanguage);
}
catch (JsonReaderException)
{
return new JsonLoadResult(false, null);
}
catch (JsonSerializationException)
{
return new JsonLoadResult(false, null);
}
}
}
}

View File

@ -0,0 +1,38 @@
using System.Linq;
namespace TextControlBoxNS.Text
{
internal class AutoPairing
{
public static (string text, int length) AutoPair(TextControlBox textbox, string inputtext)
{
if (!textbox.DoAutoPairing || inputtext.Length != 1 || textbox.CodeLanguage == null || textbox.CodeLanguage.AutoPairingPair == null)
return (inputtext, inputtext.Length);
var res = textbox.CodeLanguage.AutoPairingPair.Where(x => x.Matches(inputtext));
if (res.Count() == 0)
return (inputtext, inputtext.Length);
if (res.ElementAt(0) is AutoPairingPair pair)
return (inputtext + pair.Pair, inputtext.Length);
return (inputtext, inputtext.Length);
}
public static string AutoPairSelection(TextControlBox textbox, string inputtext)
{
if (!textbox.DoAutoPairing || inputtext.Length != 1 || textbox.CodeLanguage == null || textbox.CodeLanguage.AutoPairingPair == null)
return inputtext;
var res = textbox.CodeLanguage.AutoPairingPair.Where(x => x.Value.Equals(inputtext));
if (res.Count() == 0)
return inputtext;
if (res.ElementAt(0) is AutoPairingPair pair)
{
textbox.SurroundSelectionWith(inputtext, pair.Pair);
return null;
}
return inputtext;
}
}
}

View File

@ -0,0 +1,170 @@
using Collections.Pooled;
using System;
using TextControlBoxNS.Extensions;
using TextControlBoxNS.Helper;
namespace TextControlBoxNS.Text
{
internal class Cursor
{
private static int CheckIndex(string str, int index) => Math.Clamp(index, 0, str.Length - 1);
public static int CursorPositionToIndex(PooledList<string> totalLines, CursorPosition cursorPosition)
{
int cursorIndex = cursorPosition.CharacterPosition;
int lineNumber = cursorPosition.LineNumber < totalLines.Count ? cursorIndex : totalLines.Count - 1;
for (int i = 0; i < lineNumber; i++)
{
cursorIndex += totalLines.GetLineLength(i) + 1;
}
return cursorIndex;
}
public static bool Equals(CursorPosition curPos1, CursorPosition curPos2)
{
if (curPos1 == null || curPos2 == null)
return false;
if (curPos1.LineNumber == curPos2.LineNumber)
return curPos1.CharacterPosition == curPos2.CharacterPosition;
return false;
}
//Calculate the number of characters from the cursorposition to the next character or digit to the left and to the right
public static int CalculateStepsToMoveLeft2(string currentLine, int cursorCharPosition)
{
if (currentLine.Length == 0)
return 0;
int stepsToMove = 0;
for (int i = cursorCharPosition - 1; i >= 0; i--)
{
char currentCharacter = currentLine[CheckIndex(currentLine, i)];
if (char.IsLetterOrDigit(currentCharacter) || currentCharacter == '_')
stepsToMove++;
else if (i == cursorCharPosition - 1 && char.IsWhiteSpace(currentCharacter))
return 0;
else
break;
}
return stepsToMove;
}
public static int CalculateStepsToMoveRight2(string currentLine, int cursorCharPosition)
{
if (currentLine.Length == 0)
return 0;
int stepsToMove = 0;
for (int i = cursorCharPosition; i < currentLine.Length; i++)
{
char currentCharacter = currentLine[CheckIndex(currentLine, i)];
if (char.IsLetterOrDigit(currentCharacter) || currentCharacter == '_')
stepsToMove++;
else if (i == cursorCharPosition && char.IsWhiteSpace(currentCharacter))
return 0;
else
break;
}
return stepsToMove;
}
//Calculates how many characters the cursor needs to move if control is pressed
//Returns 1 when control is not pressed
public static int CalculateStepsToMoveLeft(string currentLine, int cursorCharPosition)
{
if (!Utils.IsKeyPressed(Windows.System.VirtualKey.Control))
return 1;
int stepsToMove = 0;
for (int i = cursorCharPosition - 1; i >= 0; i--)
{
char CurrentCharacter = currentLine[CheckIndex(currentLine, i)];
if (char.IsLetterOrDigit(CurrentCharacter) || CurrentCharacter == '_')
stepsToMove++;
else if (i == cursorCharPosition - 1 && char.IsWhiteSpace(CurrentCharacter))
stepsToMove++;
else
break;
}
//If it ignores the ControlKey return the real value of stepsToMove otherwise
//return 1 if stepsToMove is 0
return stepsToMove == 0 ? 1 : stepsToMove;
}
public static int CalculateStepsToMoveRight(string currentLine, int cursorCharPosition)
{
if (!Utils.IsKeyPressed(Windows.System.VirtualKey.Control))
return 1;
int stepsToMove = 0;
for (int i = cursorCharPosition; i < currentLine.Length; i++)
{
char CurrentCharacter = currentLine[CheckIndex(currentLine, i)];
if (char.IsLetterOrDigit(CurrentCharacter) || CurrentCharacter == '_')
stepsToMove++;
else if (i == cursorCharPosition && char.IsWhiteSpace(CurrentCharacter))
stepsToMove++;
else
break;
}
//If it ignores the ControlKey return the real value of stepsToMove otherwise
//return 1 if stepsToMove is 0
return stepsToMove == 0 ? 1 : stepsToMove;
}
//Move cursor:
public static void MoveLeft(CursorPosition currentCursorPosition, PooledList<string> totalLines, string currentLine)
{
if (currentCursorPosition.LineNumber < 0)
return;
int currentLineLength = totalLines.GetLineLength(currentCursorPosition.LineNumber);
if (currentCursorPosition.CharacterPosition == 0 && currentCursorPosition.LineNumber > 0)
{
currentCursorPosition.CharacterPosition = totalLines.GetLineLength(currentCursorPosition.LineNumber - 1);
currentCursorPosition.LineNumber -= 1;
}
else if (currentCursorPosition.CharacterPosition > currentLineLength)
currentCursorPosition.CharacterPosition = currentLineLength - 1;
else if (currentCursorPosition.CharacterPosition > 0)
currentCursorPosition.CharacterPosition -= CalculateStepsToMoveLeft(currentLine, currentCursorPosition.CharacterPosition);
}
public static void MoveRight(CursorPosition currentCursorPosition, PooledList<string> totalLines, string currentLine)
{
int lineLength = totalLines.GetLineLength(currentCursorPosition.LineNumber);
if (currentCursorPosition.LineNumber > totalLines.Count - 1)
return;
if (currentCursorPosition.CharacterPosition == lineLength && currentCursorPosition.LineNumber < totalLines.Count - 1)
{
currentCursorPosition.CharacterPosition = 0;
currentCursorPosition.LineNumber += 1;
}
else if (currentCursorPosition.CharacterPosition < lineLength)
currentCursorPosition.CharacterPosition += CalculateStepsToMoveRight(currentLine, currentCursorPosition.CharacterPosition);
if (currentCursorPosition.CharacterPosition > lineLength)
currentCursorPosition.CharacterPosition = lineLength;
}
public static CursorPosition MoveDown(CursorPosition currentCursorPosition, int totalLinesLength)
{
CursorPosition returnValue = new CursorPosition(currentCursorPosition);
if (currentCursorPosition.LineNumber < totalLinesLength - 1)
returnValue = CursorPosition.ChangeLineNumber(currentCursorPosition, currentCursorPosition.LineNumber + 1);
return returnValue;
}
public static CursorPosition MoveUp(CursorPosition currentCursorPosition)
{
CursorPosition returnValue = new CursorPosition(currentCursorPosition);
if (currentCursorPosition.LineNumber > 0)
returnValue = CursorPosition.ChangeLineNumber(returnValue, currentCursorPosition.LineNumber - 1);
return returnValue;
}
public static void MoveToLineEnd(CursorPosition cursorPosition, string currentLine)
{
cursorPosition.CharacterPosition = currentLine.Length;
}
public static void MoveToLineStart(CursorPosition cursorPosition)
{
cursorPosition.CharacterPosition = 0;
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Text.RegularExpressions;
namespace TextControlBoxNS.Text
{
internal class LineEndings
{
public static string LineEndingToString(LineEnding lineEnding)
{
return
lineEnding == LineEnding.LF ? "\n" :
lineEnding == LineEnding.CRLF ? "\r\n" :
"\r";
}
public static LineEnding FindLineEnding(string text)
{
if (text.IndexOf("\r\n", StringComparison.Ordinal) > -1)
return LineEnding.CRLF;
else if (text.IndexOf("\n", StringComparison.Ordinal) > -1)
return LineEnding.LF;
else if (text.IndexOf("\r", StringComparison.Ordinal) > -1)
return LineEnding.CR;
return LineEnding.CRLF;
}
public static string CleanLineEndings(string text, LineEnding lineEnding)
{
return Regex.Replace(text, "(\r\n|\r|\n)", LineEndingToString(lineEnding));
}
}
}

View File

@ -0,0 +1,35 @@
using Collections.Pooled;
namespace TextControlBoxNS.Text
{
internal class MoveLine
{
public static void Move(PooledList<string> totalLines, TextSelection selection, CursorPosition cursorposition, UndoRedo undoredo, string newLineCharacter, LineMoveDirection direction)
{
if (selection != null)
return;
//move down:
if (direction == LineMoveDirection.Down)
{
if (cursorposition.LineNumber >= totalLines.Count - 1)
return;
undoredo.RecordUndoAction(() =>
{
Selection.MoveLinesDown(totalLines, selection, cursorposition);
}, totalLines, cursorposition.LineNumber, 2, 2, newLineCharacter, cursorposition);
return;
}
//move up:
if (cursorposition.LineNumber <= 0)
return;
undoredo.RecordUndoAction(() =>
{
Selection.MoveLinesUp(totalLines, selection, cursorposition);
}, totalLines, cursorposition.LineNumber - 1, 2, 2, newLineCharacter, cursorposition);
}
}
}

View File

@ -0,0 +1,527 @@
using Collections.Pooled;
using System;
using System.Linq;
using System.Text;
using TextControlBoxNS.Extensions;
using TextControlBoxNS.Helper;
using TextControlBoxNS.Renderer;
namespace TextControlBoxNS.Text
{
internal class Selection
{
public static bool Equals(TextSelection sel1, TextSelection sel2)
{
if (sel1 == null || sel2 == null)
return false;
return Cursor.Equals(sel1.StartPosition, sel2.StartPosition) &&
Cursor.Equals(sel1.EndPosition, sel2.EndPosition);
}
//Order the selection that StartPosition is always smaller than EndPosition
public static TextSelection OrderTextSelection(TextSelection selection)
{
if (selection == null)
return selection;
int startLine = Math.Min(selection.StartPosition.LineNumber, selection.EndPosition.LineNumber);
int endLine = Math.Max(selection.StartPosition.LineNumber, selection.EndPosition.LineNumber);
int startPosition;
int endPosition;
if (startLine == endLine)
{
startPosition = Math.Min(selection.StartPosition.CharacterPosition, selection.EndPosition.CharacterPosition);
endPosition = Math.Max(selection.StartPosition.CharacterPosition, selection.EndPosition.CharacterPosition);
}
else
{
if (selection.StartPosition.LineNumber < selection.EndPosition.LineNumber)
{
endPosition = selection.EndPosition.CharacterPosition;
startPosition = selection.StartPosition.CharacterPosition;
}
else
{
endPosition = selection.StartPosition.CharacterPosition;
startPosition = selection.EndPosition.CharacterPosition;
}
}
return new TextSelection(selection.Index, selection.Length, new CursorPosition(startPosition, startLine), new CursorPosition(endPosition, endLine));
}
public static bool WholeTextSelected(TextSelection selection, PooledList<string> totalLines)
{
if (selection == null)
return false;
var sel = OrderTextSelection(selection);
return Utils.CursorPositionsAreEqual(sel.StartPosition, new CursorPosition(0, 0)) &&
Utils.CursorPositionsAreEqual(sel.EndPosition, new CursorPosition(totalLines.GetLineLength(-1), totalLines.Count - 1));
}
//returns whether the selection starts at character zero and ends
public static bool WholeLinesAreSelected(TextSelection selection, PooledList<string> totalLines)
{
if (selection == null)
return false;
var sel = OrderTextSelection(selection);
return Utils.CursorPositionsAreEqual(sel.StartPosition, new CursorPosition(0, sel.StartPosition.LineNumber)) &&
Utils.CursorPositionsAreEqual(sel.EndPosition, new CursorPosition(totalLines.GetLineText(sel.EndPosition.LineNumber).Length, sel.EndPosition.LineNumber));
}
public static CursorPosition GetMax(CursorPosition pos1, CursorPosition pos2)
{
if (pos1.LineNumber == pos2.LineNumber)
return pos1.CharacterPosition > pos2.CharacterPosition ? pos1 : pos2;
return pos1.LineNumber > pos2.LineNumber ? pos1 : pos2;
}
public static CursorPosition GetMin(CursorPosition pos1, CursorPosition pos2)
{
if (pos1.LineNumber == pos2.LineNumber)
return pos1.CharacterPosition > pos2.CharacterPosition ? pos2 : pos1;
return pos1.LineNumber > pos2.LineNumber ? pos2 : pos1;
}
public static CursorPosition GetMin(TextSelection selection)
{
return GetMin(selection.StartPosition, selection.EndPosition);
}
public static CursorPosition GetMax(TextSelection selection)
{
return GetMax(selection.StartPosition, selection.EndPosition);
}
public static CursorPosition InsertText(TextSelection selection, CursorPosition cursorPosition, PooledList<string> totalLines, string text, string newLineCharacter)
{
if (selection != null)
return Replace(selection, totalLines, text, newLineCharacter);
string curLine = totalLines.GetLineText(cursorPosition.LineNumber);
string[] lines = text.Split(newLineCharacter);
//Singleline
if (lines.Length == 1 && text != string.Empty)
{
text = text.Replace("\r", string.Empty).Replace("\n", string.Empty);
totalLines.SetLineText(-1, totalLines.GetLineText(-1).AddText(text, cursorPosition.CharacterPosition));
cursorPosition.AddToCharacterPos(text.Length);
return cursorPosition;
}
//Multiline:
int curPos = cursorPosition.CharacterPosition;
if (curPos > curLine.Length)
curPos = curLine.Length;
//GEt the text in front of the cursor
string textInFrontOfCursor = curLine.Substring(0, curPos < 0 ? 0 : curPos);
//Get the text behind the cursor
string textBehindCursor = curLine.SafeRemove(0, curPos < 0 ? 0 : curPos);
totalLines.DeleteAt(cursorPosition.LineNumber);
totalLines.InsertOrAddRange(ListHelper.CreateLines(lines, 0, textInFrontOfCursor, textBehindCursor), cursorPosition.LineNumber);
return new CursorPosition(cursorPosition.CharacterPosition + lines.Length > 0 ? lines[lines.Length - 1].Length : 0, cursorPosition.LineNumber + lines.Length - 1);
}
public static CursorPosition Replace(TextSelection selection, PooledList<string> totalLines, string text, string newLineCharacter)
{
//Just delete the text if the string is emty
if (text == "")
return Remove(selection, totalLines);
selection = OrderTextSelection(selection);
int startLine = selection.StartPosition.LineNumber;
int endLine = selection.EndPosition.LineNumber;
int startPosition = selection.StartPosition.CharacterPosition;
int endPosition = selection.EndPosition.CharacterPosition;
string[] lines = text.Split(newLineCharacter);
string start_Line = totalLines.GetLineText(startLine);
//Selection is singleline and text to paste is also singleline
if (startLine == endLine && lines.Length == 1)
{
start_Line =
(startPosition == 0 && endPosition == totalLines.GetLineLength(endLine)) ?
"" :
start_Line.SafeRemove(startPosition, endPosition - startPosition
);
totalLines.SetLineText(startLine, start_Line.AddText(text, startPosition));
return new CursorPosition(startPosition + text.Length, selection.StartPosition.LineNumber);
}
else if (startLine == endLine && lines.Length > 1 && (startPosition != 0 && endPosition != start_Line.Length))
{
string textTo = start_Line == "" ? "" : startPosition >= start_Line.Length ? start_Line : start_Line.Safe_Substring(0, startPosition);
string textFrom = start_Line == "" ? "" : endPosition >= start_Line.Length ? start_Line : start_Line.Safe_Substring(endPosition);
totalLines.SetLineText(startLine, (textTo + lines[0]));
totalLines.InsertOrAddRange(ListHelper.CreateLines(lines, 1, "", textFrom), startLine + 1);
return new CursorPosition(endPosition + text.Length, startLine + lines.Length - 1);
}
else if (WholeTextSelected(selection, totalLines))
{
if (lines.Length < totalLines.Count)
{
ListHelper.Clear(totalLines);
totalLines.InsertOrAddRange(lines, 0);
}
else
ReplaceLines(totalLines, 0, totalLines.Count, lines);
return new CursorPosition(totalLines.GetLineLength(-1), totalLines.Count - 1);
}
else
{
string end_Line = totalLines.GetLineText(endLine);
//All lines are selected from start to finish
if (startPosition == 0 && endPosition == end_Line.Length)
{
totalLines.Safe_RemoveRange(startLine, endLine - startLine + 1);
totalLines.InsertOrAddRange(lines, startLine);
}
//Only the startline is completely selected
else if (startPosition == 0 && endPosition != end_Line.Length)
{
totalLines.SetLineText(endLine, end_Line.Substring(endPosition).AddToStart(lines[lines.Length - 1]));
totalLines.Safe_RemoveRange(startLine, endLine - startLine);
totalLines.InsertOrAddRange(lines.Take(lines.Length - 1), startLine);
}
//Only the endline is completely selected
else if (startPosition != 0 && endPosition == end_Line.Length)
{
totalLines.SetLineText(startLine, start_Line.SafeRemove(startPosition).AddToEnd(lines[0]));
totalLines.Safe_RemoveRange(startLine + 1, endLine - startLine);
totalLines.InsertOrAddRange(lines.Skip(1), startLine + 1);
}
else
{
//Delete the selected parts
start_Line = start_Line.SafeRemove(startPosition);
end_Line = end_Line.Safe_Substring(endPosition);
//Only one line to insert
if (lines.Length == 1)
{
totalLines.SetLineText(startLine, start_Line.AddToEnd(lines[0] + end_Line));
totalLines.Safe_RemoveRange(startLine + 1, endLine - startLine < 0 ? 0 : endLine - startLine);
}
else
{
totalLines.SetLineText(startLine, start_Line.AddToEnd(lines[0]));
totalLines.SetLineText(endLine, end_Line.AddToStart(lines[lines.Length - 1]));
totalLines.Safe_RemoveRange(startLine + 1, endLine - startLine - 1 < 0 ? 0 : endLine - startLine - 1);
if (lines.Length > 2)
totalLines.InsertOrAddRange(lines.GetLines(1, lines.Length - 2), startLine + 1);
}
}
return new CursorPosition(start_Line.Length + end_Line.Length - 1, startLine + lines.Length - 1);
}
}
public static CursorPosition Remove(TextSelection selection, PooledList<string> totalLines)
{
selection = OrderTextSelection(selection);
int startLine = selection.StartPosition.LineNumber;
int endLine = selection.EndPosition.LineNumber;
int startPosition = selection.StartPosition.CharacterPosition;
int endPosition = selection.EndPosition.CharacterPosition;
string start_Line = totalLines.GetLineText(startLine);
string end_Line = totalLines.GetLineText(endLine);
if (startLine == endLine)
{
totalLines.SetLineText(startLine,
(startPosition == 0 && endPosition == end_Line.Length ?
"" :
start_Line.SafeRemove(startPosition, endPosition - startPosition))
);
}
else if (WholeTextSelected(selection, totalLines))
{
ListHelper.Clear(totalLines, true);
return new CursorPosition(0, totalLines.Count - 1);
}
else
{
//Whole lines are selected from start to finish
if (startPosition == 0 && endPosition == end_Line.Length)
{
totalLines.Safe_RemoveRange(startLine, endLine - startLine + 1);
}
//Only the startline is completely selected
else if (startPosition == 0 && endPosition != end_Line.Length)
{
totalLines.SetLineText(endLine, end_Line.Safe_Substring(endPosition));
totalLines.Safe_RemoveRange(startLine, endLine - startLine);
}
//Only the endline is completely selected
else if (startPosition != 0 && endPosition == end_Line.Length)
{
totalLines.SetLineText(startLine, start_Line.SafeRemove(startPosition));
totalLines.Safe_RemoveRange(startLine + 1, endLine - startLine);
}
//Both startline and endline are not completely selected
else
{
totalLines.SetLineText(startLine, start_Line.SafeRemove(startPosition) + end_Line.Safe_Substring(endPosition));
totalLines.Safe_RemoveRange(startLine + 1, endLine - startLine);
}
}
if (totalLines.Count == 0)
totalLines.AddLine();
return new CursorPosition(startPosition, startLine);
}
public static TextSelectionPosition GetIndexOfSelection(PooledList<string> totalLines, TextSelection selection)
{
var sel = OrderTextSelection(selection);
int startIndex = Cursor.CursorPositionToIndex(totalLines, sel.StartPosition);
int endIndex = Cursor.CursorPositionToIndex(totalLines, sel.EndPosition);
if (endIndex > startIndex)
return new TextSelectionPosition(Math.Min(startIndex, endIndex), endIndex - startIndex);
else
return new TextSelectionPosition(Math.Min(startIndex, endIndex), startIndex - endIndex);
}
public static TextSelection GetSelectionFromPosition(PooledList<string> totalLines, int startPosition, int length, int numberOfCharacters)
{
TextSelection returnValue = new TextSelection();
if (startPosition + length > numberOfCharacters)
{
if (startPosition > numberOfCharacters)
{
startPosition = numberOfCharacters;
length = 0;
}
else
length = numberOfCharacters - startPosition;
}
void GetIndexInLine(int currentIndex, int currentTotalLength)
{
int position = Math.Abs(currentTotalLength - startPosition);
returnValue.StartPosition =
new CursorPosition(position, currentIndex);
if (length == 0)
returnValue.EndPosition = new CursorPosition(returnValue.StartPosition);
else
{
int lengthCount = 0;
for (int i = currentIndex; i < totalLines.Count; i++)
{
int lineLength = totalLines[i].Length + 1;
if (lengthCount + lineLength > length)
{
returnValue.EndPosition = new CursorPosition(Math.Abs(lengthCount - length) + position, i);
break;
}
lengthCount += lineLength;
}
}
}
//Get the Length
int totalLength = 0;
for (int i = 0; i < totalLines.Count; i++)
{
int lineLength = totalLines[i].Length + 1;
if (totalLength + lineLength > startPosition)
{
GetIndexInLine(i, totalLength);
break;
}
totalLength += lineLength;
}
return returnValue;
}
public static string GetSelectedText(PooledList<string> totalLines, TextSelection textSelection, int currentLineIndex, string newLineCharacter)
{
//return the current line, if no text is selected:
if (textSelection == null)
return totalLines.GetLineText(currentLineIndex) + newLineCharacter;
int startLine = Math.Min(textSelection.StartPosition.LineNumber, textSelection.EndPosition.LineNumber);
int endLine = Math.Max(textSelection.StartPosition.LineNumber, textSelection.EndPosition.LineNumber);
int endIndex = Math.Max(textSelection.StartPosition.CharacterPosition, textSelection.EndPosition.CharacterPosition);
int startIndex = Math.Min(textSelection.StartPosition.CharacterPosition, textSelection.EndPosition.CharacterPosition);
StringBuilder stringBuilder = new StringBuilder();
if (startLine == endLine) //Singleline
{
string line = totalLines.GetLineText(startLine < totalLines.Count ? startLine : totalLines.Count - 1);
if (startIndex == 0 && endIndex != line.Length)
stringBuilder.Append(line.SafeRemove(endIndex));
else if (endIndex == line.Length && startIndex != 0)
stringBuilder.Append(line.Safe_Substring(startIndex));
else if (startIndex == 0 && endIndex == line.Length)
stringBuilder.Append(line);
else stringBuilder.Append(line.SafeRemove(endIndex).Substring(startIndex));
}
else if (WholeTextSelected(textSelection, totalLines))
{
stringBuilder.Append(ListHelper.GetLinesAsString(totalLines, newLineCharacter));
}
else //Multiline
{
//StartLine
stringBuilder.Append(totalLines.GetLineText(startLine).Substring(startIndex) + newLineCharacter);
//Other lines
if (endLine - startLine > 1)
stringBuilder.Append(totalLines.GetLines(startLine + 1, endLine - startLine - 1).GetString(newLineCharacter) + newLineCharacter);
//Endline
string currentLine = totalLines.GetLineText(endLine);
stringBuilder.Append(endIndex >= currentLine.Length ? currentLine : currentLine.SafeRemove(endIndex));
}
return stringBuilder.ToString();
}
/// <summary>
/// Replaces the lines in TotalLines, starting by Start replacing Count number of items, with the string in SplittedText
/// All lines that can be replaced get replaced all lines that are needed additionally get added
/// </summary>
/// <param name="totalLines"></param>
/// <param name="start"></param>
/// <param name="count"></param>
/// <param name="splittedText"></param>
public static void ReplaceLines(PooledList<string> totalLines, int start, int count, string[] splittedText)
{
if (splittedText.Length == 0)
{
totalLines.Safe_RemoveRange(start, count);
return;
}
//Same line-length -> check for any differences in the individual lines
if (count == splittedText.Length)
{
for (int i = 0; i < count; i++)
{
if (!totalLines.GetLineText(i).Equals(splittedText[i], StringComparison.Ordinal))
{
totalLines.SetLineText(start + i, splittedText[i]);
}
}
}
//Delete items from start to count; Insert splittedText at start
else if (count > splittedText.Length)
{
for (int i = 0; i < count; i++)
{
if (i < splittedText.Length)
{
totalLines.SetLineText(start + i, splittedText[i]);
}
else
{
totalLines.Safe_RemoveRange(start + i, count - i);
break;
}
}
}
//Replace all items from start - count with existing (add more if out of range)
else //SplittedText.Length > Count:
{
for (int i = 0; i < splittedText.Length; i++)
{
//replace all possible lines
if (i < count)
{
totalLines.SetLineText(start + i, splittedText[i]);
}
else //Add new lines
{
totalLines.InsertOrAddRange(splittedText.Skip(start + i), start + i);
break;
}
}
}
}
public static bool MoveLinesUp(PooledList<string> totalLines, TextSelection selection, CursorPosition cursorposition)
{
//Move single line
if (selection != null)
return false;
if (cursorposition.LineNumber > 0)
{
totalLines.SwapLines(cursorposition.LineNumber, cursorposition.LineNumber - 1);
cursorposition.LineNumber -= 1;
return true;
}
return false;
}
public static bool MoveLinesDown(PooledList<string> totalLines, TextSelection selection, CursorPosition cursorposition)
{
//Move single line
if (selection != null || selection.StartPosition.LineNumber != selection.EndPosition.LineNumber)
return false;
if (cursorposition.LineNumber < totalLines.Count)
{
totalLines.SwapLines(cursorposition.LineNumber, cursorposition.LineNumber + 1);
cursorposition.LineNumber += 1;
return true;
}
return false;
}
public static void ClearSelectionIfNeeded(TextControlBox textbox, SelectionRenderer selectionrenderer)
{
//If the selection is visible, but is not getting set, clear the selection
if (selectionrenderer.HasSelection && !selectionrenderer.IsSelecting)
{
textbox.ClearSelection();
}
}
public static bool SelectionIsNull(SelectionRenderer selectionrenderer, TextSelection selection)
{
if (selection == null)
return true;
return selectionrenderer.SelectionStartPosition == null || selectionrenderer.SelectionEndPosition == null;
}
public static void SelectSingleWord(CanvasHelper canvashelper, SelectionRenderer selectionrenderer, CursorPosition cursorPosition, string currentLine)
{
int characterpos = cursorPosition.CharacterPosition;
//Update variables
selectionrenderer.SelectionStartPosition =
new CursorPosition(characterpos - Cursor.CalculateStepsToMoveLeft2(currentLine, characterpos), cursorPosition.LineNumber);
selectionrenderer.SelectionEndPosition =
new CursorPosition(characterpos + Cursor.CalculateStepsToMoveRight2(currentLine, characterpos), cursorPosition.LineNumber);
cursorPosition.CharacterPosition = selectionrenderer.SelectionEndPosition.CharacterPosition;
selectionrenderer.HasSelection = true;
//Render it
canvashelper.UpdateSelection();
canvashelper.UpdateCursor();
}
}
}

View File

@ -0,0 +1,20 @@
using TextControlBoxNS.Helper;
namespace TextControlBoxNS.Text
{
internal class StringManager
{
private TabSpaceHelper tabSpaceHelper;
public LineEnding lineEnding;
public StringManager(TabSpaceHelper tabSpaceHelper)
{
this.tabSpaceHelper = tabSpaceHelper;
}
public string CleanUpString(string input)
{
//Fix tabs and lineendings
return tabSpaceHelper.UpdateTabs(LineEndings.CleanLineEndings(input, lineEnding));
}
}
}

View File

@ -0,0 +1,92 @@
using Collections.Pooled;
using TextControlBoxNS.Extensions;
namespace TextControlBoxNS.Text
{
internal class TabKey
{
public static TextSelection MoveTabBack(PooledList<string> totalLines, TextSelection textSelection, CursorPosition cursorPosition, string tabCharacter, string newLineCharacter, UndoRedo undoRedo)
{
if (textSelection == null)
{
string line = totalLines.GetLineText(cursorPosition.LineNumber);
if (line.Contains(tabCharacter, System.StringComparison.Ordinal) && cursorPosition.CharacterPosition > 0)
cursorPosition.SubtractFromCharacterPos(tabCharacter.Length);
undoRedo.RecordUndoAction(() =>
{
totalLines.SetLineText(cursorPosition.LineNumber, line.RemoveFirstOccurence(tabCharacter));
}, totalLines, cursorPosition.LineNumber, 1, 1, newLineCharacter);
return new TextSelection(cursorPosition, null);
}
textSelection = Selection.OrderTextSelection(textSelection);
int selectedLinesCount = textSelection.EndPosition.LineNumber - textSelection.StartPosition.LineNumber;
TextSelection tempSel = new TextSelection(textSelection);
tempSel.StartPosition.CharacterPosition = 0;
tempSel.EndPosition.CharacterPosition = totalLines.GetLineText(textSelection.EndPosition.LineNumber).Length + tabCharacter.Length;
undoRedo.RecordUndoAction(() =>
{
for (int i = 0; i < selectedLinesCount + 1; i++)
{
int lineIndex = i + textSelection.StartPosition.LineNumber;
string currentLine = totalLines.GetLineText(lineIndex);
if (i == 0 && currentLine.Contains(tabCharacter, System.StringComparison.Ordinal) && cursorPosition.CharacterPosition > 0)
textSelection.StartPosition.CharacterPosition -= tabCharacter.Length;
else if (i == selectedLinesCount && currentLine.Contains(tabCharacter, System.StringComparison.Ordinal))
{
textSelection.EndPosition.CharacterPosition -= tabCharacter.Length;
}
totalLines.SetLineText(lineIndex, currentLine.RemoveFirstOccurence(tabCharacter));
}
}, totalLines, tempSel, selectedLinesCount, newLineCharacter);
return new TextSelection(new CursorPosition(textSelection.StartPosition), new CursorPosition(textSelection.EndPosition));
}
public static TextSelection MoveTab(PooledList<string> totalLines, TextSelection textSelection, CursorPosition cursorPosition, string tabCharacter, string newLineCharacter, UndoRedo undoRedo)
{
if (textSelection == null)
{
string line = totalLines.GetLineText(cursorPosition.LineNumber);
undoRedo.RecordUndoAction(() =>
{
totalLines.SetLineText(cursorPosition.LineNumber, line.AddText(tabCharacter, cursorPosition.CharacterPosition));
}, totalLines, cursorPosition.LineNumber, 1, 1, newLineCharacter);
cursorPosition.AddToCharacterPos(tabCharacter.Length);
return new TextSelection(cursorPosition, null);
}
textSelection = Selection.OrderTextSelection(textSelection);
int selectedLinesCount = textSelection.EndPosition.LineNumber - textSelection.StartPosition.LineNumber;
if (textSelection.StartPosition.LineNumber == textSelection.EndPosition.LineNumber) //Singleline
textSelection.StartPosition = Selection.Replace(textSelection, totalLines, tabCharacter, newLineCharacter);
else
{
TextSelection tempSel = new TextSelection(textSelection);
tempSel.StartPosition.CharacterPosition = 0;
tempSel.EndPosition.CharacterPosition = totalLines.GetLineText(textSelection.EndPosition.LineNumber).Length + tabCharacter.Length;
textSelection.EndPosition.CharacterPosition += tabCharacter.Length;
textSelection.StartPosition.CharacterPosition += tabCharacter.Length;
undoRedo.RecordUndoAction(() =>
{
for (int i = textSelection.StartPosition.LineNumber; i < selectedLinesCount + textSelection.StartPosition.LineNumber + 1; i++)
{
totalLines.SetLineText(i, totalLines.GetLineText(i).AddToStart(tabCharacter));
}
}, totalLines, tempSel, selectedLinesCount + 1, newLineCharacter);
}
return new TextSelection(new CursorPosition(textSelection.StartPosition), new CursorPosition(textSelection.EndPosition));
}
}
}

View File

@ -0,0 +1,176 @@
using Collections.Pooled;
using System;
using System.Collections.Generic;
using TextControlBoxNS.Extensions;
using TextControlBoxNS.Helper;
using TextControlBoxNS.Models;
namespace TextControlBoxNS.Text
{
internal class UndoRedo
{
private Stack<UndoRedoItem> UndoStack = new Stack<UndoRedoItem>();
private Stack<UndoRedoItem> RedoStack = new Stack<UndoRedoItem>();
private bool HasRedone = false;
private void RecordRedo(UndoRedoItem item)
{
RedoStack.Push(item);
}
private void RecordUndo(UndoRedoItem item)
{
UndoStack.Push(item);
}
private void AddUndoItem(TextSelection selection, int startLine, string undoText, string redoText, int undoCount, int redoCount)
{
UndoStack.Push(new UndoRedoItem
{
RedoText = redoText,
UndoText = undoText,
Selection = selection,
StartLine = startLine,
UndoCount = undoCount,
RedoCount = redoCount,
});
}
private void RecordSingleLine(Action action, PooledList<string> totalLines, int startline)
{
var lineBefore = totalLines.GetLineText(startline);
action.Invoke();
var lineAfter = totalLines.GetLineText(startline);
AddUndoItem(null, startline, lineBefore, lineAfter, 1, 1);
}
public void RecordUndoAction(Action action, PooledList<string> totalLines, int startline, int undocount, int redoCount, string newLineCharacter, CursorPosition cursorposition = null)
{
if (undocount == redoCount && redoCount == 1)
{
RecordSingleLine(action, totalLines, startline);
return;
}
var linesBefore = totalLines.GetLines(startline, undocount).GetString(newLineCharacter);
action.Invoke();
var linesAfter = totalLines.GetLines(startline, redoCount).GetString(newLineCharacter);
AddUndoItem(cursorposition == null ? null : new TextSelection(new CursorPosition(cursorposition), null), startline, linesBefore, linesAfter, undocount, redoCount);
}
public void RecordUndoAction(Action action, PooledList<string> totalLines, TextSelection selection, int numberOfAddedLines, string newLineCharacter)
{
var orderedSel = Selection.OrderTextSelection(selection);
if (orderedSel.StartPosition.LineNumber == orderedSel.EndPosition.LineNumber && orderedSel.StartPosition.LineNumber == 1)
{
RecordSingleLine(action, totalLines, orderedSel.StartPosition.LineNumber);
return;
}
int numberOfRemovedLines = orderedSel.EndPosition.LineNumber - orderedSel.StartPosition.LineNumber + 1;
if (numberOfAddedLines == 0 && !Selection.WholeLinesAreSelected(selection, totalLines) ||
orderedSel.StartPosition.LineNumber == orderedSel.EndPosition.LineNumber && orderedSel.Length == totalLines.GetLineLength(orderedSel.StartPosition.LineNumber))
numberOfAddedLines += 1;
var linesBefore = totalLines.GetLines(orderedSel.StartPosition.LineNumber, numberOfRemovedLines).GetString(newLineCharacter);
action.Invoke();
var linesAfter = totalLines.GetLines(orderedSel.StartPosition.LineNumber, numberOfAddedLines).GetString(newLineCharacter);
AddUndoItem(
selection,
orderedSel.StartPosition.LineNumber,
linesBefore,
linesAfter,
numberOfRemovedLines,
numberOfAddedLines
);
}
public TextSelection Undo(PooledList<string> totalLines, StringManager stringManager, string newLineCharacter)
{
if (UndoStack.Count < 1)
return null;
if (HasRedone)
{
HasRedone = false;
while (RedoStack.Count > 0)
{
var redoItem = RedoStack.Pop();
redoItem.UndoText = redoItem.RedoText = null;
}
}
UndoRedoItem item = UndoStack.Pop();
RecordRedo(item);
//Faster for singleline
if (item.UndoCount == 1 && item.RedoCount == 1)
{
totalLines.SetLineText(item.StartLine, stringManager.CleanUpString(item.UndoText));
}
else
{
totalLines.Safe_RemoveRange(item.StartLine, item.RedoCount);
if (item.UndoCount > 0)
totalLines.InsertOrAddRange(ListHelper.GetLinesFromString(stringManager.CleanUpString(item.UndoText), newLineCharacter), item.StartLine);
}
return item.Selection;
}
public TextSelection Redo(PooledList<string> totalLines, StringManager stringmanager, string newLineCharacter)
{
if (RedoStack.Count < 1)
return null;
UndoRedoItem item = RedoStack.Pop();
RecordUndo(item);
HasRedone = true;
//Faster for singleline
if (item.UndoCount == 1 && item.RedoCount == 1)
{
totalLines.SetLineText(item.StartLine, stringmanager.CleanUpString(item.RedoText));
}
else
{
totalLines.Safe_RemoveRange(item.StartLine, item.UndoCount);
if (item.RedoCount > 0)
totalLines.InsertOrAddRange(ListHelper.GetLinesFromString(stringmanager.CleanUpString(item.RedoText), newLineCharacter), item.StartLine);
}
return null;
}
/// <summary>
/// Clears all the items in the undo and redo stack
/// </summary>
public void ClearAll()
{
UndoStack.Clear();
RedoStack.Clear();
UndoStack.TrimExcess();
RedoStack.TrimExcess();
GC.Collect(GC.GetGeneration(UndoStack), GCCollectionMode.Optimized);
GC.Collect(GC.GetGeneration(RedoStack), GCCollectionMode.Optimized);
}
public void NullAll()
{
UndoStack = null;
RedoStack = null;
}
/// <summary>
/// Gets if the undo stack contains actions
/// </summary>
public bool CanUndo { get => UndoStack.Count > 0; }
/// <summary>
/// Gets if the redo stack contains actions
/// </summary>
public bool CanRedo { get => RedoStack.Count > 0; }
}
}

View File

@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>TextControlBoxNS</RootNamespace>
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<UseWinUI>true</UseWinUI>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<DocumentationFile></DocumentationFile>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<PackageId>TextControlBox.WinUI.JuliusKirsch</PackageId>
<Title>TextControlBox WinUI</Title>
<Version>1.0.0</Version>
<Authors>Julius Kirsch</Authors>
<Product>TextControlBox WinUI</Product>
<Description>A textbox for WinUI3 with syntax highlighting, line numbering, and support for a large amount of text</Description>
<Copyright>Julius Kirsch</Copyright>
<PackageProjectUrl>https://github.com/FrozenAssassine/TextControlBox-WinUI</PackageProjectUrl>
<RepositoryUrl>https://github.com/FrozenAssassine/TextControlBox-WinUI</RepositoryUrl>
<PackageTags>TextControlBox; Textbox; WinUI; C#; SyntaxHighlighting; LineNumbers</PackageTags>
<PackageReleaseNotes>Migrated from UWP to WinUI.</PackageReleaseNotes>
<PackageIcon>Icon1.png</PackageIcon>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Collections.Pooled" Version="1.0.82" />
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.0.5.1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.2.221109.1" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.755" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,117 @@
<UserControl
x:Class="TextControlBoxNS.TextControlBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helper="using:TextControlBoxNS.Helper"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xaml="using:Microsoft.Graphics.Canvas.UI.Xaml"
d:DesignHeight="300"
d:DesignWidth="400"
AllowDrop="True"
AllowFocusOnInteraction="false"
DragOver="UserControl_DragOver"
Drop="UserControl_Drop"
GotFocus="UserControl_GotFocus"
IsTabStop="True"
LosingFocus="UserControl_LosingFocus"
LostFocus="UserControl_LostFocus"
PointerEntered="UserControl_PointerEntered"
PointerExited="UserControl_PointerExited"
PointerWheelChanged="Canvas_Selection_PointerWheelChanged"
TabIndex="0"
Tapped="UserControl_Tapped"
mc:Ignorable="d">
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<xaml:CanvasControl
x:Name="Canvas_LineNumber"
Grid.Column="0"
Width="100"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
Draw="Canvas_LineNumber_Draw"
PointerEntered="Canvas_LineNumber_PointerEntered"
PointerExited="Canvas_LineNumber_PointerExited"
PointerPressed="Canvas_LineNumber_PointerPressed"
PointerReleased="Canvas_Selection_PointerReleased"
PointerWheelChanged="Canvas_Selection_PointerWheelChanged" />
<Grid x:Name="Scroll" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<xaml:CanvasControl
x:Name="Canvas_Cursor"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Draw="Canvas_Cursor_Draw" />
<xaml:CanvasControl
x:Name="Canvas_Text"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Draw="Canvas_Text_Draw" />
<xaml:CanvasControl
x:Name="Canvas_Selection"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Draw="Canvas_Selection_Draw"
PointerMoved="Canvas_Selection_PointerMoved"
PointerPressed="Canvas_Selection_PointerPressed"
PointerReleased="Canvas_Selection_PointerReleased" />
<ScrollBar
x:Name="VerticalScrollbar"
Grid.Column="2"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Background="Transparent"
IndicatorMode="MouseIndicator"
LargeChange="100"
Loaded="VerticalScrollbar_Loaded"
Maximum="0"
Minimum="0"
Orientation="Vertical"
PointerEntered="Scrollbar_PointerEntered"
PointerExited="Scrollbar_PointerExited"
Scroll="VerticalScrollbar_Scroll"
SmallChange="10"
Value="0" />
<ScrollBar
x:Name="HorizontalScrollbar"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Background="Transparent"
IndicatorMode="MouseIndicator"
LargeChange="100"
Maximum="0"
Minimum="0"
Orientation="Horizontal"
PointerEntered="Scrollbar_PointerEntered"
PointerExited="Scrollbar_PointerExited"
Scroll="HorizontalScrollbar_Scroll"
SmallChange="10"
Value="0" />
</Grid>
<helper:InputHandlerControl
x:Name="inputHandler"
Grid.Column="1"
Width="0"
Height="0"
GotFocus="UserControl_GotFocus"
LostFocus="UserControl_LostFocus"
Opacity="0"
PreviewKeyDown="InputHandler_KeyDown"
TextChanged="InputHandler_TextChanged" />
</Grid>
</UserControl>

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
true

View File

@ -1,336 +0,0 @@
#include "pch.h"
#include "CodeEditorControl.h"
#if __has_include("CodeEditorControl.g.cpp")
#include "CodeEditorControl.g.cpp"
#endif
#include "Helpers.h"
using namespace ::WinUIEditor;
using namespace winrt;
using namespace Windows::UI::Core;
using namespace Windows::Foundation;
using namespace Windows::System;
using namespace DUD;
using namespace DUX;
using namespace DUX::Controls;
using namespace DUX::Input;
using namespace winrt;
namespace winrt::WinUIEditor::implementation
{
CodeEditorControl::CodeEditorControl()
{
DefaultStyleKey(winrt::box_value(L"WinUIEditor.CodeEditorControl"));
_editor = make_self<EditorBaseControl>();
_call = _editor->Call();
SetScintilla(_call);
SetLexilla(CreateLexer);
Initialize();
_editor->DpiChanged({ this, &CodeEditorControl::Editor_DpiChanged });
_editor->InternalNotifyMessageReceived.add({ this, &CodeEditorControl::Editor_NotifyMessageReceived });
Loaded({ this, &CodeEditorControl::OnLoaded });
Unloaded({ this, &CodeEditorControl::OnUnloaded });
GettingFocus({ this, &CodeEditorControl::OnGettingFocus });
#ifndef WINUI3
if (_hasFcu)
{
#endif
_dispatcherQueue = DUD::DispatcherQueue::GetForCurrentThread();
#ifndef WINUI3
}
#endif
}
static constexpr CodeEditorTheme XamlToCodeEditorTheme(ElementTheme theme)
{
return static_cast<CodeEditorTheme>(theme);
}
static constexpr ElementTheme CodeEditorToXamlTheme(CodeEditorTheme theme)
{
return static_cast<ElementTheme>(theme);
}
void CodeEditorControl::OnApplyTemplate()
{
__super::OnApplyTemplate();
#ifndef WINUI3
if (_hasFcu)
{
#endif
UpdateColors(XamlToCodeEditorTheme(ActualTheme()));
#ifndef WINUI3
}
else
{
UpdateColors(XamlToCodeEditorTheme(LegacyActualTheme()));
}
#endif
if (const auto presenter{ GetTemplateChild(L"EditorContainer").try_as<ContentPresenter>() })
{
presenter.Content(_editor.as<WinUIEditor::EditorBaseControl>());
}
}
void CodeEditorControl::OnKeyDown(KeyRoutedEventArgs const &e)
{
__super::OnKeyDown(e);
const auto modifiers{ GetKeyModifiersForCurrentThread() }; // Todo: Can we avoid calling this every time?
if ((modifiers & VirtualKeyModifiers::Control) == VirtualKeyModifiers::Control)
{
switch (e.Key())
{
case VirtualKey::F2: // Todo: make customizable
{
if (_call->Focus())
{
ChangeAllOccurrences();
e.Handled(true);
}
}
break;
}
}
}
void CodeEditorControl::OnLoaded(IInspectable const &sender, DUX::RoutedEventArgs const &args)
{
#ifndef WINUI3
_isLoaded = true;
#endif
if (!IsLoadedCompat())
{
return;
}
#ifndef WINUI3
if (_hasFcu)
{
#endif
UpdateColors(XamlToCodeEditorTheme(ActualTheme()));
_actualThemeChangedRevoker = ActualThemeChanged(auto_revoke, { this, &CodeEditorControl::OnActualThemeChanged });
#ifndef WINUI3
}
else
{
UpdateColors(XamlToCodeEditorTheme(LegacyActualTheme()));
// Todo: Add fallback for ActualThemeChanged
}
#endif
}
void CodeEditorControl::OnUnloaded(IInspectable const &sender, DUX::RoutedEventArgs const &args)
{
#ifndef WINUI3
_isLoaded = false;
#endif
if (IsLoadedCompat())
{
return;
}
#ifndef WINUI3
if (_hasFcu)
{
#endif
_actualThemeChangedRevoker.revoke();
#ifndef WINUI3
}
else
{
// Todo: Add fallback
}
#endif
}
bool CodeEditorControl::IsLoadedCompat()
{
#ifndef WINUI3
if (_hasIsLoaded)
{
#endif
return IsLoaded();
#ifndef WINUI3
}
else
{
return _isLoaded;
}
#endif
}
void CodeEditorControl::OnGettingFocus(IInspectable const &sender, GettingFocusEventArgs const &e)
{
if (e.NewFocusedElement() == *this && (
#ifndef WINUI3
!_has1803 ||
#endif
!e.TrySetNewFocusedElement(*_editor)))
{
const auto focusState{ e.FocusState() };
#ifndef WINUI3
if (_hasFcu)
{
#endif
_dispatcherQueue.TryEnqueue([this, focusState]()
{
_editor->Focus(focusState);
});
#ifndef WINUI3
}
else
{
Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [this, focusState]()
{
_editor->Focus(focusState);
});
}
#endif
e.Handled(true);
}
}
int64_t CodeEditorControl::SendMessage(ScintillaMessage const &message, uint64_t wParam, int64_t lParam)
{
return _editor->PublicWndProc(static_cast<Scintilla::Message>(message), wParam, lParam);
}
WinUIEditor::Editor CodeEditorControl::Editor()
{
return _editor->Editor();
}
void CodeEditorControl::OnActualThemeChanged(IInspectable const &sender, IInspectable const &e)
{
UpdateColors(XamlToCodeEditorTheme(ActualTheme()));
}
void CodeEditorControl::Editor_DpiChanged(IInspectable const &sender, double value)
{
UpdateDpi(value);
}
void CodeEditorControl::Editor_NotifyMessageReceived(IInspectable const &sender, int64_t value)
{
ProcessNotification(reinterpret_cast<Scintilla::NotificationData *>(value));
}
hstring CodeEditorControl::HighlightingLanguage()
{
return hstring{ CodeEditorHandler::HighlightingLanguage() };
}
void CodeEditorControl::HighlightingLanguage(hstring const &value)
{
CodeEditorHandler::HighlightingLanguage(value);
}
event_token CodeEditorControl::DefaultColorsChanged(EventHandler<ElementTheme> const &handler)
{
return _defaultColorsChangedEvent.add(handler);
}
void CodeEditorControl::DefaultColorsChanged(event_token const &token) noexcept
{
_defaultColorsChangedEvent.remove(token);
}
event_token CodeEditorControl::SyntaxHighlightingApplied(EventHandler<ElementTheme> const &handler)
{
return _syntaxHighlightingAppliedEvent.add(handler);
}
void CodeEditorControl::SyntaxHighlightingApplied(event_token const &token) noexcept
{
_syntaxHighlightingAppliedEvent.remove(token);
}
void CodeEditorControl::ApplyDefaultsToDocument()
{
ChangeDocumentDefaults();
UpdateZoom();
}
void CodeEditorControl::ResetLexer()
{
SetLexer();
}
#ifndef WINUI3
DUX::ElementTheme CodeEditorControl::LegacyActualTheme()
{
// Todo: Fully implement
const auto requestedTheme{ RequestedTheme() };
if (requestedTheme == ElementTheme::Default)
{
return Application::Current().RequestedTheme() == ApplicationTheme::Dark
? ElementTheme::Dark
: ElementTheme::Light;
}
else
{
return requestedTheme;
}
}
#endif
void CodeEditorControl::StyleSetFore(int style, Scintilla::ColourAlpha color)
{
_editor->StyleSetForeTransparent(style, Scintilla::Internal::ColourRGBA{ color });
}
void CodeEditorControl::StyleSetBack(int style, Scintilla::ColourAlpha color)
{
_editor->StyleSetBackTransparent(style, Scintilla::Internal::ColourRGBA{ color });
}
void CodeEditorControl::InvalidateStyleRedraw()
{
_editor->InvalidateStyleRedraw();
}
void CodeEditorControl::StyleClearCustom()
{
_editor->StyleClearCustom();
}
void CodeEditorControl::SetFoldMarginColor(bool useSetting, Scintilla::ColourAlpha back)
{
_editor->SetFoldMarginColorTransparent(useSetting, Scintilla::Internal::ColourRGBA{ back });
}
void CodeEditorControl::SetFoldMarginHiColor(bool useSetting, Scintilla::ColourAlpha fore)
{
_editor->SetFoldMarginHiColorTransparent(useSetting, Scintilla::Internal::ColourRGBA{ fore });
}
void CodeEditorControl::DefaultColorsChanged(CodeEditorTheme theme)
{
_defaultColorsChangedEvent(*this, CodeEditorToXamlTheme(theme));
}
void CodeEditorControl::SyntaxHighlightingApplied(CodeEditorTheme theme)
{
_syntaxHighlightingAppliedEvent(*this, CodeEditorToXamlTheme(theme));
}
event_token CodeEditorControl::NotifyMessageReceived(EventHandler<int64_t> const &handler)
{
return _editor->NotifyMessageReceived(handler);
}
void CodeEditorControl::NotifyMessageReceived(event_token const &token) noexcept
{
_editor->NotifyMessageReceived(token);
}
}

View File

@ -1,75 +0,0 @@
#pragma once
#include "CodeEditorControl.g.h"
#include "CodeEditorHandler.h"
#include "EditorBaseControl.h"
namespace winrt::WinUIEditor::implementation
{
struct CodeEditorControl : CodeEditorControlT<CodeEditorControl>, ::WinUIEditor::CodeEditorHandler
{
CodeEditorControl();
int64_t SendMessage(ScintillaMessage const &message, uint64_t wParam, int64_t lParam);
WinUIEditor::Editor Editor();
void OnApplyTemplate();
void OnKeyDown(DUX::Input::KeyRoutedEventArgs const &e);
hstring HighlightingLanguage();
void HighlightingLanguage(hstring const &value);
event_token NotifyMessageReceived(Windows::Foundation::EventHandler<int64_t> const &handler);
void NotifyMessageReceived(event_token const &token) noexcept;
event_token DefaultColorsChanged(Windows::Foundation::EventHandler<DUX::ElementTheme> const &handler);
void DefaultColorsChanged(event_token const &token) noexcept;
event_token SyntaxHighlightingApplied(Windows::Foundation::EventHandler<DUX::ElementTheme> const &handler);
void SyntaxHighlightingApplied(event_token const &token) noexcept;
void ApplyDefaultsToDocument();
void ResetLexer();
private:
com_ptr<EditorBaseControl> _editor{ nullptr };
std::shared_ptr<Scintilla::ScintillaCall> _call{ nullptr };
event<Windows::Foundation::EventHandler<int64_t>> _notifyMessageReceived;
event<Windows::Foundation::EventHandler<DUX::ElementTheme>> _defaultColorsChangedEvent;
event<Windows::Foundation::EventHandler<DUX::ElementTheme>> _syntaxHighlightingAppliedEvent;
DUD::DispatcherQueue _dispatcherQueue{ nullptr };
#ifndef WINUI3
bool _hasFcu{ Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 5) }; // Todo: Make static
bool _has1803{ Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 6) }; // Todo: Make static
bool _hasIsLoaded{ Windows::Foundation::Metadata::ApiInformation::IsPropertyPresent(L"Windows.UI.Xaml.FrameworkElement", L"IsLoaded") }; // Todo: Make static
bool _isLoaded{ false };
#endif
void OnLoaded(Windows::Foundation::IInspectable const &sender, DUX::RoutedEventArgs const &args);
void OnUnloaded(Windows::Foundation::IInspectable const &sender, DUX::RoutedEventArgs const &args);
bool IsLoadedCompat();
void OnGettingFocus(Windows::Foundation::IInspectable const &sender, DUX::Input::GettingFocusEventArgs const &e);
DUX::FrameworkElement::ActualThemeChanged_revoker _actualThemeChangedRevoker{};
void OnActualThemeChanged(Windows::Foundation::IInspectable const &sender, Windows::Foundation::IInspectable const &e);
void Editor_DpiChanged(Windows::Foundation::IInspectable const &sender, double value);
void Editor_NotifyMessageReceived(Windows::Foundation::IInspectable const &sender, int64_t value);
#ifndef WINUI3
DUX::ElementTheme LegacyActualTheme();
#endif
void StyleSetFore(int style, Scintilla::ColourAlpha color) override;
void StyleSetBack(int style, Scintilla::ColourAlpha color) override;
void InvalidateStyleRedraw() override;
void StyleClearCustom() override;
void SetFoldMarginColor(bool useSetting, Scintilla::ColourAlpha back) override;
void SetFoldMarginHiColor(bool useSetting, Scintilla::ColourAlpha fore) override;
void DefaultColorsChanged(::WinUIEditor::CodeEditorTheme theme) override;
void SyntaxHighlightingApplied(::WinUIEditor::CodeEditorTheme theme) override;
};
}
namespace winrt::WinUIEditor::factory_implementation
{
struct CodeEditorControl : CodeEditorControlT<CodeEditorControl, implementation::CodeEditorControl>
{
};
}

View File

@ -1,19 +0,0 @@
#include "Defines.idl"
import "EditorWrapper.idl";
import "IEditorAccess.idl";
namespace WinUIEditor
{
[default_interface]
[webhosthidden]
runtimeclass CodeEditorControl : DUX.Controls.Control, IEditorAccess
{
CodeEditorControl();
Editor Editor { get; };
String HighlightingLanguage { get; set; };
event Windows.Foundation.EventHandler<DUX.ElementTheme> DefaultColorsChanged;
event Windows.Foundation.EventHandler<DUX.ElementTheme> SyntaxHighlightingApplied;
void ApplyDefaultsToDocument();
void ResetLexer();
}
}

View File

@ -1,669 +0,0 @@
// This file includes code derived from SciTEBase.cxx and StyleWriter.cxx
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// The scintilla\License.txt file describes the conditions under which this software may be distributed.
// Notable changes:
// Modifications to StyleAndWords:
// - Added constructor that is not string-based
// - Changed functions (IsSingleChar, IsCharacter, Includes) to support multiple characters for indent blocks
// Modifications to TextReader
// - Removed InternalIsLeadByte
// - Removed IsLeadByte (header)
#include "CodeEditorHandler.h"
#include <stdexcept>
#include "SciLexer.h"
using namespace WinUIEditor::Internal;
using namespace Scintilla;
namespace WinUIEditor
{
static constexpr bool IsBrace(char ch) noexcept
{
return ch == '[' || ch == ']' || ch == '(' || ch == ')' || ch == '{' || ch == '}';
}
static constexpr bool IsAlphabetic(int ch) noexcept
{
return ((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z'));
}
static int IntegerFromString(const std::string &val, int defaultValue)
{
try
{
if (val.length())
{
return std::stoi(val);
}
}
catch (std::logic_error &)
{
// Ignore bad values, either non-numeric or out of range numeric
}
return defaultValue;
}
static std::set<std::string> SetFromString(std::string_view text, char separator)
{
std::set<std::string> result;
while (!text.empty())
{
const size_t after = text.find_first_of(separator);
const std::string_view symbol(text.substr(0, after));
if (!symbol.empty())
{
result.emplace(symbol);
}
if (after == std::string_view::npos)
{
break;
}
text.remove_prefix(after + 1);
}
return result;
}
StyleAndWords::StyleAndWords() noexcept
{
};
// Set of words separated by spaces. First is style number, rest are symbols.
// <styleNumber> [symbol]*
StyleAndWords::StyleAndWords(const std::string &definition)
{
styleNumber = IntegerFromString(definition, 0);
std::string_view symbols(definition);
// Remove initial style number
const size_t endNumber = symbols.find_first_of(' ');
if (endNumber == std::string::npos)
{
return;
}
symbols.remove_prefix(endNumber + 1);
words = SetFromString(symbols, ' ');
}
StyleAndWords::StyleAndWords(int style, const std::set<std::string> &words)
{
styleNumber = style;
this->words = words;
}
bool StyleAndWords::IsEmpty() const noexcept
{
return words.empty();
}
// WinUI modified
bool StyleAndWords::IsSingleChar() const noexcept
{
//if (words.size() != 1)
if (words.size() == 0)
{
return false;
}
const std::string &first = *words.begin();
return first.length() == 1;
}
// WinUI modified
bool StyleAndWords::IsCharacter(char ch) const noexcept
{
//if (words.size() != 1)
if (words.size() == 0)
{
return false;
}
for (std::string word : words)
{
if (word.size() == 1 && ch == word[0])
{
return true;
}
}
return false;
//const std::string &first = *words.begin();
//return (first.length() == 1) && (ch == first[0]);
}
int StyleAndWords::Style() const noexcept
{
return styleNumber;
}
// WinUI modified
bool StyleAndWords::Includes(const std::string &value) const
{
if (words.empty())
{
return false;
}
const std::string &first = *words.begin();
if (first.empty())
{
return false;
}
if (IsAlphabetic(first[0]))
{
return words.count(value) != 0;
}
// Set of individual characters. Only one character allowed for now
//const char ch = first[0];
//return value.find(ch) != std::string::npos;
for (std::string ch : words)
{
if (ch.size() == 1 && value.find(ch[0]) != std::string::npos)
{
return true;
}
}
return false;
}
TextReader::TextReader(ScintillaCall &sc_) noexcept :
startPos(extremePosition),
endPos(0),
codePage(0),
sc(sc_),
lenDoc(-1)
{
buf[0] = 0;
}
void TextReader::Fill(Position position)
{
if (lenDoc == -1)
lenDoc = sc.Length();
startPos = position - slopSize;
if (startPos + bufferSize > lenDoc)
startPos = lenDoc - bufferSize;
if (startPos < 0)
startPos = 0;
endPos = startPos + bufferSize;
if (endPos > lenDoc)
endPos = lenDoc;
sc.SetTarget(Span(startPos, endPos));
sc.TargetText(buf);
}
bool TextReader::Match(Position pos, const char *s)
{
for (int i = 0; *s; i++)
{
if (*s != SafeGetCharAt(pos + i))
return false;
s++;
}
return true;
}
int TextReader::StyleAt(Position position)
{
return sc.UnsignedStyleAt(position);
}
Line TextReader::GetLine(Position position)
{
return sc.LineFromPosition(position);
}
Position TextReader::LineStart(Line line)
{
return sc.LineStart(line);
}
FoldLevel TextReader::LevelAt(Line line)
{
return sc.FoldLevel(line);
}
Position TextReader::Length()
{
if (lenDoc == -1)
lenDoc = sc.Length();
return lenDoc;
}
int TextReader::GetLineState(Line line)
{
return sc.LineState(line);
}
/**
* Find if there is a brace next to the caret, checking before caret first, then
* after caret. If brace found also find its matching brace.
* @return @c true if inside a bracket pair.
*/
bool CodeEditorHandler::SciFindMatchingBracePosition(Position &braceAtCaret, Position &braceOpposite, bool sloppy)
{
// Config
const auto bracesStyle{ 0 };
const int lexLanguage{ _call->Lexer() };
bool isInside = false;
const int mainSel = _call->MainSelection();
if (_call->SelectionNCaretVirtualSpace(mainSel) > 0)
return false;
const int bracesStyleCheck = bracesStyle;
Position caretPos = _call->CurrentPos();
braceAtCaret = -1;
braceOpposite = -1;
char charBefore = '\0';
int styleBefore = 0;
const Position lengthDoc = _call->Length();
TextReader acc(*_call);
if ((lengthDoc > 0) && (caretPos > 0))
{
// Check to ensure not matching brace that is part of a multibyte character
if (_call->PositionBefore(caretPos) == (caretPos - 1))
{
charBefore = acc[caretPos - 1];
styleBefore = acc.StyleAt(caretPos - 1);
}
}
// Priority goes to character before caret
if (charBefore && IsBrace(charBefore) &&
((styleBefore == bracesStyleCheck) || (!bracesStyle)))
{
braceAtCaret = caretPos - 1;
}
bool colonMode = false;
if ((lexLanguage == SCLEX_PYTHON) &&
(':' == charBefore) && (SCE_P_OPERATOR == styleBefore))
{
braceAtCaret = caretPos - 1;
colonMode = true;
}
bool isAfter = true;
if (lengthDoc > 0 && sloppy && (braceAtCaret < 0) && (caretPos < lengthDoc))
{
// No brace found so check other side
// Check to ensure not matching brace that is part of a multibyte character
if (_call->PositionAfter(caretPos) == (caretPos + 1))
{
const char charAfter = acc[caretPos];
const int styleAfter = acc.StyleAt(caretPos);
if (charAfter && IsBrace(charAfter) && ((styleAfter == bracesStyleCheck) || (!bracesStyle)))
{
braceAtCaret = caretPos;
isAfter = false;
}
if ((lexLanguage == SCLEX_PYTHON) &&
(':' == charAfter) && (SCE_P_OPERATOR == styleAfter))
{
braceAtCaret = caretPos;
colonMode = true;
}
}
}
if (braceAtCaret >= 0)
{
if (colonMode)
{
const Line lineStart = _call->LineFromPosition(braceAtCaret);
const Line lineMaxSubord = _call->LastChild(lineStart, static_cast<FoldLevel>(-1));
braceOpposite = _call->LineEnd(lineMaxSubord);
}
else
{
braceOpposite = _call->BraceMatch(braceAtCaret, 0);
}
if (braceOpposite > braceAtCaret)
{
isInside = isAfter;
}
else
{
isInside = !isAfter;
}
}
return isInside;
}
void CodeEditorHandler::SciBraceMatch()
{
// Config
const auto bracesCheck{ true };
const auto bracesSloppy{ true };
if (!bracesCheck)
return;
Position braceAtCaret = -1;
Position braceOpposite = -1;
SciFindMatchingBracePosition(braceAtCaret, braceOpposite, bracesSloppy);
if ((braceAtCaret != -1) && (braceOpposite == -1))
{
//_call->BraceBadLight(braceAtCaret);
_call->BraceBadLight(-1);
_call->SetHighlightGuide(0);
}
else
{
char chBrace = 0;
if (braceAtCaret >= 0)
chBrace = _call->CharacterAt(braceAtCaret);
_call->BraceHighlight(braceAtCaret, braceOpposite);
Position columnAtCaret = _call->Column(braceAtCaret);
Position columnOpposite = _call->Column(braceOpposite);
if (chBrace == ':')
{
const Line lineStart = _call->LineFromPosition(braceAtCaret);
const Position indentPos = _call->LineIndentPosition(lineStart);
const Position indentPosNext = _call->LineIndentPosition(lineStart + 1);
columnAtCaret = _call->Column(indentPos);
const Position columnAtCaretNext = _call->Column(indentPosNext);
const int indentSize = _call->Indent();
if (columnAtCaretNext - indentSize > 1)
columnAtCaret = columnAtCaretNext - indentSize;
if (columnOpposite == 0) // If the final line of the structure is empty
columnOpposite = columnAtCaret;
}
else
{
if (_call->LineFromPosition(braceAtCaret) == _call->LineFromPosition(braceOpposite))
{
// Avoid attempting to draw a highlight guide
columnAtCaret = 0;
columnOpposite = 0;
}
}
// Todo: has rendering issues
//if (props.GetInt("highlight.indentation.guides"))
//_call->SetHighlightGuide(std::min(columnAtCaret, columnOpposite));
}
}
Line CodeEditorHandler::SciGetCurrentLineNumber()
{
return _call->LineFromPosition(
_call->CurrentPos());
}
int CodeEditorHandler::SciGetLineIndentation(Line line)
{
return _call->LineIndentation(line);
}
Position CodeEditorHandler::SciGetLineIndentPosition(Line line)
{
return _call->LineIndentPosition(line);
}
std::vector<std::string> CodeEditorHandler::SciGetLinePartsInStyle(Line line, const StyleAndWords &saw)
{
std::vector<std::string> sv;
TextReader acc(*_call);
std::string s;
const bool separateCharacters = saw.IsSingleChar();
const Position thisLineStart = _call->LineStart(line);
const Position nextLineStart = _call->LineStart(line + 1);
for (Position pos = thisLineStart; pos < nextLineStart; pos++)
{
if (acc.StyleAt(pos) == saw.Style())
{
if (separateCharacters)
{
// Add one character at a time, even if there is an adjacent character in the same style
if (s.length() > 0)
{
sv.push_back(s);
}
s = "";
}
s += acc[pos];
}
else if (s.length() > 0)
{
sv.push_back(s);
s = "";
}
}
if (s.length() > 0)
{
sv.push_back(s);
}
return sv;
}
IndentationStatus CodeEditorHandler::SciGetIndentState(Line line)
{
// C like language indentation defined by braces and keywords
IndentationStatus indentState = IndentationStatus::none;
const std::vector<std::string> controlIndents = SciGetLinePartsInStyle(line, _sciStatementIndent);
for (const std::string &sIndent : controlIndents)
{
if (_sciStatementIndent.Includes(sIndent))
indentState = IndentationStatus::keyWordStart;
}
const std::vector<std::string> controlEnds = SciGetLinePartsInStyle(line, _sciStatementEnd);
for (const std::string &sEnd : controlEnds)
{
if (_sciStatementEnd.Includes(sEnd))
indentState = IndentationStatus::none;
}
// Braces override keywords
const std::vector<std::string> controlBlocks = SciGetLinePartsInStyle(line, _sciBlockEnd);
for (const std::string &sBlock : controlBlocks)
{
if (_sciBlockEnd.Includes(sBlock))
indentState = IndentationStatus::blockEnd;
if (_sciBlockStart.Includes(sBlock))
indentState = IndentationStatus::blockStart;
}
return indentState;
}
int CodeEditorHandler::SciIndentOfBlock(Line line)
{
if (line < 0)
return 0;
const int indentSize = _call->Indent();
int indentBlock = SciGetLineIndentation(line);
Line backLine = line;
IndentationStatus indentState = IndentationStatus::none;
if (_sciStatementIndent.IsEmpty() && _sciBlockStart.IsEmpty() && _sciBlockEnd.IsEmpty())
indentState = IndentationStatus::blockStart; // Don't bother searching backwards
Line lineLimit = line - _sciStatementLookback;
if (lineLimit < 0)
lineLimit = 0;
while ((backLine >= lineLimit) && (indentState == IndentationStatus::none))
{
indentState = SciGetIndentState(backLine);
if (indentState != IndentationStatus::none)
{
indentBlock = SciGetLineIndentation(backLine);
if (indentState == IndentationStatus::blockStart)
{
if (!_sciIndentOpening)
indentBlock += indentSize;
}
if (indentState == IndentationStatus::blockEnd)
{
if (_sciIndentClosing)
indentBlock -= indentSize;
if (indentBlock < 0)
indentBlock = 0;
}
if ((indentState == IndentationStatus::keyWordStart) && (backLine == line))
indentBlock += indentSize;
}
backLine--;
}
return indentBlock;
}
Span CodeEditorHandler::SciGetSelection()
{
return _call->SelectionSpan();
}
void CodeEditorHandler::SciSetSelection(Position anchor, Position currentPos)
{
_call->SetSel(anchor, currentPos);
}
void CodeEditorHandler::SciSetLineIndentation(Line line, int indent)
{
if (indent < 0)
return;
const Span rangeStart = SciGetSelection();
Span range = rangeStart;
const Position posBefore = SciGetLineIndentPosition(line);
_call->SetLineIndentation(line, indent);
const Position posAfter = SciGetLineIndentPosition(line);
const Position posDifference = posAfter - posBefore;
if (posAfter > posBefore)
{
// Move selection on
if (range.start >= posBefore)
{
range.start += posDifference;
}
if (range.end >= posBefore)
{
range.end += posDifference;
}
}
else if (posAfter < posBefore)
{
// Move selection back
if (range.start >= posAfter)
{
if (range.start >= posBefore)
range.start += posDifference;
else
range.start = posAfter;
}
if (range.end >= posAfter)
{
if (range.end >= posBefore)
range.end += posDifference;
else
range.end = posAfter;
}
}
if (!(rangeStart == range))
{
SciSetSelection(range.start, range.end);
}
}
bool CodeEditorHandler::SciRangeIsAllWhitespace(Position start, Position end)
{
TextReader acc(*_call);
for (Position i = start; i < end; i++)
{
if ((acc[i] != ' ') && (acc[i] != '\t'))
return false;
}
return true;
}
void CodeEditorHandler::SciAutomaticIndentation(char ch)
{
const Span range = _call->SelectionSpan();
const Position selStart = range.start;
const Line curLine = SciGetCurrentLineNumber();
const Position thisLineStart = _call->LineStart(curLine);
const int indentSize = _call->Indent();
int indentBlock = SciIndentOfBlock(curLine - 1);
if ((_call->Lexer() == SCLEX_PYTHON) &&
/*(props.GetInt("indent.python.colon") == 1)*/ true)
{
const EndOfLine eolMode = _call->EOLMode();
const int eolChar = (eolMode == EndOfLine::Cr ? '\r' : '\n');
const int eolChars = (eolMode == EndOfLine::CrLf ? 2 : 1);
const Position prevLineStart = _call->LineStart(curLine - 1);
const Position prevIndentPos = SciGetLineIndentPosition(curLine - 1);
const int indentExisting = SciGetLineIndentation(curLine);
if (ch == eolChar)
{
// Find last noncomment, nonwhitespace character on previous line
char character = '\0';
int style = 0;
for (Position p = selStart - eolChars - 1; p > prevLineStart; p--)
{
style = _call->UnsignedStyleAt(p);
if (style != SCE_P_DEFAULT && style != SCE_P_COMMENTLINE &&
style != SCE_P_COMMENTBLOCK)
{
character = _call->CharacterAt(p);
break;
}
}
indentBlock = SciGetLineIndentation(curLine - 1);
if (style == SCE_P_OPERATOR && character == ':')
{
SciSetLineIndentation(curLine, indentBlock + indentSize);
}
else if (selStart == prevIndentPos + eolChars)
{
// Preserve the indentation of preexisting text beyond the caret
SciSetLineIndentation(curLine, indentBlock + indentExisting);
}
else
{
SciSetLineIndentation(curLine, indentBlock);
}
}
return;
}
if (_sciBlockEnd.IsCharacter(ch))
{ // Dedent maybe
if (!_sciIndentClosing)
{
if (SciRangeIsAllWhitespace(thisLineStart, selStart - 1))
{
SciSetLineIndentation(curLine, indentBlock - indentSize);
}
}
}
else if (!_sciBlockEnd.IsSingleChar() && (ch == ' '))
{ // Dedent maybe
if (!_sciIndentClosing && (SciGetIndentState(curLine) == IndentationStatus::blockEnd)) {}
}
else if (_sciBlockStart.IsCharacter(ch))
{
// Dedent maybe if first on line and previous line was starting keyword
if (!_sciIndentOpening && (SciGetIndentState(curLine - 1) == IndentationStatus::keyWordStart))
{
if (SciRangeIsAllWhitespace(thisLineStart, selStart - 1))
{
SciSetLineIndentation(curLine, indentBlock - indentSize);
}
}
}
else if ((ch == '\r' || ch == '\n') && (selStart == thisLineStart))
{
if (!_sciIndentClosing && !_sciBlockEnd.IsSingleChar())
{ // Dedent previous line maybe
const std::vector<std::string> controlWords = SciGetLinePartsInStyle(curLine - 1, _sciBlockEnd);
if (!controlWords.empty())
{
if (_sciBlockEnd.Includes(controlWords[0]))
{
// Check if first keyword on line is an ender
SciSetLineIndentation(curLine - 1, SciIndentOfBlock(curLine - 2) - indentSize);
// Recalculate as may have changed previous line
indentBlock = SciIndentOfBlock(curLine - 1);
}
}
}
SciSetLineIndentation(curLine, indentBlock);
}
}
}

View File

@ -1,91 +0,0 @@
// This file includes code derived from SciTEBase.h and StyleWriter.h
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// The scintilla\License.txt file describes the conditions under which this software may be distributed.
#pragma once
namespace WinUIEditor::Internal
{
enum class IndentationStatus
{
none, // no effect on indentation
blockStart, // indentation block begin such as "{" or VB "function"
blockEnd, // indentation end indicator such as "}" or VB "end"
keyWordStart, // Keywords that cause indentation
};
class StyleAndWords
{
int styleNumber = 0;
std::set<std::string> words;
public:
StyleAndWords() noexcept;
explicit StyleAndWords(const std::string &definition);
StyleAndWords(int style, const std::set<std::string> &words);
[[nodiscard]] bool IsEmpty() const noexcept;
[[nodiscard]] bool IsSingleChar() const noexcept;
[[nodiscard]] bool IsCharacter(char ch) const noexcept;
[[nodiscard]] int Style() const noexcept;
[[nodiscard]] bool Includes(const std::string &value) const;
};
// Read only access to a document, its styles and other data
class TextReader
{
protected:
static constexpr Scintilla::Position extremePosition = INTPTR_MAX;
/** @a bufferSize is a trade off between time taken to copy the characters
* and retrieval overhead.
* @a slopSize positions the buffer before the desired position
* in case there is some backtracking. */
static constexpr Scintilla::Position bufferSize = 4000;
static constexpr Scintilla::Position slopSize = bufferSize / 8;
char buf[bufferSize + 1];
Scintilla::Position startPos;
Scintilla::Position endPos;
int codePage;
Scintilla::ScintillaCall &sc;
Scintilla::Position lenDoc;
void Fill(Scintilla::Position position);
public:
explicit TextReader(Scintilla::ScintillaCall &sc_) noexcept;
// Deleted so TextReader objects can not be copied.
TextReader(const TextReader &source) = delete;
TextReader &operator=(const TextReader &) = delete;
char operator[](Scintilla::Position position)
{
if (position < startPos || position >= endPos)
{
Fill(position);
}
return buf[position - startPos];
}
/** Safe version of operator[], returning a defined value for invalid position. */
char SafeGetCharAt(Scintilla::Position position, char chDefault = ' ')
{
if (position < startPos || position >= endPos)
{
Fill(position);
if (position < startPos || position >= endPos)
{
// Position is outside range of document
return chDefault;
}
}
return buf[position - startPos];
}
void SetCodePage(int codePage_) noexcept
{
codePage = codePage_;
}
bool Match(Scintilla::Position pos, const char *s);
int StyleAt(Scintilla::Position position);
Scintilla::Line GetLine(Scintilla::Position position);
Scintilla::Position LineStart(Scintilla::Line line);
Scintilla::FoldLevel LevelAt(Scintilla::Line line);
Scintilla::Position Length();
int GetLineState(Scintilla::Line line);
};
}

View File

@ -1,395 +0,0 @@
#include "CodeEditorHandler.h"
#include "SciLexer.h"
#include "TextMateScope.h"
#include "DarkPlus.h"
#include "LightPlus.h"
using namespace Scintilla;
namespace WinUIEditor
{
static constexpr auto WINUI_SCE_HJ_KEYWORD2{ 53 };
void CodeEditorHandler::SetLexer()
{
if (_highlightingLanguage == L"cpp")
{
const auto lexer{ _createLexer("cpp") };
lexer->PropertySet("fold", "1");
_call->SetILexer(lexer);
// This list of keywords from SciTe (cpp.properties)
_call->SetKeyWords(0,
"alignas alignof and and_eq asm audit auto axiom bitand bitor bool "
"char char8_t char16_t char32_t class compl concept "
"const consteval constexpr const_cast "
"decltype default delete double dynamic_cast enum explicit export extern false final float "
"friend import inline int long module mutable namespace new noexcept not not_eq nullptr "
"operator or or_eq override private protected public "
"register reinterpret_cast requires "
"short signed sizeof static static_assert static_cast struct "
"template this thread_local true typedef typeid typename union unsigned using "
"virtual void volatile wchar_t xor xor_eq");
_call->SetKeyWords(1,
"break case catch co_await co_return co_yield continue do else for goto if return switch throw try while");
_call->SetKeyWords(2,
"a addindex addtogroup anchor arg attention"
"author b brief bug c class code date def defgroup deprecated dontinclude"
"e em endcode endhtmlonly endif endlatexonly endlink endverbatim enum example exception"
"f$ f[ f] file fn hideinitializer htmlinclude htmlonly"
"if image include ingroup internal invariant interface latexonly li line link"
"mainpage name namespace nosubgrouping note overload"
"p page par param param[in] param[out]"
"post pre ref relates remarks return retval"
"sa section see showinitializer since skip skipline struct subsection"
"test throw throws todo typedef union until"
"var verbatim verbinclude version warning weakgroup $ @ \\ & < > # { }");
SetLanguageIndentMode(
SCE_C_WORD2, { "case", "default", "do", "else", "for", "if", "while", },
SCE_C_OPERATOR, { ";", },
SCE_C_OPERATOR, { "{", },
SCE_C_OPERATOR, { "}", });
}
else if (_highlightingLanguage == L"csharp")
{
const auto lexer{ _createLexer("cpp") };
lexer->PropertySet("fold", "1");
_call->SetILexer(lexer);
// This list of keywords from SciTe (cpp.properties) and https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
_call->SetKeyWords(0,
"abstract as ascending async await base bool by byte char checked "
"class const decimal default delegate descending double enum "
"equals event explicit extern false fixed float from get group "
"implicit in int interface internal into is join lock let long nameof namespace new nint null "
"object on operator orderby out override params partial private protected public "
"readonly ref sbyte sealed select set short sizeof stackalloc static "
"string struct this true typeof uint ulong"
"unchecked unsafe ushort var virtual void volatile where");
_call->SetKeyWords(1,
"break case catch continue do else finally for foreach goto if return switch throw try using while yield");
// XML document comments from https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/documentation-comments#d31-general
_call->SetKeyWords(2,
"c code example exception include list para param paramref permission remarks returns see seealso summary typeparam typeparamref value");
SetLanguageIndentMode(
SCE_C_WORD2, { "case", "default", "do", "else", "for", "foreach", "if", "using", "while", },
SCE_C_OPERATOR, { ";", },
SCE_C_OPERATOR, { "{", },
SCE_C_OPERATOR, { "}", });
}
else if (_highlightingLanguage == L"javascript")
{
const auto lexer{ _createLexer("cpp") };
lexer->PropertySet("fold", "1");
_call->SetILexer(lexer);
SetJavaScriptDefaults(0, 1, SCE_C_WORD2, SCE_C_OPERATOR);
}
else if (_highlightingLanguage == L"json")
{
const auto lexer{ _createLexer("json") };
lexer->PropertySet("fold", "1");
lexer->PropertySet("lexer.json.allow.comments", "1");
lexer->PropertySet("lexer.json.escape.sequence", "1");
_call->SetILexer(lexer);
// This list of keywords from SciTe (json.properties)
_call->SetKeyWords(0, "false true null");
_call->SetKeyWords(1,
"@id @context @type @value @language @container @list @set @reverse @index @base @vocab @graph");
SetLanguageIndentMode(
0, { },
0, { },
SCE_JSON_OPERATOR, { "{", "[", },
SCE_JSON_OPERATOR, { "}", "]", });
}
else if (_highlightingLanguage == L"xml" || _highlightingLanguage == L"html")
{
const auto lexer{ _createLexer(_highlightingLanguage == L"xml" ? "xml" : "hypertext") };
lexer->PropertySet("fold", "1");
lexer->PropertySet("fold.html", "1");
lexer->PropertySet("winuiedit.style.tag.brackets.as.tag.end", "1");
_call->SetILexer(lexer);
if (_highlightingLanguage == L"html")
{
_call->SetKeyWords(5, "ELEMENT DOCTYPE doctype ATTLIST ENTITY NOTATION");
SetJavaScriptDefaults(1, 6, WINUI_SCE_HJ_KEYWORD2, SCE_HJ_SYMBOLS);
}
else
{
SetLanguageIndentMode(0, { }, 0, { }, 0, { }, 0, { });
}
}
else if (_highlightingLanguage == L"plaintext")
{
_call->SetILexer(_createLexer("null"));
SetLanguageIndentMode(0, { }, 0, { }, 0, { }, 0, { });
}
else
{
_call->SetILexer(nullptr);
SetLanguageIndentMode(0, { }, 0, { }, 0, { }, 0, { });
}
if (_highlightingLanguage == L"cpp" || _highlightingLanguage == L"csharp" || _highlightingLanguage == L"javascript")
{
_call->SetKeyWords(5, "todo toDo Todo ToDo TODO fixme fixMe Fixme FixMe FIXME");
}
}
void CodeEditorHandler::SetJavaScriptDefaults(int wordList1, int wordList2, int indentKeywordStyle, int symbolStyle)
{
// This list of keywords from MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#keywords
// Note additional words like undefined
_call->SetKeyWords(wordList1,
"class const debugger delete export extends false function in instanceof "
"new null super this true typeof var void let static enum implements "
"interface private protected public arguments async get of set Infinity NaN undefined");
_call->SetKeyWords(wordList2,
"break case catch continue default do else finally for if import return "
"switch throw try while with yield await package as from");
SetLanguageIndentMode(
indentKeywordStyle, { "case", "default", "do", "else", "for", "if", "while", },
symbolStyle, { ";", },
symbolStyle, { "{", "[" },
symbolStyle, { "}", "]" });
}
void CodeEditorHandler::UpdateLanguageStyles()
{
if (_highlightingLanguage == L"cpp" || _highlightingLanguage == L"csharp" || _highlightingLanguage == L"javascript")
{
switch (_theme)
{
case CodeEditorTheme::Dark:
StyleSetFore(static_cast<int>(StylesCommon::Default), DarkPlusEditorForeground);
StyleClearCustom();
StyleSetFore(static_cast<int>(StylesCommon::BraceLight), DarkPlusEditorForeground);
StyleSetFore(SCE_C_COMMENT, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_C_COMMENTLINE, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_C_COMMENTDOC, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_C_NUMBER, DarkPlus2(Scope::ConstantNumeric));
StyleSetFore(SCE_C_WORD, DarkPlus2(Scope::Keyword));
StyleSetFore(SCE_C_STRING, DarkPlus2(Scope::String));
StyleSetFore(SCE_C_CHARACTER, DarkPlus2(Scope::String));
StyleSetFore(SCE_C_UUID, DarkPlus2(Scope::ConstantNumeric));
StyleSetFore(SCE_C_PREPROCESSOR, DarkPlus2(Scope::MetaPreprocessor));
StyleSetFore(SCE_C_OPERATOR, DarkPlus2(Scope::KeywordOperator));
if (_highlightingLanguage != L"cpp")
{
StyleSetFore(SCE_C_IDENTIFIER, DarkPlus2(Scope::Variable));
}
StyleSetFore(SCE_C_STRINGEOL, DarkPlus2(Scope::String));
StyleSetFore(SCE_C_VERBATIM, DarkPlus2(Scope::String));
StyleSetFore(SCE_C_REGEX, DarkPlus2(Scope::StringRegexp));
StyleSetFore(SCE_C_COMMENTLINEDOC, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_C_WORD2, DarkPlus2(Scope::KeywordControl));
StyleSetFore(SCE_C_COMMENTDOCKEYWORD, DarkPlus2(Scope::Keyword));
StyleSetFore(SCE_C_COMMENTDOCKEYWORDERROR, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_C_GLOBALCLASS, DarkPlus2(Scope::EntityNameType));
StyleSetFore(SCE_C_STRINGRAW, DarkPlus2(Scope::String));
StyleSetFore(SCE_C_TRIPLEVERBATIM, DarkPlus2(Scope::String));
StyleSetFore(SCE_C_HASHQUOTEDSTRING, DarkPlus2(Scope::String));
StyleSetFore(SCE_C_PREPROCESSORCOMMENT, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_C_PREPROCESSORCOMMENTDOC, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_C_USERLITERAL, DarkPlus2(Scope::KeywordOtherUnit));
StyleSetFore(SCE_C_TASKMARKER, DarkPlus2(Scope::Comment));
_call->StyleSetItalic(SCE_C_TASKMARKER, true);
_call->StyleSetBold(SCE_C_TASKMARKER, true);
StyleSetFore(SCE_C_ESCAPESEQUENCE, DarkPlus2(Scope::ConstantCharacterEscape));
break;
case CodeEditorTheme::Light:
StyleSetFore(static_cast<int>(StylesCommon::Default), LightPlusEditorForeground);
StyleClearCustom();
StyleSetFore(static_cast<int>(StylesCommon::BraceLight), LightPlusEditorForeground);
StyleSetFore(SCE_C_COMMENT, LightPlus2(Scope::Comment));
StyleSetFore(SCE_C_COMMENTLINE, LightPlus2(Scope::Comment));
StyleSetFore(SCE_C_COMMENTDOC, LightPlus2(Scope::Comment));
StyleSetFore(SCE_C_NUMBER, LightPlus2(Scope::ConstantNumeric));
StyleSetFore(SCE_C_WORD, LightPlus2(Scope::Keyword));
StyleSetFore(SCE_C_STRING, LightPlus2(Scope::String));
StyleSetFore(SCE_C_CHARACTER, LightPlus2(Scope::String));
StyleSetFore(SCE_C_UUID, LightPlus2(Scope::ConstantNumeric));
StyleSetFore(SCE_C_PREPROCESSOR, LightPlus2(Scope::MetaPreprocessor));
StyleSetFore(SCE_C_OPERATOR, LightPlus2(Scope::KeywordOperator));
if (_highlightingLanguage != L"cpp")
{
StyleSetFore(SCE_C_IDENTIFIER, LightPlus2(Scope::Variable));
}
StyleSetFore(SCE_C_STRINGEOL, LightPlus2(Scope::String));
StyleSetFore(SCE_C_VERBATIM, LightPlus2(Scope::String));
StyleSetFore(SCE_C_REGEX, LightPlus2(Scope::StringRegexp));
StyleSetFore(SCE_C_COMMENTLINEDOC, LightPlus2(Scope::Comment));
StyleSetFore(SCE_C_WORD2, LightPlus2(Scope::KeywordControl));
StyleSetFore(SCE_C_COMMENTDOCKEYWORD, LightPlus2(Scope::Keyword));
StyleSetFore(SCE_C_COMMENTDOCKEYWORDERROR, LightPlus2(Scope::Comment));
StyleSetFore(SCE_C_GLOBALCLASS, LightPlus2(Scope::EntityNameType));
StyleSetFore(SCE_C_STRINGRAW, LightPlus2(Scope::String));
StyleSetFore(SCE_C_TRIPLEVERBATIM, LightPlus2(Scope::String));
StyleSetFore(SCE_C_HASHQUOTEDSTRING, LightPlus2(Scope::String));
StyleSetFore(SCE_C_PREPROCESSORCOMMENT, LightPlus2(Scope::Comment));
StyleSetFore(SCE_C_PREPROCESSORCOMMENTDOC, LightPlus2(Scope::Comment));
StyleSetFore(SCE_C_USERLITERAL, LightPlus2(Scope::KeywordOtherUnit));
StyleSetFore(SCE_C_TASKMARKER, LightPlus2(Scope::Comment));
_call->StyleSetItalic(SCE_C_TASKMARKER, true);
_call->StyleSetBold(SCE_C_TASKMARKER, true);
StyleSetFore(SCE_C_ESCAPESEQUENCE, LightPlus2(Scope::ConstantCharacterEscape));
break;
}
}
else if (_highlightingLanguage == L"json")
{
switch (_theme)
{
case CodeEditorTheme::Dark:
StyleSetFore(static_cast<int>(StylesCommon::Default), DarkPlusEditorForeground);
StyleClearCustom();
StyleSetFore(static_cast<int>(StylesCommon::BraceLight), DarkPlusEditorForeground);
StyleSetFore(SCE_JSON_NUMBER, DarkPlus2(Scope::ConstantNumeric));
StyleSetFore(SCE_JSON_STRING, DarkPlus2(Scope::String));
StyleSetFore(SCE_JSON_STRINGEOL, DarkPlus2(Scope::String));
StyleSetFore(SCE_JSON_PROPERTYNAME, DarkPlus2(Scope::SupportTypeProperty_NameJson));
StyleSetFore(SCE_JSON_ESCAPESEQUENCE, DarkPlus2(Scope::ConstantCharacterEscape));
StyleSetFore(SCE_JSON_LINECOMMENT, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_JSON_BLOCKCOMMENT, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_JSON_OPERATOR, DarkPlus2(Scope::KeywordOperator));
StyleSetFore(SCE_JSON_URI, DarkPlus2(Scope::String));
_call->StyleSetUnderline(SCE_JSON_URI, true);
StyleSetFore(SCE_JSON_COMPACTIRI, DarkPlus2(Scope::String));
StyleSetFore(SCE_JSON_KEYWORD, DarkPlus2(Scope::ConstantLanguage));
StyleSetFore(SCE_JSON_LDKEYWORD, DarkPlus2(Scope::KeywordControl));
StyleSetFore(SCE_JSON_ERROR, DarkPlus2(Scope::Invalid));
break;
case CodeEditorTheme::Light:
StyleSetFore(static_cast<int>(StylesCommon::Default), LightPlusEditorForeground);
StyleClearCustom();
StyleSetFore(static_cast<int>(StylesCommon::BraceLight), LightPlusEditorForeground);
StyleSetFore(SCE_JSON_NUMBER, LightPlus2(Scope::ConstantNumeric));
StyleSetFore(SCE_JSON_STRING, LightPlus2(Scope::String));
StyleSetFore(SCE_JSON_STRINGEOL, LightPlus2(Scope::String));
StyleSetFore(SCE_JSON_PROPERTYNAME, LightPlus2(Scope::SupportTypeProperty_NameJson));
StyleSetFore(SCE_JSON_ESCAPESEQUENCE, LightPlus2(Scope::ConstantCharacterEscape));
StyleSetFore(SCE_JSON_LINECOMMENT, LightPlus2(Scope::Comment));
StyleSetFore(SCE_JSON_BLOCKCOMMENT, LightPlus2(Scope::Comment));
StyleSetFore(SCE_JSON_OPERATOR, LightPlus2(Scope::KeywordOperator));
StyleSetFore(SCE_JSON_URI, LightPlus2(Scope::String));
_call->StyleSetUnderline(SCE_JSON_URI, true);
StyleSetFore(SCE_JSON_COMPACTIRI, LightPlus2(Scope::String));
StyleSetFore(SCE_JSON_KEYWORD, LightPlus2(Scope::ConstantLanguage));
StyleSetFore(SCE_JSON_LDKEYWORD, LightPlus2(Scope::KeywordControl));
StyleSetFore(SCE_JSON_ERROR, LightPlus2(Scope::Invalid));
break;
}
}
else if (_highlightingLanguage == L"xml" || _highlightingLanguage == L"html")
{
const auto isHtml{ _highlightingLanguage == L"html" };
switch (_theme)
{
case CodeEditorTheme::Dark:
StyleSetFore(static_cast<int>(StylesCommon::Default), DarkPlusEditorForeground);
StyleClearCustom();
StyleSetFore(static_cast<int>(StylesCommon::BraceLight), DarkPlusEditorForeground);
StyleSetFore(SCE_H_TAG, DarkPlus2(Scope::EntityNameTag));
StyleSetFore(SCE_H_TAGUNKNOWN, DarkPlus2(Scope::EntityNameTag));
StyleSetFore(SCE_H_ATTRIBUTE, DarkPlus2(Scope::EntityOtherAttribute_Name));
StyleSetFore(SCE_H_ATTRIBUTEUNKNOWN, DarkPlus2(Scope::EntityOtherAttribute_Name));
StyleSetFore(SCE_H_NUMBER, DarkPlus2(Scope::ConstantNumeric));
StyleSetFore(SCE_H_DOUBLESTRING, DarkPlus2(Scope::String));
StyleSetFore(SCE_H_SINGLESTRING, DarkPlus2(Scope::String));
// ...
StyleSetFore(SCE_H_COMMENT, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_H_ENTITY, DarkPlus2(Scope::ConstantCharacter));
StyleSetFore(SCE_H_TAGEND, DarkPlus2(Scope::PunctuationDefinitionTag));
StyleSetFore(SCE_H_XMLSTART, DarkPlus2(Scope::PunctuationDefinitionTag));
StyleSetFore(SCE_H_XMLEND, DarkPlus2(Scope::PunctuationDefinitionTag));
// ...
StyleSetFore(SCE_H_CDATA, DarkPlus2(Scope::String));
StyleSetFore(SCE_H_SGML_DEFAULT, DarkPlus2(Scope::PunctuationDefinitionTag));
StyleSetFore(SCE_H_SGML_COMMAND, DarkPlus2(Scope::EntityNameTag));
StyleSetFore(SCE_H_SGML_1ST_PARAM, DarkPlus2(Scope::EntityOtherAttribute_Name));
StyleSetFore(SCE_H_SGML_DOUBLESTRING, DarkPlus2(Scope::String));
// ...
StyleSetFore(SCE_H_SGML_COMMENT, DarkPlus2(Scope::Comment));
// ...
if (isHtml)
{
StyleSetFore(SCE_H_VALUE, DarkPlus2(Scope::String));
StyleSetFore(SCE_HJ_COMMENT, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_HJ_COMMENTLINE, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_HJ_COMMENTDOC, DarkPlus2(Scope::Comment));
StyleSetFore(SCE_HJ_NUMBER, DarkPlus2(Scope::ConstantNumeric));
StyleSetFore(SCE_HJ_WORD, DarkPlus2(Scope::Variable));
StyleSetFore(SCE_HJ_KEYWORD, DarkPlus2(Scope::Keyword));
StyleSetFore(WINUI_SCE_HJ_KEYWORD2, DarkPlus2(Scope::KeywordControl));
StyleSetFore(SCE_HJ_DOUBLESTRING, DarkPlus2(Scope::String));
StyleSetFore(SCE_HJ_SINGLESTRING, DarkPlus2(Scope::String));
StyleSetFore(SCE_HJ_SYMBOLS, DarkPlus2(Scope::KeywordOperator));
StyleSetFore(SCE_HJ_STRINGEOL, DarkPlus2(Scope::String));
StyleSetFore(SCE_HJ_REGEX, DarkPlus2(Scope::StringRegexp));
}
break;
case CodeEditorTheme::Light:
StyleSetFore(static_cast<int>(StylesCommon::Default), LightPlusEditorForeground);
StyleClearCustom();
StyleSetFore(static_cast<int>(StylesCommon::BraceLight), LightPlusEditorForeground);
StyleSetFore(SCE_H_TAG, LightPlus2(Scope::EntityNameTag));
StyleSetFore(SCE_H_TAGUNKNOWN, LightPlus2(Scope::EntityNameTag));
StyleSetFore(SCE_H_ATTRIBUTE, LightPlus2(Scope::EntityOtherAttribute_Name));
StyleSetFore(SCE_H_ATTRIBUTEUNKNOWN, LightPlus2(Scope::EntityOtherAttribute_Name));
StyleSetFore(SCE_H_NUMBER, LightPlus2(Scope::ConstantNumeric));
StyleSetFore(SCE_H_DOUBLESTRING, isHtml ? LightPlus2(Scope::StringQuotedDoubleHtml) : LightPlus2(Scope::StringQuotedDoubleXml));
StyleSetFore(SCE_H_SINGLESTRING, isHtml ? LightPlus2(Scope::StringQuotedSingleHtml) : LightPlus2(Scope::StringQuotedSingleXml));
// ...
StyleSetFore(SCE_H_COMMENT, LightPlus2(Scope::Comment));
StyleSetFore(SCE_H_ENTITY, LightPlus2(Scope::ConstantCharacter));
StyleSetFore(SCE_H_TAGEND, LightPlus2(Scope::PunctuationDefinitionTag));
StyleSetFore(SCE_H_XMLSTART, LightPlus2(Scope::PunctuationDefinitionTag));
StyleSetFore(SCE_H_XMLEND, LightPlus2(Scope::PunctuationDefinitionTag));
// ...
StyleSetFore(SCE_H_CDATA, isHtml ? LightPlus2(Scope::String) : LightPlus2(Scope::StringUnquotedCdataXml));
StyleSetFore(SCE_H_SGML_DEFAULT, LightPlus2(Scope::PunctuationDefinitionTag));
StyleSetFore(SCE_H_SGML_COMMAND, LightPlus2(Scope::EntityNameTag));
StyleSetFore(SCE_H_SGML_1ST_PARAM, LightPlus2(Scope::EntityOtherAttribute_Name));
StyleSetFore(SCE_H_SGML_DOUBLESTRING, LightPlus2(Scope::StringQuotedDoubleHtml));
// ...
StyleSetFore(SCE_H_SGML_COMMENT, LightPlus2(Scope::Comment));
// ...
if (isHtml)
{
StyleSetFore(SCE_H_VALUE, LightPlus2(Scope::StringUnquotedHtml));
StyleSetFore(SCE_HJ_COMMENT, LightPlus2(Scope::Comment));
StyleSetFore(SCE_HJ_COMMENTLINE, LightPlus2(Scope::Comment));
StyleSetFore(SCE_HJ_COMMENTDOC, LightPlus2(Scope::Comment));
StyleSetFore(SCE_HJ_NUMBER, LightPlus2(Scope::ConstantNumeric));
StyleSetFore(SCE_HJ_WORD, LightPlus2(Scope::Variable));
StyleSetFore(SCE_HJ_KEYWORD, LightPlus2(Scope::Keyword));
StyleSetFore(WINUI_SCE_HJ_KEYWORD2, LightPlus2(Scope::KeywordControl));
StyleSetFore(SCE_HJ_DOUBLESTRING, LightPlus2(Scope::String));
StyleSetFore(SCE_HJ_SINGLESTRING, LightPlus2(Scope::String));
StyleSetFore(SCE_HJ_SYMBOLS, LightPlus2(Scope::KeywordOperator));
StyleSetFore(SCE_HJ_STRINGEOL, LightPlus2(Scope::String));
StyleSetFore(SCE_HJ_REGEX, LightPlus2(Scope::StringRegexp));
}
break;
}
}
else
{
StyleClearCustom();
}
}
}

View File

@ -1,557 +0,0 @@
#include "CodeEditorHandler.h"
#include <cmath>
#include "ScintillaMessages.h"
using namespace Scintilla;
namespace WinUIEditor
{
void CodeEditorHandler::SetScintilla(std::shared_ptr<ScintillaCall> call)
{
_call = call;
}
void CodeEditorHandler::SetLexilla(Lexilla::CreateLexerFn createLexer)
{
_createLexer = createLexer;
}
void CodeEditorHandler::Initialize()
{
AddKeyboardShortcuts();
ChangeDefaults();
ChangeDocumentDefaults();
}
void CodeEditorHandler::ChangeDocumentDefaults()
{
_call->SetUseTabs(false);
_call->SetTabWidth(4);
_call->SetIndent(4); // Brace matching and autoindent relies on this
}
void CodeEditorHandler::UpdateColors(CodeEditorTheme theme)
{
// Todo: Support high contrast mode
constexpr auto folderForeDark{ IntRGBA(0, 0, 0, 0) };
constexpr auto folderBackDark{ IntRGBA(0xFF, 0xFF, 0xFF, 148) };
constexpr auto folderBackHighlightDark{ folderBackDark };
constexpr auto folderForeLight{ IntRGBA(0xFF, 0xFF, 0xFF, 0) };
constexpr auto folderBackLight{ IntRGBA(0, 0, 0, 108) };
constexpr auto folderBackHighlightLight{ folderBackLight };
if (_theme != theme)
{
_theme = theme;
switch (theme)
{
case CodeEditorTheme::Dark:
_call->SetElementColour(Element::Caret, IntRGBA(0xAE, 0xAF, 0xAD));
_call->SetElementColour(Element::SelectionBack, IntRGBA(0x26, 0x4F, 0x78));
_call->SetElementColour(Element::SelectionAdditionalBack, IntRGBA(0x26, 0x4F, 0x78));
_call->SetElementColour(Element::SelectionInactiveBack, IntRGBA(0x3A, 0x3D, 0x41));
_call->SetElementColour(Element::HiddenLine, IntRGBA(0xFF, 0xFF, 0xFF, 48));
MarkerSetColors(Scintilla::MarkerOutline::FolderOpen, folderForeDark, folderBackDark, folderBackHighlightDark);
MarkerSetColors(Scintilla::MarkerOutline::Folder, folderForeDark, folderBackDark, folderBackHighlightDark);
MarkerSetColors(Scintilla::MarkerOutline::FolderSub, folderForeDark, folderBackDark, folderBackHighlightDark);
MarkerSetColors(Scintilla::MarkerOutline::FolderTail, folderForeDark, folderBackDark, folderBackHighlightDark);
MarkerSetColors(Scintilla::MarkerOutline::FolderEnd, folderForeDark, folderBackDark, folderBackHighlightDark);
MarkerSetColors(Scintilla::MarkerOutline::FolderOpenMid, folderForeDark, folderBackDark, folderBackHighlightDark);
MarkerSetColors(Scintilla::MarkerOutline::FolderMidTail, folderForeDark, folderBackDark, folderBackHighlightDark);
_call->MarkerSetForeTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryRevertedToOrigin), IntRGBA(0x35, 0x95, 0xDE));
_call->MarkerSetBackTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryRevertedToOrigin), IntRGBA(0x35, 0x95, 0xDE, 0x00));
_call->MarkerSetForeTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistorySaved), IntRGBA(0x55, 0xB1, 0x55));
_call->MarkerSetBackTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistorySaved), IntRGBA(0x55, 0xB1, 0x55));
_call->MarkerSetForeTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryModified), IntRGBA(0xD0, 0xB1, 0x32));
_call->MarkerSetBackTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryModified), IntRGBA(0x27, 0x27, 0x27, 0x00));
_call->MarkerSetForeTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryRevertedToModified), IntRGBA(0x93, 0xB1, 0x44));
_call->MarkerSetBackTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryRevertedToModified), IntRGBA(0x93, 0xB1, 0x44, 0x00));
break;
case CodeEditorTheme::Light:
_call->SetElementColour(Element::Caret, IntRGBA(0x00, 0x00, 0x00));
_call->SetElementColour(Element::SelectionBack, IntRGBA(0xAD, 0xD6, 0xFF));
_call->SetElementColour(Element::SelectionAdditionalBack, IntRGBA(0xAD, 0xD6, 0xFF));
_call->SetElementColour(Element::SelectionInactiveBack, IntRGBA(0xE5, 0xEB, 0xF1));
_call->SetElementColour(Element::HiddenLine, IntRGBA(0x00, 0x00, 0x00, 64));
MarkerSetColors(Scintilla::MarkerOutline::FolderOpen, folderForeLight, folderBackLight, folderBackHighlightLight);
MarkerSetColors(Scintilla::MarkerOutline::Folder, folderForeLight, folderBackLight, folderBackHighlightLight);
MarkerSetColors(Scintilla::MarkerOutline::FolderSub, folderForeLight, folderBackLight, folderBackHighlightLight);
MarkerSetColors(Scintilla::MarkerOutline::FolderTail, folderForeLight, folderBackLight, folderBackHighlightLight);
MarkerSetColors(Scintilla::MarkerOutline::FolderEnd, folderForeLight, folderBackLight, folderBackHighlightLight);
MarkerSetColors(Scintilla::MarkerOutline::FolderOpenMid, folderForeLight, folderBackLight, folderBackHighlightLight);
MarkerSetColors(Scintilla::MarkerOutline::FolderMidTail, folderForeLight, folderBackLight, folderBackHighlightLight);
_call->MarkerSetForeTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryRevertedToOrigin), IntRGBA(0x00, 0x78, 0xD4));
_call->MarkerSetBackTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryRevertedToOrigin), IntRGBA(0x00, 0x78, 0xD4, 0x00));
_call->MarkerSetForeTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistorySaved), IntRGBA(0x10, 0x7C, 0x10));
_call->MarkerSetBackTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistorySaved), IntRGBA(0x10, 0x7C, 0x10));
_call->MarkerSetForeTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryModified), IntRGBA(0xAE, 0x8C, 0x00));
_call->MarkerSetBackTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryModified), IntRGBA(0xF5, 0xF5, 0xF5, 0x00));
_call->MarkerSetForeTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryRevertedToModified), IntRGBA(0x5F, 0x84, 0x08));
_call->MarkerSetBackTranslucent(static_cast<int>(Scintilla::MarkerOutline::HistoryRevertedToModified), IntRGBA(0x5F, 0x84, 0x08, 0x00));
break;
}
UpdateCaretLineBackColors(true);
UpdateStyles();
}
}
// Duplicated from Helpers.cpp to make portable
// Derived from https://github.com/microsoft/Windows-universal-samples/blob/main/Samples/ComplexInk/cpp/Common/DeviceResources.h
static constexpr int ConvertFromDipToPixelUnit(float val, float dpiAdjustmentRatio, bool rounded = true)
{
float pixelVal = val * dpiAdjustmentRatio;
return static_cast<int>(rounded ? floorf(pixelVal + 0.5f) : pixelVal); // Todo: Test if this is ever necessary
}
void CodeEditorHandler::UpdateDpi(double value)
{
_dpiScale = value;
_call->SetXCaretPolicy(CaretPolicy::Slop | CaretPolicy::Strict | CaretPolicy::Even, ConvertFromDipToPixelUnit(24, value));
UpdateZoom();
}
void CodeEditorHandler::StyleSetFore(int style, ColourAlpha color)
{
// Overridable to allow users to internally set transparent color
_call->StyleSetFore(style, color);
}
void CodeEditorHandler::StyleSetBack(int style, ColourAlpha color)
{
// Overridable to allow users to internally set transparent color
_call->StyleSetBack(style, color);
}
void CodeEditorHandler::InvalidateStyleRedraw()
{
// Overridable to allow users to invalidate after setting all colors
// Not needed if using default StyleSetFore/Back
}
void CodeEditorHandler::StyleClearCustom()
{
// Less performant way to copy styles
// Overridable when there is access to Scintilla internals
for (size_t i = 0; i < 256; i++)
{
if (i < static_cast<int>(StylesCommon::Default) || i > static_cast<int>(StylesCommon::LastPredefined))
{
_call->StyleSetFont(i, _call->StyleGetFont(static_cast<int>(StylesCommon::Default)).c_str());
_call->StyleSetSizeFractional(i, _call->StyleGetSizeFractional(static_cast<int>(StylesCommon::Default)));
_call->StyleSetBold(i, _call->StyleGetBold(static_cast<int>(StylesCommon::Default)));
_call->StyleSetWeight(i, _call->StyleGetWeight(static_cast<int>(StylesCommon::Default)));
_call->StyleSetItalic(i, _call->StyleGetItalic(static_cast<int>(StylesCommon::Default)));
_call->StyleSetUnderline(i, _call->StyleGetUnderline(static_cast<int>(StylesCommon::Default)));
_call->StyleSetFore(i, _call->StyleGetFore(static_cast<int>(StylesCommon::Default)));
_call->StyleSetBack(i, _call->StyleGetBack(static_cast<int>(StylesCommon::Default)));
_call->StyleSetEOLFilled(i, _call->StyleGetEOLFilled(static_cast<int>(StylesCommon::Default)));
_call->StyleSetCharacterSet(i, _call->StyleGetCharacterSet(static_cast<int>(StylesCommon::Default)));
_call->StyleSetCase(i, _call->StyleGetCase(static_cast<int>(StylesCommon::Default)));
_call->StyleSetVisible(i, _call->StyleGetVisible(static_cast<int>(StylesCommon::Default)));
_call->StyleSetChangeable(i, _call->StyleGetChangeable(static_cast<int>(StylesCommon::Default)));
_call->StyleSetHotSpot(i, _call->StyleGetHotSpot(static_cast<int>(StylesCommon::Default)));
_call->StyleSetCheckMonospaced(i, _call->StyleGetCheckMonospaced(static_cast<int>(StylesCommon::Default)));
_call->StyleSetInvisibleRepresentation(i, _call->StyleGetInvisibleRepresentation(static_cast<int>(StylesCommon::Default)).c_str());
}
}
}
void CodeEditorHandler::SetFoldMarginColor(bool useSetting, ColourAlpha back)
{
// Implement for transparent folding margin. Not implemented so default is preserved
}
void CodeEditorHandler::SetFoldMarginHiColor(bool useSetting, ColourAlpha fore)
{
// Implement for transparent folding margin. Not implemented so default is preserved
}
void CodeEditorHandler::DefaultColorsChanged(CodeEditorTheme theme)
{
// Default event handler
}
void CodeEditorHandler::SyntaxHighlightingApplied(CodeEditorTheme theme)
{
// Default event handler
}
void CodeEditorHandler::UpdateStyles()
{
constexpr auto bgDark{ IntRGBA(0x27, 0x27, 0x27, 0x00) };
constexpr auto bgLight{ IntRGBA(0xF5, 0xF5, 0xF5, 0x00) };
switch (_theme)
{
case CodeEditorTheme::Dark:
StyleSetFore(static_cast<int>(StylesCommon::LineNumber), IntRGBA(0x85, 0x85, 0x85));
StyleSetBack(static_cast<int>(StylesCommon::LineNumber), bgDark);
StyleSetFore(static_cast<int>(StylesCommon::Default), IntRGBA(0xFF, 0xFF, 0xFF));
StyleSetBack(static_cast<int>(StylesCommon::Default), bgDark);
StyleSetFore(static_cast<int>(StylesCommon::BraceLight), IntRGBA(0xFF, 0xFF, 0xFF));
StyleSetBack(static_cast<int>(StylesCommon::BraceLight), IntRGBA(0x11, 0x3D, 0x6F));
StyleSetFore(static_cast<int>(StylesCommon::BraceBad), IntRGBA(0xcd, 0x31, 0x31));
StyleSetBack(static_cast<int>(StylesCommon::BraceBad), bgDark);
StyleSetFore(static_cast<int>(StylesCommon::IndentGuide), IntRGBA(0xFF, 0xFF, 0xFF, 48));
StyleSetBack(static_cast<int>(StylesCommon::IndentGuide), bgDark);
StyleSetFore(static_cast<int>(StylesCommon::ControlChar), IntRGBA(0xFF, 0xFF, 0xFF));
StyleSetBack(static_cast<int>(StylesCommon::ControlChar), IntRGBA(0x96, 0x00, 0x00));
StyleSetFore(static_cast<int>(StylesCommon::FoldDisplayText), IntRGBA(0xB8, 0xC2, 0xCC));
StyleSetBack(static_cast<int>(StylesCommon::FoldDisplayText), IntRGBA(0x26, 0x33, 0x3F));
break;
case CodeEditorTheme::Light:
StyleSetFore(static_cast<int>(StylesCommon::LineNumber), IntRGBA(0x23, 0x78, 0x93));
StyleSetBack(static_cast<int>(StylesCommon::LineNumber), bgLight);
StyleSetFore(static_cast<int>(StylesCommon::Default), IntRGBA(0x00, 0x00, 0x00));
StyleSetBack(static_cast<int>(StylesCommon::Default), bgLight);
StyleSetFore(static_cast<int>(StylesCommon::BraceLight), IntRGBA(0x00, 0x00, 0x00));
StyleSetBack(static_cast<int>(StylesCommon::BraceLight), IntRGBA(0xE2, 0xE6, 0xD6));
StyleSetFore(static_cast<int>(StylesCommon::BraceBad), IntRGBA(0xcd, 0x31, 0x31));
StyleSetBack(static_cast<int>(StylesCommon::BraceBad), bgLight);
StyleSetFore(static_cast<int>(StylesCommon::IndentGuide), IntRGBA(0x00, 0x00, 0x00, 64));
StyleSetBack(static_cast<int>(StylesCommon::IndentGuide), bgLight);
StyleSetFore(static_cast<int>(StylesCommon::ControlChar), IntRGBA(0xFF, 0xFF, 0xFF));
StyleSetBack(static_cast<int>(StylesCommon::ControlChar), IntRGBA(0x96, 0x00, 0x00));
StyleSetFore(static_cast<int>(StylesCommon::FoldDisplayText), IntRGBA(0x73, 0x79, 0x80));
StyleSetBack(static_cast<int>(StylesCommon::FoldDisplayText), IntRGBA(0xDC, 0xEA, 0xF5));
break;
}
DefaultColorsChanged(_theme);
UpdateLanguageStyles();
SyntaxHighlightingApplied(_theme);
InvalidateStyleRedraw();
}
void CodeEditorHandler::MarkerSetColors(Scintilla::MarkerOutline marker, Scintilla::ColourAlpha fore, Scintilla::ColourAlpha back, Scintilla::ColourAlpha backHighlight)
{
const auto markerNumber{ static_cast<int>(marker) };
_call->MarkerSetForeTranslucent(markerNumber, fore);
_call->MarkerSetBackTranslucent(markerNumber, back);
_call->MarkerSetBackSelectedTranslucent(markerNumber, backHighlight);
}
void CodeEditorHandler::UpdateCaretLineBackColors(bool colorsUpdated)
{
const auto hasEmptySelection = _call->SelectionEmpty();
if ((_hasEmptySelection != hasEmptySelection) || (hasEmptySelection && colorsUpdated))
{
_hasEmptySelection = hasEmptySelection;
if (hasEmptySelection)
{
switch (_theme)
{
case CodeEditorTheme::Dark:
_call->SetElementColour(Element::CaretLineBack, IntRGBA(0xFF, 0xFF, 0xFF, 16));
break;
case CodeEditorTheme::Light:
_call->SetElementColour(Element::CaretLineBack, IntRGBA(0x00, 0x00, 0x00, 12));
break;
}
}
else
{
_call->ResetElementColour(Element::CaretLineBack);
}
}
}
void CodeEditorHandler::UpdateBraceMatch()
{
SciBraceMatch();
}
void CodeEditorHandler::AutoIndent(char ch)
{
SciAutomaticIndentation(ch);
}
void CodeEditorHandler::SetLanguageIndentMode(
int indentKeywordStyle, const std::set<std::string> &indentKeywords,
int lineEndStyle, const std::set<std::string> &lineEndWords,
int blockStartStyle, const std::set<std::string> &blockStartWords,
int blockEndStyle, const std::set<std::string> &blockEndWords)
{
_sciStatementIndent = { indentKeywordStyle, { indentKeywords, } }; // Todo: customize. also note using WORD2 for these
_sciStatementEnd = { lineEndStyle, { lineEndWords, } };
_sciBlockStart = { blockStartStyle, { blockStartWords, } };
_sciBlockEnd = { blockEndStyle, { blockEndWords, } };
}
void CodeEditorHandler::UpdateZoom()
{
const auto size{ _call->StyleGetSizeFractional(static_cast<int>(StylesCommon::Default)) };
const auto zoom{ static_cast<int>(_call->Zoom()) };
const auto factor{ static_cast<float>((size + zoom * 100)) / size };
// Todo: Width 11 hard coded for a digit. Use below for real value:
// _call->TextWidth, static_cast<uptr_t>(StylesCommon::LineNumber), reinterpret_cast<sptr_t>("9"))
const auto line{ _call->LineCount() };
const auto width{ 12 + 11 * std::max(3, static_cast<int>(std::floor(std::log10(line) + 1))) };
_call->SetMarginWidthN(0, ConvertFromDipToPixelUnit(std::floorf(factor * width + 0.5f), _dpiScale));
_call->SetMarginWidthN(1, ConvertFromDipToPixelUnit(std::floorf(factor * 12 + 0.5f), _dpiScale));
_call->SetMarginWidthN(2, ConvertFromDipToPixelUnit(std::floorf(factor * 10 + 0.5f), _dpiScale));
const auto foldMarkerStroke{ ConvertFromDipToPixelUnit(factor * 100.0f, _dpiScale, false) };
_call->MarkerSetStrokeWidth(static_cast<int>(Scintilla::MarkerOutline::FolderOpen), foldMarkerStroke);
_call->MarkerSetStrokeWidth(static_cast<int>(Scintilla::MarkerOutline::Folder), foldMarkerStroke);
_call->MarkerSetStrokeWidth(static_cast<int>(Scintilla::MarkerOutline::FolderSub), foldMarkerStroke);
_call->MarkerSetStrokeWidth(static_cast<int>(Scintilla::MarkerOutline::FolderTail), foldMarkerStroke);
_call->MarkerSetStrokeWidth(static_cast<int>(Scintilla::MarkerOutline::FolderEnd), foldMarkerStroke);
_call->MarkerSetStrokeWidth(static_cast<int>(Scintilla::MarkerOutline::FolderOpenMid), foldMarkerStroke);
_call->MarkerSetStrokeWidth(static_cast<int>(Scintilla::MarkerOutline::FolderMidTail), foldMarkerStroke);
const auto historyMarkerStroke{ foldMarkerStroke };
_call->MarkerSetStrokeWidth(static_cast<int>(Scintilla::MarkerOutline::HistoryRevertedToOrigin), historyMarkerStroke);
// HistorySaved is left at default width (1) because rendering artifacts occur with the solid color + box outline
//_call->MarkerSetStrokeWidth(static_cast<int>(Scintilla::MarkerOutline::HistorySaved), historyMarkerStroke);
_call->MarkerSetStrokeWidth(static_cast<int>(Scintilla::MarkerOutline::HistoryModified), historyMarkerStroke);
_call->MarkerSetStrokeWidth(static_cast<int>(Scintilla::MarkerOutline::HistoryRevertedToModified), historyMarkerStroke);
_call->SetMarginLeft(ConvertFromDipToPixelUnit(std::floorf(factor * 1 + 0.5f), _dpiScale));
// Todo: Set caret width to be at least the UISettings system caret width
const auto caretWidth{ std::max(1.0f, std::floorf(factor * 2 * _dpiScale)) };
_call->SetCaretWidth(caretWidth); // Todo: Needs to stop blinking after timeout and respect blink rate
_call->SetCaretLineFrame(caretWidth);
_call->SetExtraDescent(std::floorf(factor * 1.8 * _dpiScale));
}
void CodeEditorHandler::AddKeyboardShortcuts()
{
_call->AssignCmdKey(187 + (static_cast<int>(KeyMod::Ctrl) << 16), static_cast<int>(Message::ZoomIn)); // Ctrl+Plus
_call->AssignCmdKey(189 + (static_cast<int>(KeyMod::Ctrl) << 16), static_cast<int>(Message::ZoomOut)); // Ctrl+Minus
_call->AssignCmdKey(48 + (static_cast<int>(KeyMod::Ctrl) << 16), static_cast<int>(Message::SetZoom)); // Ctrl+0
}
void CodeEditorHandler::ChangeDefaults()
{
_call->SetMultipleSelection(true);
_call->SetScrollWidth(2000);
_call->SetScrollWidthTracking(true);
_call->SetYCaretPolicy(CaretPolicy::Slop | CaretPolicy::Strict | CaretPolicy::Even, 1);
_call->SetVisiblePolicy(VisiblePolicy::Slop, 0);
_call->SetHScrollBar(true);
_call->SetEndAtLastLine(false);
_call->StyleSetFont(static_cast<int>(StylesCommon::Default), "Cascadia Code"); // Todo: Use font available on Windows 10
_call->StyleSetSizeFractional(static_cast<int>(StylesCommon::Default), 11 * FontSizeMultiplier);
_call->SetAdditionalSelectionTyping(true);
_call->SetMultiPaste(MultiPaste::Each);
_call->SetLayoutThreads(16); // Todo: Determine performance impact
_call->SetCaretLineVisibleAlways(true);
_call->SetCaretLineLayer(Layer::UnderText);
_call->SetCaretLineHighlightSubLine(true);
_call->SetIndentationGuides(IndentView::LookBoth);
_call->SetMarginMaskN(2, Scintilla::MaskFolders);
_call->SetMarginSensitiveN(2, true);
SetFoldMarginColor(true, IntRGBA(0, 0, 0, 0));
SetFoldMarginHiColor(true, IntRGBA(0, 0, 0, 0));
constexpr auto useCustomChevron{ true }; // Todo: make overridable
constexpr auto chevronMinus{ static_cast<MarkerSymbol>(1989) };
constexpr auto chevronPlus{ static_cast<MarkerSymbol>(1990) };
_call->MarkerDefine(static_cast<int>(MarkerOutline::FolderOpen), useCustomChevron ? chevronMinus : MarkerSymbol::BoxMinus);
_call->MarkerDefine(static_cast<int>(MarkerOutline::Folder), useCustomChevron ? chevronPlus : MarkerSymbol::BoxPlus);
_call->MarkerDefine(static_cast<int>(MarkerOutline::FolderSub), MarkerSymbol::VLine);
_call->MarkerDefine(static_cast<int>(MarkerOutline::FolderTail), MarkerSymbol::LCorner);
_call->MarkerDefine(static_cast<int>(MarkerOutline::FolderEnd), useCustomChevron ? chevronPlus : MarkerSymbol::BoxPlusConnected);
_call->MarkerDefine(static_cast<int>(MarkerOutline::FolderOpenMid), useCustomChevron ? chevronMinus : MarkerSymbol::BoxMinusConnected);
_call->MarkerDefine(static_cast<int>(MarkerOutline::FolderMidTail), MarkerSymbol::TCorner);
_call->MarkerEnableHighlight(false);
_call->SetDefaultFoldDisplayText(u8"\u00a0\u22ef\u00a0"); // ... nbsp + centered vertically + nbsp
_call->FoldDisplayTextSetStyle(Scintilla::FoldDisplayTextStyle::Standard);
_call->SetAutomaticFold(static_cast<Scintilla::AutomaticFold>(static_cast<int>(Scintilla::AutomaticFold::Show) | static_cast<int>(Scintilla::AutomaticFold::Click) | static_cast<int>(Scintilla::AutomaticFold::Change)));
}
// Todo: This code needs to integrate with find and replace
// Todo: This code seems to struggle with rectangular selections and/or multiple carets already existing and/or multiple selections already existing
void CodeEditorHandler::ChangeAllOccurrences()
{
sptr_t start;
sptr_t end;
const auto s{ GetMainSelectedText(true, start, end) };
if (s.length() == 0)
{
return;
}
const auto length{ end - start };
// Drop additional selections and ensure caret is at end of selection
_call->SetSelection(end, start);
_call->TargetWholeDocument();
_call->SetSearchFlags(FindOption::MatchCase);
const auto mainSelection{ _call->MainSelection() };
const auto bodyLength{ _call->Length() };
while (true)
{
const auto match{ _call->SearchInTarget(length, &s[0]) };
if (match == -1)
{
break;
}
const auto targetEnd{ _call->TargetEnd() };
if (match != start)
{
// Todo: Add maximum number of carets and notify user if exceeded (VS Code allows 10,000)
// Todo: This method calls a lot of redraws in a loop. You might need to use the lower level API to avoid that
_call->AddSelection(match + length, match);
}
_call->SetTargetStart(targetEnd);
_call->SetTargetEnd(bodyLength);
}
_call->SetMainSelection(mainSelection);
}
std::wstring_view CodeEditorHandler::HighlightingLanguage()
{
return _highlightingLanguage;
}
void CodeEditorHandler::HighlightingLanguage(std::wstring_view value)
{
if (_highlightingLanguage == value)
{
return;
}
_highlightingLanguage = value;
_call->ClearDocumentStyle();
SetLexer();
UpdateStyles();
_call->ColouriseAll();
}
void CodeEditorHandler::ProcessNotification(NotificationData *data)
{
if (data->nmhdr.code == Notification::Zoom
|| (data->nmhdr.code == Notification::Modified && data->linesAdded))
{
UpdateZoom();
}
if (data->nmhdr.code == Notification::UpdateUI && FlagSet(data->updated, Update::Content | Update::Selection))
{
UpdateCaretLineBackColors();
if (_call->Focus())
{
UpdateBraceMatch();
}
}
if (data->nmhdr.code == Notification::FocusOut)
{
_call->BraceBadLight(-1);
}
else if (data->nmhdr.code == Notification::FocusIn)
{
UpdateBraceMatch();
}
if (data->nmhdr.code == Notification::CharAdded && data->ch <= 0xFF)
{
const auto sel{ _call->SelectionSpan() };
if (sel.start == sel.end && sel.start > 0
&& !_call->CallTipActive()
&& !_call->AutoCActive())
{
AutoIndent(data->ch);
}
}
if (data->nmhdr.code == Notification::DoubleClick && _call->FoldDisplayTextGetStyle() != FoldDisplayTextStyle::Hidden)
{
const auto lineEndPosition{ _call->LineEndPosition(data->line) };
if ((data->position == lineEndPosition || data->position == InvalidPosition)
&& !_call->FoldExpanded(data->line))
{
const auto ctrl{ FlagSet(data->modifiers, KeyMod::Ctrl) };
const auto shift{ FlagSet(data->modifiers, KeyMod::Shift) };
const auto levelClick{ _call->FoldLevel(data->line) };
if (LevelIsHeader(levelClick))
{
if (shift)
{
// Ensure all children visible
_call->ExpandChildren(data->line, levelClick);
}
else if (ctrl)
{
_call->FoldChildren(data->line, FoldAction::Toggle);
}
else
{
// Toggle this line
_call->FoldLine(data->line, FoldAction::Toggle);
}
// Remove selection from double click
_call->SetEmptySelection(lineEndPosition);
}
}
}
}
std::string CodeEditorHandler::GetMainSelectedText(bool expandCaretToWord, sptr_t &start, sptr_t &end)
{
// Todo: This code may be problematic for rectangular selections
start = _call->SelectionStart();
end = _call->SelectionEnd();
if (expandCaretToWord && start == end)
{
start = _call->WordStartPosition(start, true);
end = _call->WordEndPosition(start, true);
if (start == end)
{
return "";
}
}
const auto length{ end - start };
std::string s(length, '\0');
TextRangeFull range
{
{ start, end, },
&s[0],
};
_call->GetTextRangeFull(&range);
return s;
}
}

View File

@ -1,102 +0,0 @@
#pragma once
#include <string>
#include <memory>
#include <set>
#include <vector>
#include "ScintillaTypes.h"
#include "ScintillaStructures.h"
#include "ScintillaCall.h"
#include "ILexer.h"
#include "Lexilla.h"
#include "CodeEditorHandler.SciEdit.h"
namespace WinUIEditor
{
constexpr int IntRGBA(unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha = 0xff) noexcept
{
return red | (green << 8) | (blue << 16) | (alpha << 24);
}
enum class CodeEditorTheme
{
Unset,
Light,
Dark,
};
struct CodeEditorHandler
{
void SetScintilla(std::shared_ptr<Scintilla::ScintillaCall> call);
void SetLexilla(Lexilla::CreateLexerFn createLexer);
void Initialize();
void ChangeDocumentDefaults();
void UpdateColors(CodeEditorTheme theme);
void UpdateDpi(double value);
void UpdateZoom();
void ChangeAllOccurrences();
std::wstring_view HighlightingLanguage();
void HighlightingLanguage(std::wstring_view language);
void ProcessNotification(Scintilla::NotificationData *data);
void SetLexer();
protected:
virtual void StyleSetFore(int style, Scintilla::ColourAlpha color);
virtual void StyleSetBack(int style, Scintilla::ColourAlpha color);
virtual void InvalidateStyleRedraw();
virtual void StyleClearCustom();
virtual void SetFoldMarginColor(bool useSetting, Scintilla::ColourAlpha back);
virtual void SetFoldMarginHiColor(bool useSetting, Scintilla::ColourAlpha fore);
virtual void DefaultColorsChanged(CodeEditorTheme theme);
virtual void SyntaxHighlightingApplied(CodeEditorTheme theme);
private:
std::shared_ptr<Scintilla::ScintillaCall> _call{ nullptr };
Lexilla::CreateLexerFn _createLexer{ nullptr };
CodeEditorTheme _theme{ CodeEditorTheme::Unset };
double _dpiScale;
int8_t _hasEmptySelection{ -1 };
std::wstring _highlightingLanguage;
void UpdateStyles();
void UpdateCaretLineBackColors(bool colorsUpdated = false);
void UpdateBraceMatch();
void AutoIndent(char ch);
void AddKeyboardShortcuts();
void ChangeDefaults();
std::string GetMainSelectedText(bool expandCaretToWord, Scintilla::sptr_t &start, Scintilla::sptr_t &end);
void SetLanguageIndentMode(
int indentKeywordStyle, const std::set<std::string> &indentKeywords,
int lineEndStyle, const std::set<std::string> &lineEndWords,
int blockStartStyle, const std::set<std::string> &blockStartWords,
int blockEndStyle, const std::set<std::string> &blockEndWords
);
void SetJavaScriptDefaults(int wordList1, int wordList2, int indentKeywordStyle, int symbolStyle);
void UpdateLanguageStyles();
void MarkerSetColors(Scintilla::MarkerOutline marker, Scintilla::ColourAlpha fore, Scintilla::ColourAlpha back, Scintilla::ColourAlpha backHighlight);
static constexpr bool _sciIndentOpening{ false };
static constexpr bool _sciIndentClosing{ false };
static constexpr int _sciStatementLookback{ 20 };
Internal::StyleAndWords _sciStatementIndent;
Internal::StyleAndWords _sciStatementEnd;
Internal::StyleAndWords _sciBlockStart;
Internal::StyleAndWords _sciBlockEnd;
bool SciFindMatchingBracePosition(Scintilla::Position &braceAtCaret, Scintilla::Position &braceOpposite, bool sloppy);
void SciBraceMatch();
Scintilla::Line SciGetCurrentLineNumber();
int SciIndentOfBlock(Scintilla::Line line);
int SciGetLineIndentation(Scintilla::Line line);
Scintilla::Position SciGetLineIndentPosition(Scintilla::Line line);
void SciSetLineIndentation(Scintilla::Line line, int indent);
Scintilla::Span SciGetSelection();
std::vector<std::string> SciGetLinePartsInStyle(Scintilla::Line line, const Internal::StyleAndWords &saw);
void SciSetSelection(Scintilla::Position anchor, Scintilla::Position currentPos);
bool SciRangeIsAllWhitespace(Scintilla::Position start, Scintilla::Position end);
Internal::IndentationStatus SciGetIndentState(Scintilla::Line line);
void SciAutomaticIndentation(char ch);
};
}

View File

@ -1,4 +0,0 @@
#pragma once
#include "EditorBaseControl.h"
#include "CodeEditorControl.h"

View File

@ -1,213 +0,0 @@
// Ported from
// https://github.com/microsoft/vscode/blob/main/extensions/theme-defaults/themes/dark_plus.json
// https://github.com/microsoft/vscode/blob/main/extensions/theme-defaults/themes/dark_vs.json
// under the following license
/*
MIT License
Copyright (c) 2015 - present Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
namespace WinUIEditor
{
constexpr int DarkPlusEditorForeground{ IntRGBA(0xD4, 0xD4, 0xD4) };
constexpr int DarkPlus(Scope scope)
{
switch (scope)
{
case Scope::MetaEmbedded: return IntRGBA(0xD4, 0xD4, 0xD4);
case Scope::SourceGroovyEmbedded: return IntRGBA(0xD4, 0xD4, 0xD4);
case Scope::String__MetaImageInlineMarkdown: return IntRGBA(0xD4, 0xD4, 0xD4);
case Scope::VariableLegacyBuiltinPython: return IntRGBA(0xD4, 0xD4, 0xD4);
case Scope::Header: return IntRGBA(0x00, 0x00, 0x80);
case Scope::Comment: return IntRGBA(0x6A, 0x99, 0x55);
case Scope::ConstantLanguage: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::ConstantNumeric: return IntRGBA(0xB5, 0xCE, 0xA8);
case Scope::VariableOtherEnummember: return IntRGBA(0x4F, 0xC1, 0xFF);
case Scope::KeywordOperatorPlusExponent: return IntRGBA(0xB5, 0xCE, 0xA8);
case Scope::KeywordOperatorMinusExponent: return IntRGBA(0xB5, 0xCE, 0xA8);
case Scope::ConstantRegexp: return IntRGBA(0x64, 0x66, 0x95);
case Scope::EntityNameTag: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::EntityNameTagCss: return IntRGBA(0xD7, 0xBA, 0x7D);
case Scope::EntityOtherAttribute_Name: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::EntityOtherAttribute_NameClassCss: return IntRGBA(0xD7, 0xBA, 0x7D);
case Scope::EntityOtherAttribute_NameClassMixinCss: return IntRGBA(0xD7, 0xBA, 0x7D);
case Scope::EntityOtherAttribute_NameIdCss: return IntRGBA(0xD7, 0xBA, 0x7D);
case Scope::EntityOtherAttribute_NameParent_SelectorCss: return IntRGBA(0xD7, 0xBA, 0x7D);
case Scope::EntityOtherAttribute_NamePseudo_ClassCss: return IntRGBA(0xD7, 0xBA, 0x7D);
case Scope::EntityOtherAttribute_NamePseudo_ElementCss: return IntRGBA(0xD7, 0xBA, 0x7D);
case Scope::SourceCssLess__EntityOtherAttribute_NameId: return IntRGBA(0xD7, 0xBA, 0x7D);
case Scope::EntityOtherAttribute_NameScss: return IntRGBA(0xD7, 0xBA, 0x7D);
case Scope::Invalid: return IntRGBA(0xF4, 0x47, 0x47);
case Scope::MarkupBold: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::MarkupHeading: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::MarkupInserted: return IntRGBA(0xB5, 0xCE, 0xA8);
case Scope::MarkupDeleted: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::MarkupChanged: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::PunctuationDefinitionQuoteBeginMarkdown: return IntRGBA(0x6A, 0x99, 0x55);
case Scope::PunctuationDefinitionListBeginMarkdown: return IntRGBA(0x67, 0x96, 0xE6);
case Scope::MarkupInlineRaw: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::PunctuationDefinitionTag: return IntRGBA(0x80, 0x80, 0x80);
case Scope::MetaPreprocessor: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::EntityNameFunctionPreprocessor: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::MetaPreprocessorString: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::MetaPreprocessorNumeric: return IntRGBA(0xB5, 0xCE, 0xA8);
case Scope::MetaStructureDictionaryKeyPython: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::MetaDiffHeader: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::Storage: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::StorageType: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::StorageModifier: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordOperatorNoexcept: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::String: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::MetaEmbeddedAssembly: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::StringTag: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::StringValue: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::StringRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::PunctuationDefinitionTemplate_ExpressionBegin: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::PunctuationDefinitionTemplate_ExpressionEnd: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::PunctuationSectionEmbedded: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::MetaTemplateExpression: return IntRGBA(0xD4, 0xD4, 0xD4);
case Scope::SupportTypeVendoredProperty_Name: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::SupportTypeProperty_Name: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::VariableCss: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::VariableScss: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::VariableOtherLess: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::SourceCoffeeEmbedded: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::Keyword: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordControl: return IntRGBA(0xC5, 0x86, 0xC0);
case Scope::KeywordOperator: return IntRGBA(0xD4, 0xD4, 0xD4);
case Scope::KeywordOperatorNew: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordOperatorExpression: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordOperatorCast: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordOperatorSizeof: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordOperatorAlignof: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordOperatorTypeid: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordOperatorAlignas: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordOperatorInstanceof: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordOperatorLogicalPython: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordOperatorWordlike: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::KeywordOtherUnit: return IntRGBA(0xB5, 0xCE, 0xA8);
case Scope::PunctuationSectionEmbeddedBeginPhp: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::PunctuationSectionEmbeddedEndPhp: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::SupportFunctionGit_Rebase: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::ConstantShaGit_Rebase: return IntRGBA(0xB5, 0xCE, 0xA8);
case Scope::StorageModifierImportJava: return IntRGBA(0xD4, 0xD4, 0xD4);
case Scope::VariableLanguageWildcardJava: return IntRGBA(0xD4, 0xD4, 0xD4);
case Scope::StorageModifierPackageJava: return IntRGBA(0xD4, 0xD4, 0xD4);
case Scope::VariableLanguage: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::EntityNameFunction: return IntRGBA(0xDC, 0xDC, 0xAA);
case Scope::SupportFunction: return IntRGBA(0xDC, 0xDC, 0xAA);
case Scope::SupportConstantHandlebars: return IntRGBA(0xDC, 0xDC, 0xAA);
case Scope::SourcePowershell__VariableOtherMember: return IntRGBA(0xDC, 0xDC, 0xAA);
case Scope::EntityNameOperatorCustom_Literal: return IntRGBA(0xDC, 0xDC, 0xAA);
case Scope::SupportClass: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::SupportType: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::EntityNameType: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::EntityNameNamespace: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::EntityOtherAttribute: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::EntityNameScope_Resolution: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::EntityNameClass: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeNumericGo: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeByteGo: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeBooleanGo: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeStringGo: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeUintptrGo: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeErrorGo: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeRuneGo: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeCs: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeGenericCs: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeModifierCs: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeVariableCs: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeAnnotationJava: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeGenericJava: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeJava: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeObjectArrayJava: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypePrimitiveArrayJava: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypePrimitiveJava: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeTokenJava: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeGroovy: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeAnnotationGroovy: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeParametersGroovy: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeGenericGroovy: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypeObjectArrayGroovy: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypePrimitiveArrayGroovy: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::StorageTypePrimitiveGroovy: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::MetaTypeCastExpr: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::MetaTypeNewExpr: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::SupportConstantMath: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::SupportConstantDom: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::SupportConstantJson: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::EntityOtherInherited_Class: return IntRGBA(0x4E, 0xC9, 0xB0);
case Scope::SourceCpp__KeywordOperatorNew: return IntRGBA(0xC5, 0x86, 0xC0);
case Scope::KeywordOperatorDelete: return IntRGBA(0xC5, 0x86, 0xC0);
case Scope::KeywordOtherUsing: return IntRGBA(0xC5, 0x86, 0xC0);
case Scope::KeywordOtherDirectiveUsing: return IntRGBA(0xC5, 0x86, 0xC0);
case Scope::KeywordOtherOperator: return IntRGBA(0xC5, 0x86, 0xC0);
case Scope::EntityNameOperator: return IntRGBA(0xC5, 0x86, 0xC0);
case Scope::Variable: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::MetaDefinitionVariableName: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::SupportVariable: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::EntityNameVariable: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::ConstantOtherPlaceholder: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::VariableOtherConstant: return IntRGBA(0x4F, 0xC1, 0xFF);
case Scope::MetaObject_LiteralKey: return IntRGBA(0x9C, 0xDC, 0xFE);
case Scope::SupportConstantProperty_Value: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::SupportConstantFont_Name: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::SupportConstantMedia_Type: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::SupportConstantMedia: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::ConstantOtherColorRgb_Value: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::ConstantOtherRgb_Value: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::SupportConstantColor: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::PunctuationDefinitionGroupRegexp: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::PunctuationDefinitionGroupAssertionRegexp: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::PunctuationDefinitionCharacter_ClassRegexp: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::PunctuationCharacterSetBeginRegexp: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::PunctuationCharacterSetEndRegexp: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::KeywordOperatorNegationRegexp: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::SupportOtherParenthesisRegexp: return IntRGBA(0xCE, 0x91, 0x78);
case Scope::ConstantCharacterCharacter_ClassRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::ConstantOtherCharacter_ClassSetRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::ConstantOtherCharacter_ClassRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::ConstantCharacterSetRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::KeywordOperatorOrRegexp: return IntRGBA(0xDC, 0xDC, 0xAA);
case Scope::KeywordControlAnchorRegexp: return IntRGBA(0xDC, 0xDC, 0xAA);
case Scope::KeywordOperatorQuantifierRegexp: return IntRGBA(0xD7, 0xBA, 0x7D);
case Scope::ConstantCharacter: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::ConstantOtherOption: return IntRGBA(0x56, 0x9C, 0xD6);
case Scope::ConstantCharacterEscape: return IntRGBA(0xD7, 0xBA, 0x7D);
case Scope::EntityNameLabel: return IntRGBA(0xC8, 0xC8, 0xC8);
}
}
constexpr int DarkPlus2(Scope scope)
{
switch (scope)
{
case Scope::MetaPreprocessor: return IntRGBA(0x9B, 0x9B, 0x9B);
case Scope::SupportTypeProperty_NameJson: return DarkPlus(Scope::SupportTypeProperty_Name);
default: return DarkPlus(scope);
}
}
}

View File

@ -1,5 +0,0 @@
#ifdef WINUI3
#define DUX Microsoft.UI.Xaml
#else
#define DUX Windows.UI.Xaml
#endif

View File

@ -1,13 +0,0 @@
#include "pch.h"
#include "DummyPage.h"
#if __has_include("DummyPage.g.cpp")
#include "DummyPage.g.cpp"
#endif
// Workaround for https://github.com/microsoft/xlang/issues/431
// Improves compile time when working on headers by including
// them in the DummyPage header instead of pch.h
// because the XAML compiler is not including them itself
// Not used in Release mode
// Do not include in metadata

View File

@ -1,19 +0,0 @@
#pragma once
#include "DummyPage.g.h"
#include "ControlIncludes.h"
namespace winrt::WinUIEditor::implementation
{
struct DummyPage : DummyPageT<DummyPage>
{
};
}
namespace winrt::WinUIEditor::factory_implementation
{
struct DummyPage : DummyPageT<DummyPage, implementation::DummyPage>
{
};
}

View File

@ -1,11 +0,0 @@
#include "Defines.idl"
namespace WinUIEditor
{
[default_interface]
[webhosthidden]
runtimeclass DummyPage : DUX.Controls.Page
{
DummyPage();
}
}

View File

@ -1,8 +0,0 @@
<Page
x:Class="WinUIEditor.DummyPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:WinUIEditor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" />

View File

@ -1,665 +0,0 @@
#include "pch.h"
#include "EditorBaseControl.h"
#if __has_include("EditorBaseControl.g.cpp")
#include "EditorBaseControl.g.cpp"
#endif
#include "EditorWrapper.h"
#include "Helpers.h"
#include "EditorBaseControlAutomationPeer.h"
using namespace ::WinUIEditor;
using namespace winrt;
using namespace DUX;
using namespace DUX::Automation::Peers;
using namespace DUX::Controls;
using namespace DUX::Controls::Primitives;
using namespace DUX::Input;
using namespace DUX::Media;
using namespace DUX::Media::Imaging;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::System;
using namespace Windows::Graphics::Display;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::DataTransfer;
namespace winrt::WinUIEditor::implementation
{
// Todo: Something about this control is keeping the WinUI 3 versions from closing.
// Note that making this into a blank control fixes the issue, so it is definitely something here.
EditorBaseControl::EditorBaseControl()
{
DefaultStyleKey(winrt::box_value(L"WinUIEditor.EditorBaseControl"));
_wrapper = std::make_shared<Wrapper>();
Loaded({ this, &EditorBaseControl::OnLoaded });
Unloaded({ this, &EditorBaseControl::OnUnloaded });
#ifndef WINUI3
if (!_hasXamlRoot)
{
_displayInformation = DisplayInformation::GetForCurrentView();
}
#endif
_scintilla = make_self<Scintilla::Internal::ScintillaWinUI>(_wrapper);
_call = std::make_shared<Scintilla::ScintillaCall>();
_call->SetFnPtr(reinterpret_cast<SciFnDirectStatus>(_scintilla->WndProc(Scintilla::Message::GetDirectStatusFunction, 0, 0)), _scintilla->WndProc(Scintilla::Message::GetDirectPointer, 0, 0));
_editorWrapper = make<implementation::Editor>(get_strong());
_scintilla->SetWndProcTag(*this);
_scintilla->SetWndProc(&EditorBaseControl::WndProc);
#ifndef WINUI3
if (_hasFcu)
{
#endif
// Registering the CharacterReceived event causes undesirable behavior with TSF in CoreWindow (normal UWP)
// but is required to get text in classic windows (XAML Islands and WinUI 3)
// Todo: Find more ideal way to do this
// Tried using _tfThreadManager->GetActiveFlags but TF_TMF_IMMERSIVEMODE flag was not accurate
if (IsClassicWindow())
{
CharacterReceived({ this, &EditorBaseControl::EditorBaseControl_CharacterReceived });
}
#ifndef WINUI3
}
#endif
}
EditorBaseControl::~EditorBaseControl()
{
_scintilla->Finalize();
}
WinUIEditor::Editor EditorBaseControl::Editor()
{
return _editorWrapper;
}
void EditorBaseControl::OnLoaded(IInspectable const &sender, DUX::RoutedEventArgs const &args)
{
// Following pattern from https://github.com/microsoft/microsoft-ui-xaml/blob/a7183df20367bc0e2b8c825430597a5c1e6871b6/dev/WebView2/WebView2.cpp#L1556
#ifndef WINUI3
_isLoaded = true;
#endif
if (!IsLoadedCompat())
{
return;
}
#ifndef WINUI3
if (_hasXamlRoot)
{
#endif
UpdateDpi(XamlRoot().RasterizationScale());
_xamlRootChangedRevoker = XamlRoot().Changed(auto_revoke, { this, &EditorBaseControl::XamlRoot_Changed });
#ifndef WINUI3
}
else
{
UpdateDpi(_displayInformation.RawPixelsPerViewPixel());
_dpiChangedRevoker = _displayInformation.DpiChanged(auto_revoke, { this, &EditorBaseControl::DisplayInformation_DpiChanged });
}
#endif
}
void EditorBaseControl::OnUnloaded(IInspectable const &sender, DUX::RoutedEventArgs const &args)
{
#ifndef WINUI3
_isLoaded = false;
#endif
if (IsLoadedCompat())
{
return;
}
#ifndef WINUI3
if (_hasXamlRoot)
{
#endif
_xamlRootChangedRevoker.revoke();
#ifndef WINUI3
}
else
{
_dpiChangedRevoker.revoke();
}
#endif
_scintilla->StopTimers();
}
bool EditorBaseControl::IsLoadedCompat()
{
#ifndef WINUI3
if (_hasIsLoaded)
{
#endif
return IsLoaded();
#ifndef WINUI3
}
else
{
return _isLoaded;
}
#endif
}
#ifndef WINUI3
void EditorBaseControl::DisplayInformation_DpiChanged(DisplayInformation const &sender, IInspectable const &args)
{
UpdateDpi(sender.RawPixelsPerViewPixel());
}
#endif
void EditorBaseControl::XamlRoot_Changed(DUX::XamlRoot const &sender, XamlRootChangedEventArgs const &args)
{
UpdateDpi(sender.RasterizationScale());
}
void EditorBaseControl::UpdateDpi(float dpiScale)
{
if (_dpiScale != dpiScale)
{
_wrapper->LogicalDpi(dpiScale * 96);
_dpiScale = dpiScale;
_scintilla->DpiChanged();
_dpiChangedEvent(*this, dpiScale);
}
}
void EditorBaseControl::AddContextMenuItems(MenuFlyout const &menu)
{
const auto writable{ !static_cast<bool>(_scintilla->WndProc(Scintilla::Message::GetReadOnly, 0, 0)) };
const auto selection{ !static_cast<bool>(_scintilla->WndProc(Scintilla::Message::GetSelectionEmpty, 0, 0)) };
const MenuFlyoutItem undoItem{};
undoItem.Text(L"Undo"); // Todo: Localize
undoItem.Icon(SymbolIcon{ Symbol::Undo });
undoItem.Tag(box_value(ScintillaMessage::Undo));
undoItem.IsEnabled(_scintilla->WndProc(Scintilla::Message::CanUndo, 0, 0));
undoItem.Click({ this, &EditorBaseControl::ContextMenuItem_Click }); // Todo: Revoke event handler?
menu.Items().Append(undoItem);
const MenuFlyoutItem redoItem{};
redoItem.Text(L"Redo");
redoItem.Icon(SymbolIcon{ Symbol::Redo });
redoItem.Tag(box_value(ScintillaMessage::Redo));
redoItem.IsEnabled(_scintilla->WndProc(Scintilla::Message::CanRedo, 0, 0));
redoItem.Click({ this, &EditorBaseControl::ContextMenuItem_Click });
menu.Items().Append(redoItem);
menu.Items().Append(MenuFlyoutSeparator{});
const MenuFlyoutItem cutItem{};
cutItem.Text(L"Cut");
cutItem.Icon(SymbolIcon{ Symbol::Cut });
cutItem.Tag(box_value(ScintillaMessage::Cut));
cutItem.IsEnabled(writable && selection);
cutItem.Click({ this, &EditorBaseControl::ContextMenuItem_Click });
menu.Items().Append(cutItem);
const MenuFlyoutItem copyItem{};
copyItem.Text(L"Copy");
copyItem.Icon(SymbolIcon{ Symbol::Copy });
copyItem.Tag(box_value(ScintillaMessage::Copy));
copyItem.IsEnabled(selection);
copyItem.Click({ this, &EditorBaseControl::ContextMenuItem_Click });
menu.Items().Append(copyItem);
const MenuFlyoutItem pasteItem{};
pasteItem.Text(L"Paste");
pasteItem.Icon(SymbolIcon{ Symbol::Paste });
pasteItem.Tag(box_value(ScintillaMessage::Paste));
pasteItem.IsEnabled(_scintilla->WndProc(Scintilla::Message::CanPaste, 0, 0));
pasteItem.Click({ this, &EditorBaseControl::ContextMenuItem_Click });
menu.Items().Append(pasteItem);
const MenuFlyoutItem deleteItem{};
deleteItem.Text(L"Delete");
deleteItem.Icon(SymbolIcon{ Symbol::Delete });
deleteItem.Tag(box_value(ScintillaMessage::Clear));
deleteItem.IsEnabled(writable && selection);
deleteItem.Click({ this, &EditorBaseControl::ContextMenuItem_Click });
menu.Items().Append(deleteItem);
menu.Items().Append(MenuFlyoutSeparator{});
const MenuFlyoutItem selectAllItem{};
selectAllItem.Text(L"Select all");
selectAllItem.Icon(SymbolIcon{ Symbol::SelectAll });
selectAllItem.Tag(box_value(ScintillaMessage::SelectAll));
selectAllItem.Click({ this, &EditorBaseControl::ContextMenuItem_Click });
menu.Items().Append(selectAllItem);
}
bool EditorBaseControl::ShowContextMenu(UIElement const &targetElement, Point const &point)
{
if (_scintilla->ShouldShowContextMenu(Point{ point.X * _dpiScale, point.Y * _dpiScale }))
{
const MenuFlyout menu{};
AddContextMenuItems(menu);
menu.ShowAt(targetElement, point);
return true;
}
return false;
}
bool EditorBaseControl::ShowContextMenuAtCurrentPosition()
{
if (auto imageTarget{ GetTemplateChild(L"ImageTarget").try_as<UIElement>() }) // Todo: Store this
{
const auto pos{ _scintilla->WndProc(Scintilla::Message::GetCurrentPos, 0, 0) };
return ShowContextMenu(imageTarget, Point{
_scintilla->WndProc(Scintilla::Message::PointXFromPosition, 0, pos) / _dpiScale,
(_scintilla->WndProc(Scintilla::Message::PointYFromPosition, 0, pos) + _scintilla->WndProc(Scintilla::Message::TextHeight, 0, 0)) / _dpiScale
});
}
return false;
}
Scintilla::sptr_t EditorBaseControl::PublicWndProc(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam)
{
return _scintilla->WndProc(iMessage, wParam, lParam);
}
int64_t EditorBaseControl::SendMessage(ScintillaMessage const &message, uint64_t wParam, int64_t lParam)
{
return PublicWndProc(static_cast<Scintilla::Message>(message), wParam, lParam);
}
void EditorBaseControl::StyleSetForeTransparent(int style, Scintilla::Internal::ColourRGBA color)
{
_scintilla->StyleSetForeTransparent(style, color);
}
void EditorBaseControl::StyleSetBackTransparent(int style, Scintilla::Internal::ColourRGBA color)
{
_scintilla->StyleSetBackTransparent(style, color);
}
void EditorBaseControl::InvalidateStyleRedraw()
{
_scintilla->PublicInvalidateStyleRedraw();
}
void EditorBaseControl::StyleClearCustom()
{
_scintilla->StyleClearCustom();
}
void EditorBaseControl::SetFoldMarginColorTransparent(bool useSetting, Scintilla::Internal::ColourRGBA back)
{
_scintilla->SetFoldMarginColorTransparent(useSetting, back);
}
void EditorBaseControl::SetFoldMarginHiColorTransparent(bool useSetting, Scintilla::Internal::ColourRGBA fore)
{
_scintilla->SetFoldMarginHiColorTransparent(useSetting, fore);
}
void EditorBaseControl::OnApplyTemplate()
{
__super::OnApplyTemplate();
#ifndef WINUI3
if (_hasXamlRoot)
{
#endif
UpdateDpi(XamlRoot().RasterizationScale());
#ifndef WINUI3
}
else
{
UpdateDpi(_displayInformation.RawPixelsPerViewPixel());
}
#endif
const VirtualSurfaceImageSource virtualSurfaceImageSource{ 0, 0 };
_vsisNative = virtualSurfaceImageSource.as<::IVirtualSurfaceImageSourceNative>();
_wrapper->VsisNative(_vsisNative);
_wrapper->CreateGraphicsDevices();
_vsisNative->RegisterForUpdatesNeeded(_scintilla.as<::IVirtualSurfaceUpdatesCallbackNative>().get());
// The SurfaceImageSource object's underlying
// ISurfaceImageSourceNativeWithD2D object will contain the completed bitmap.
const auto horizontalScrollBar{ GetTemplateChild(L"HorizontalScrollBar").try_as<ScrollBar>() };
const auto verticalScrollBar{ GetTemplateChild(L"VerticalScrollBar").try_as<ScrollBar>() };
if (horizontalScrollBar)
{
_horizontalScrollBarScrollRevoker = horizontalScrollBar.Scroll(auto_revoke, { this, &EditorBaseControl::HorizontalScrollBar_Scroll });
}
if (verticalScrollBar)
{
_verticalScrollBarScrollRevoker = verticalScrollBar.Scroll(auto_revoke, { this, &EditorBaseControl::VerticalScrollBar_Scroll });
}
_wrapper->SetScrollBars(horizontalScrollBar, verticalScrollBar);
if (const auto imageTarget{ GetTemplateChild(L"ImageTarget").try_as<Border>() })
{
_imageTargetSizeChangedRevoker = imageTarget.SizeChanged(auto_revoke, { this, &EditorBaseControl::ImageTarget_SizeChanged });
_imageTargetPointerMovedRevoker = imageTarget.PointerMoved(auto_revoke, { this, &EditorBaseControl::ImageTarget_PointerMoved });
#ifndef WINUI3
_imageTargetPointerCaptureLostRevoker = imageTarget.PointerCaptureLost(auto_revoke, { this, &EditorBaseControl::ImageTarget_PointerCaptureLost });
_imageTargetPointerEnteredRevoker = imageTarget.PointerEntered(auto_revoke, { this, &EditorBaseControl::ImageTarget_PointerEntered });
#endif
_imageTargetPointerExitedRevoker = imageTarget.PointerExited(auto_revoke, { this, &EditorBaseControl::ImageTarget_PointerExited });
_imageTargetPointerWheelChangedRevoker = imageTarget.PointerWheelChanged(auto_revoke, { this, &EditorBaseControl::ImageTarget_PointerWheelChanged });
_imageTargetDragEnterRevoker = imageTarget.DragEnter(auto_revoke, { this, &EditorBaseControl::ImageTarget_DragEnter });
_imageTargetDragOverRevoker = imageTarget.DragOver(auto_revoke, { this, &EditorBaseControl::ImageTarget_DragOver });
_imageTargetDragLeaveRevoker = imageTarget.DragLeave(auto_revoke, { this, &EditorBaseControl::ImageTarget_DragLeave });
_imageTargetDropRevoker = imageTarget.Drop(auto_revoke, { this, &EditorBaseControl::ImageTarget_Drop });
_wrapper->SetMouseCaptureElement(imageTarget);
_imageTargetDragStartingRevoker = imageTarget.DragStarting(auto_revoke, { this, &EditorBaseControl::ImageTarget_DragStarting });
_imageTargetContextRequestedRevoker = imageTarget.ContextRequested(auto_revoke, { this, &EditorBaseControl::ImageTarget_ContextRequested });
const ImageBrush brush{};
brush.ImageSource(virtualSurfaceImageSource);
imageTarget.Background(brush);
}
#ifndef WINUI3
// Todo: Evaluate if this is an appropriate place to add this event (and other code in this method)
_suspendingRevoker = Application::Current().Suspending(auto_revoke, { this, &EditorBaseControl::Application_Suspending });
#endif
}
// Todo: Focus bug: deactive window, click on control, press ctrl+a quickly. result: selection disappears
void EditorBaseControl::OnGotFocus(RoutedEventArgs const &e)
{
__super::OnGotFocus(e);
_isFocused = true;
_scintilla->FocusChanged(true);
}
void EditorBaseControl::OnLostFocus(RoutedEventArgs const &e)
{
__super::OnLostFocus(e);
_isFocused = false;
_scintilla->FocusChanged(false);
}
void EditorBaseControl::OnPointerPressed(DUX::Input::PointerRoutedEventArgs const &e)
{
__super::OnPointerPressed(e);
Focus(FocusState::Pointer);
// The focus state seems to get confused if the following code is placed in ImageTarget_PointerPressed.
// OnPointerReleased is the same for symmetry. ImageTarget_PointerMoved is there to show correct cursor
// when moving the cursor over the scrollbar (UWP).
if (auto imageTarget{ GetTemplateChild(L"ImageTarget").try_as<UIElement>() }) // Todo: Store this
{
auto point{ e.GetCurrentPoint(imageTarget) };
auto scaled{ point.Position() };
switch (point.Properties().PointerUpdateKind())
{
case DUI::PointerUpdateKind::LeftButtonPressed:
_scintilla->PointerPressed(Point{ scaled.X * _dpiScale, scaled.Y * _dpiScale }, point.Timestamp() / 1000ul, e.KeyModifiers());
break;
case DUI::PointerUpdateKind::RightButtonPressed:
_scintilla->RightPointerPressed(Point{ scaled.X * _dpiScale, scaled.Y * _dpiScale }, point.Timestamp() / 1000ul, e.KeyModifiers());
break;
}
// Todo: make sure the loss of precision is not going to realistically cause a problem
}
}
void EditorBaseControl::OnPointerReleased(DUX::Input::PointerRoutedEventArgs const &e)
{
__super::OnPointerReleased(e);
if (auto imageTarget{ GetTemplateChild(L"ImageTarget").try_as<UIElement>() }) // Todo: Store this
{
auto point{ e.GetCurrentPoint(imageTarget) };
auto scaled{ point.Position() };
switch (point.Properties().PointerUpdateKind())
{
case DUI::PointerUpdateKind::LeftButtonReleased:
_scintilla->PointerReleased(Point{ scaled.X * _dpiScale, scaled.Y * _dpiScale }, point.Timestamp() / 1000ul, e.KeyModifiers());
break;
}
}
e.Handled(true); // Prevents control from losing focus on pointer released
// See https://stackoverflow.com/questions/59392044/uwp-control-to-keep-focus-after-mouse-click
// Alternate approach: call Focus in OnFocusLost
}
AutomationPeer EditorBaseControl::OnCreateAutomationPeer()
{
return make<EditorBaseControlAutomationPeer>(*this);
}
void EditorBaseControl::ImageTarget_PointerMoved(IInspectable const &sender, PointerRoutedEventArgs const &e)
{
if (auto imageTarget{ GetTemplateChild(L"ImageTarget").try_as<UIElement>() }) // Todo: Store this
{
auto point{ e.GetCurrentPoint(imageTarget) };
auto scaled{ point.Position() };
auto x{ scaled.X * _dpiScale };
auto y{ scaled.Y * _dpiScale };
_scintilla->PointerMoved(Point{ x, y }, point.Timestamp() / 1000ul, e.KeyModifiers(), point);
}
}
#ifndef WINUI3
void EditorBaseControl::ImageTarget_PointerCaptureLost(IInspectable const &sender, PointerRoutedEventArgs const &e)
{
if (!_isPointerOver)
{
// Todo: if you, e.g. hover over a HyperlinkButton when this is called, you will get an arrow instead of the hand you want
winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread().PointerCursor(Windows::UI::Core::CoreCursor{ Windows::UI::Core::CoreCursorType::Arrow, 0 });
}
}
void EditorBaseControl::ImageTarget_PointerEntered(IInspectable const &sender, PointerRoutedEventArgs const &e)
{
_isPointerOver = true;
}
#endif
void EditorBaseControl::ImageTarget_PointerExited(IInspectable const &sender, PointerRoutedEventArgs const &e)
{
#ifndef WINUI3
_isPointerOver = false;
if (!_wrapper->HaveMouseCapture())
{
winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread().PointerCursor(Windows::UI::Core::CoreCursor{ Windows::UI::Core::CoreCursorType::Arrow, 0 });
}
#endif
_scintilla->PointerExited();
}
void EditorBaseControl::OnKeyDown(KeyRoutedEventArgs const &e)
{
__super::OnKeyDown(e);
const auto modifiers{ GetKeyModifiersForCurrentThread() };
auto handled = true;
_scintilla->KeyDown(e.Key(), modifiers, e.KeyStatus().IsExtendedKey, &handled); // Todo: Or use VirtualKey?
if (!handled
&& e.Key() == VirtualKey::F10 && (modifiers & VirtualKeyModifiers::Shift) == VirtualKeyModifiers::Shift
&& ShowContextMenuAtCurrentPosition())
{
handled = true;
}
e.Handled(handled);
}
void EditorBaseControl::OnKeyUp(KeyRoutedEventArgs const &e)
{
if (e.Key() == VirtualKey::Application)
{
e.Handled(ShowContextMenuAtCurrentPosition());
}
}
void EditorBaseControl::EditorBaseControl_CharacterReceived(DUX::UIElement const &sender, CharacterReceivedRoutedEventArgs const &e)
{
if (_isFocused)
{
_scintilla->CharacterReceived(e.Character());
e.Handled(true);
}
}
void EditorBaseControl::ImageTarget_SizeChanged(IInspectable const &sender, SizeChangedEventArgs const &args)
{
if (_vsisNative)
{
auto width{ ConvertFromDipToPixelUnit(args.NewSize().Width, _dpiScale) };
auto height{ ConvertFromDipToPixelUnit(args.NewSize().Height, _dpiScale) };
_wrapper->Width(width);
_wrapper->Height(height);
_vsisNative->Resize(width, height);
_scintilla->SizeChanged();
}
}
void EditorBaseControl::ImageTarget_PointerWheelChanged(IInspectable const &sender, PointerRoutedEventArgs const &e)
{
auto properties{ e.GetCurrentPoint(sender.as<UIElement>()).Properties() };
_scintilla->PointerWheelChanged(properties.MouseWheelDelta(), properties.IsHorizontalMouseWheel(), e.KeyModifiers());
}
void EditorBaseControl::ImageTarget_DragEnter(IInspectable const &sender, DragEventArgs const &e)
{
DataPackageOperation op;
_scintilla->DragEnter(e.DataView(), e.AllowedOperations(), e.Modifiers(), op);
e.AcceptedOperation(op);
e.DragUIOverride().IsContentVisible(false);
e.DragUIOverride().IsCaptionVisible(false);
}
void EditorBaseControl::ImageTarget_DragOver(IInspectable const &sender, DragEventArgs const &e)
{
auto point{ e.GetPosition(sender.as<UIElement>()) };
point.X *= _dpiScale;
point.Y *= _dpiScale;
DataPackageOperation op;
_scintilla->DragOver(point, e.AllowedOperations(), e.Modifiers(), op);
e.AcceptedOperation(op);
}
void EditorBaseControl::ImageTarget_DragLeave(IInspectable const &sender, DragEventArgs const &e)
{
_scintilla->DragLeave();
}
void EditorBaseControl::ImageTarget_Drop(IInspectable const &sender, DragEventArgs const &e)
{
auto point{ e.GetPosition(sender.as<UIElement>()) };
point.X *= _dpiScale;
point.Y *= _dpiScale;
DataPackageOperation op;
_scintilla->Drop(point, e.DataView(), e.AllowedOperations(), e.Modifiers(), op);
e.AcceptedOperation(op);
}
void EditorBaseControl::ImageTarget_DragStarting(UIElement const &sender, DragStartingEventArgs const &e)
{
e.AllowedOperations(DataPackageOperation::Copy | DataPackageOperation::Move);
e.Data().SetText(winrt::to_hstring(_scintilla->GetDragData()));
e.DragUI().SetContentFromDataPackage();
}
void EditorBaseControl::ImageTarget_ContextRequested(UIElement const &sender, ContextRequestedEventArgs const &e)
{
Point point;
if (e.TryGetPosition(sender, point))
{
e.Handled(ShowContextMenu(sender, point));
}
else if (const auto frameworkElement{ sender.try_as<FrameworkElement>() })
{
e.Handled(ShowContextMenuAtCurrentPosition());
}
}
void EditorBaseControl::ContextMenuItem_Click(Windows::Foundation::IInspectable const &sender, DUX::RoutedEventArgs const &e)
{
_scintilla->WndProc(static_cast<Scintilla::Message>(unbox_value<ScintillaMessage>(sender.as<FrameworkElement>().Tag())), 0, 0);
}
void EditorBaseControl::HorizontalScrollBar_Scroll(IInspectable const &sender, ScrollEventArgs const &e)
{
_scintilla->HorizontalScroll(static_cast<Scintilla::Internal::ScrollEventType>(e.ScrollEventType()), static_cast<int>(e.NewValue()));
}
void EditorBaseControl::VerticalScrollBar_Scroll(IInspectable const &sender, ScrollEventArgs const &e)
{
_scintilla->Scroll(static_cast<Scintilla::Internal::ScrollEventType>(e.ScrollEventType()), static_cast<int>(e.NewValue()));
}
LRESULT EditorBaseControl::WndProc(IInspectable const &tag, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_NOTIFY)
{
const auto data{ reinterpret_cast<Scintilla::NotificationData *>(lParam) };
const auto sender{ tag.as<EditorBaseControl>() };
sender->InternalNotifyMessageReceived(*sender, lParam); // CodeEditorControl should receive the notification before user subscriptions
sender->_notifyMessageReceived(*sender, lParam);
sender->_editorWrapper.as<implementation::Editor>()->ProcessEvent(data);
}
return 0;
}
event_token EditorBaseControl::DpiChanged(EventHandler<double> const &handler)
{
return _dpiChangedEvent.add(handler);
}
void EditorBaseControl::DpiChanged(event_token const &token) noexcept
{
_dpiChangedEvent.remove(token);
}
event_token EditorBaseControl::NotifyMessageReceived(EventHandler<int64_t> const &handler)
{
return _notifyMessageReceived.add(handler);
}
void EditorBaseControl::NotifyMessageReceived(event_token const &token) noexcept
{
_notifyMessageReceived.remove(token);
}
float EditorBaseControl::DpiScale()
{
return _dpiScale;
}
#ifndef WINUI3
void EditorBaseControl::Application_Suspending(IInspectable const &sender, SuspendingEventArgs const &args)
{
// Required or crashes on resume
// https://learn.microsoft.com/en-us/windows/uwp/gaming/directx-and-xaml-interop
// https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_3/nf-dxgi1_3-idxgidevice3-trim
// Todo: Should ClearResources get called too? https://github.com/microsoft/Win2D/blob/master/winrt/lib/drawing/CanvasDevice.cpp#L1040
_wrapper->TrimDxgiDevice();
}
#endif
}

View File

@ -1,121 +0,0 @@
#pragma once
#include "EditorBaseControl.g.h"
#include "ScintillaWin.h"
#include "ScintillaCall.h"
#include "Wrapper.h"
namespace winrt::WinUIEditor::implementation
{
struct EditorBaseControl : EditorBaseControlT<EditorBaseControl>
{
EditorBaseControl();
~EditorBaseControl();
WinUIEditor::Editor Editor();
std::shared_ptr<Scintilla::ScintillaCall> Call() noexcept { return _call; }
void OnApplyTemplate();
void OnGotFocus(DUX::RoutedEventArgs const &e);
void OnLostFocus(DUX::RoutedEventArgs const &e);
void OnKeyDown(DUX::Input::KeyRoutedEventArgs const &e);
void OnKeyUp(DUX::Input::KeyRoutedEventArgs const &e);
void OnPointerPressed(DUX::Input::PointerRoutedEventArgs const &e);
void OnPointerReleased(DUX::Input::PointerRoutedEventArgs const &e);
DUX::Automation::Peers::AutomationPeer OnCreateAutomationPeer();
Scintilla::sptr_t PublicWndProc(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam);
int64_t SendMessage(ScintillaMessage const &message, uint64_t wParam, int64_t lParam);
void StyleSetForeTransparent(int style, Scintilla::Internal::ColourRGBA color);
void StyleSetBackTransparent(int style, Scintilla::Internal::ColourRGBA color);
void InvalidateStyleRedraw();
void StyleClearCustom();
void SetFoldMarginColorTransparent(bool useSetting, Scintilla::Internal::ColourRGBA back);
void SetFoldMarginHiColorTransparent(bool useSetting, Scintilla::Internal::ColourRGBA fore);
event_token DpiChanged(Windows::Foundation::EventHandler<double> const &handler);
void DpiChanged(event_token const &token) noexcept;
event_token NotifyMessageReceived(Windows::Foundation::EventHandler<int64_t> const &handler);
void NotifyMessageReceived(event_token const &token) noexcept;
float DpiScale();
event<Windows::Foundation::EventHandler<int64_t>> InternalNotifyMessageReceived;
private:
#ifndef WINUI3
bool _hasFcu{ Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 5) }; // Todo: Make static
bool _hasXamlRoot{ Windows::Foundation::Metadata::ApiInformation::IsTypePresent(L"Windows.UI.Xaml.XamlRoot") }; // Todo: Make static
bool _hasIsLoaded{ Windows::Foundation::Metadata::ApiInformation::IsPropertyPresent(L"Windows.UI.Xaml.FrameworkElement", L"IsLoaded") }; // Todo: Make static
bool _isPointerOver{ false };
Windows::Graphics::Display::DisplayInformation _displayInformation{ nullptr };
bool _isLoaded{ false };
#endif
bool _isFocused{ false };
WinUIEditor::Editor _editorWrapper{ nullptr };
std::shared_ptr<Scintilla::ScintillaCall> _call{ nullptr };
com_ptr<::Scintilla::Internal::ScintillaWinUI> _scintilla{ nullptr };
float _dpiScale{ 0 };
event<Windows::Foundation::EventHandler<double>> _dpiChangedEvent;
event<Windows::Foundation::EventHandler<int64_t>> _notifyMessageReceived;
DUX::FrameworkElement::SizeChanged_revoker _imageTargetSizeChangedRevoker{};
void ImageTarget_SizeChanged(Windows::Foundation::IInspectable const &sender, DUX::SizeChangedEventArgs const &args);
DUX::UIElement::PointerMoved_revoker _imageTargetPointerMovedRevoker{};
void ImageTarget_PointerMoved(Windows::Foundation::IInspectable const &sender, DUX::Input::PointerRoutedEventArgs const &e);
#ifndef WINUI3
DUX::UIElement::PointerCaptureLost_revoker _imageTargetPointerCaptureLostRevoker{};
void ImageTarget_PointerCaptureLost(Windows::Foundation::IInspectable const &sender, DUX::Input::PointerRoutedEventArgs const &e);
DUX::UIElement::PointerEntered_revoker _imageTargetPointerEnteredRevoker{};
void ImageTarget_PointerEntered(Windows::Foundation::IInspectable const &sender, DUX::Input::PointerRoutedEventArgs const &e);
#endif
DUX::UIElement::PointerExited_revoker _imageTargetPointerExitedRevoker{};
void ImageTarget_PointerExited(Windows::Foundation::IInspectable const &sender, DUX::Input::PointerRoutedEventArgs const &e);
DUX::UIElement::PointerWheelChanged_revoker _imageTargetPointerWheelChangedRevoker{};
void ImageTarget_PointerWheelChanged(Windows::Foundation::IInspectable const &sender, DUX::Input::PointerRoutedEventArgs const &e);
DUX::UIElement::DragEnter_revoker _imageTargetDragEnterRevoker{};
void ImageTarget_DragEnter(Windows::Foundation::IInspectable const &sender, DUX::DragEventArgs const &e);
DUX::UIElement::DragOver_revoker _imageTargetDragOverRevoker{};
void ImageTarget_DragOver(Windows::Foundation::IInspectable const &sender, DUX::DragEventArgs const &e);
DUX::UIElement::DragLeave_revoker _imageTargetDragLeaveRevoker{};
void ImageTarget_DragLeave(Windows::Foundation::IInspectable const &sender, DUX::DragEventArgs const &e);
DUX::UIElement::Drop_revoker _imageTargetDropRevoker{};
void ImageTarget_Drop(Windows::Foundation::IInspectable const &sender, DUX::DragEventArgs const &e);
DUX::UIElement::DragStarting_revoker _imageTargetDragStartingRevoker{};
void ImageTarget_DragStarting(DUX::UIElement const &sender, DUX::DragStartingEventArgs const &e);
DUX::UIElement::ContextRequested_revoker _imageTargetContextRequestedRevoker{};
void ImageTarget_ContextRequested(DUX::UIElement const &sender, DUX::Input::ContextRequestedEventArgs const &e);
void ContextMenuItem_Click(Windows::Foundation::IInspectable const &sender, DUX::RoutedEventArgs const &e);
DUXC::Primitives::ScrollBar::Scroll_revoker _horizontalScrollBarScrollRevoker{};
void HorizontalScrollBar_Scroll(Windows::Foundation::IInspectable const &sender, DUX::Controls::Primitives::ScrollEventArgs const &e);
DUXC::Primitives::ScrollBar::Scroll_revoker _verticalScrollBarScrollRevoker{};
void VerticalScrollBar_Scroll(Windows::Foundation::IInspectable const &sender, DUX::Controls::Primitives::ScrollEventArgs const &e);
void EditorBaseControl_CharacterReceived(DUX::UIElement const &sender, DUX::Input::CharacterReceivedRoutedEventArgs const &args);
void OnLoaded(Windows::Foundation::IInspectable const &sender, DUX::RoutedEventArgs const &args);
void OnUnloaded(Windows::Foundation::IInspectable const &sender, DUX::RoutedEventArgs const &args);
bool IsLoadedCompat();
DUX::XamlRoot::Changed_revoker _xamlRootChangedRevoker{};
void XamlRoot_Changed(DUX::XamlRoot const &sender, DUX::XamlRootChangedEventArgs const &args);
void UpdateDpi(float dpiScale);
void AddContextMenuItems(DUX::Controls::MenuFlyout const &menu);
bool ShowContextMenu(DUX::UIElement const &targetElement, Windows::Foundation::Point const &point);
bool ShowContextMenuAtCurrentPosition();
winrt::com_ptr<::IVirtualSurfaceImageSourceNative> _vsisNative;
std::shared_ptr<::WinUIEditor::Wrapper> _wrapper{ nullptr };
static LRESULT WndProc(Windows::Foundation::IInspectable const &, UINT msg, WPARAM wParam, LPARAM lParam);
#ifndef WINUI3
Windows::Graphics::Display::DisplayInformation::DpiChanged_revoker _dpiChangedRevoker{};
void DisplayInformation_DpiChanged(Windows::Graphics::Display::DisplayInformation const &sender, Windows::Foundation::IInspectable const &args);
Windows::UI::Xaml::Application::Suspending_revoker _suspendingRevoker{};
void Application_Suspending(Windows::Foundation::IInspectable const &sender, Windows::ApplicationModel::SuspendingEventArgs const &args);
#endif
};
}
namespace winrt::WinUIEditor::factory_implementation
{
struct EditorBaseControl : EditorBaseControlT<EditorBaseControl, implementation::EditorBaseControl>
{
};
}

View File

@ -1,15 +0,0 @@
#include "Defines.idl"
import "EditorWrapper.idl";
import "IEditorAccess.idl";
namespace WinUIEditor
{
[default_interface]
[webhosthidden]
runtimeclass EditorBaseControl : DUX.Controls.Control, IEditorAccess
{
EditorBaseControl();
Editor Editor { get; };
event Windows.Foundation.EventHandler<Double> DpiChanged;
}
}

View File

@ -1,190 +0,0 @@
#include "pch.h"
#include "EditorBaseControlAutomationPeer.h"
#include "EditorBaseControlAutomationPeer.g.cpp"
#include "TextRangeProvider.h"
#include "Helpers.h"
#include "EditorBaseControl.h"
using namespace ::WinUIEditor;
using namespace winrt;
using namespace Windows::Foundation;
using namespace DUX::Automation;
using namespace DUX::Automation::Peers;
using namespace DUX::Automation::Provider;
using namespace DUX::Automation::Text;
namespace winrt::WinUIEditor::implementation
{
EditorBaseControlAutomationPeer::EditorBaseControlAutomationPeer(WinUIEditor::EditorBaseControl const &owner) : base_type(owner)
{
_updateUIRevoker = owner.Editor().UpdateUI(auto_revoke, { this, &EditorBaseControlAutomationPeer::Editor_UpdateUI });
}
void EditorBaseControlAutomationPeer::Editor_UpdateUI(Editor const &sender, UpdateUIEventArgs const &args)
{
// https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L133
// Todo: Maybe we should raise selection changed on Update::Content also
if (static_cast<int>(static_cast<Update>(args.Updated()) & Update::Selection))
{
this->RaiseAutomationEvent(AutomationEvents::TextPatternOnTextSelectionChanged);
}
}
hstring EditorBaseControlAutomationPeer::GetLocalizedControlTypeCore()
{
// Todo: Localize
// Todo: Make sure this is a good name
return L"code editor";
}
IInspectable EditorBaseControlAutomationPeer::GetPatternCore(PatternInterface const &patternInterface)
{
// Todo: Should we forward scroll elements? https://learn.microsoft.com/en-us/windows/apps/design/accessibility/custom-automation-peers#forwarding-patterns-from-sub-elements
switch (patternInterface)
{
case PatternInterface::TextEdit:
case PatternInterface::Text:
case PatternInterface::Text2:
case PatternInterface::Value:
return *this;
default:
return __super::GetPatternCore(patternInterface);
}
}
hstring EditorBaseControlAutomationPeer::GetClassNameCore()
{
return hstring{ name_of<WinUIEditor::EditorBaseControl>() };
}
AutomationControlType EditorBaseControlAutomationPeer::GetAutomationControlTypeCore()
{
return AutomationControlType::Edit;
}
ITextRangeProvider EditorBaseControlAutomationPeer::DocumentRange()
{
// Todo: Look at how WinUI 2 handles GetImpl in automation peers
const auto editor{ Owner().as<WinUIEditor::EditorBaseControl>().Editor() };
return make<TextRangeProvider>(ProviderFromPeer(*this), editor, 0, editor.Length(), GetBoundingRectangle());
}
SupportedTextSelection EditorBaseControlAutomationPeer::SupportedTextSelection()
{
const auto editor{ Owner().as<WinUIEditor::EditorBaseControl>().Editor() };
return editor.MultipleSelection() ? SupportedTextSelection::Multiple : SupportedTextSelection::Single;
}
com_array<ITextRangeProvider> EditorBaseControlAutomationPeer::GetSelection()
{
const auto editor{ Owner().as<WinUIEditor::EditorBaseControl>().Editor() };
const auto n{ static_cast<uint32_t>(editor.Selections()) };
com_array<ITextRangeProvider> arr(n, nullptr);
const auto topLeft{ GetBoundingRectangle() };
for (uint32_t i{ 0 }; i < n; i++)
{
const auto start{ editor.GetSelectionNStart(i) };
const auto end{ editor.GetSelectionNEnd(i) };
arr[i] = make<TextRangeProvider>(ProviderFromPeer(*this), editor, start, end, topLeft);
}
return arr; // Todo: Trying to retrieve the value of a selection n >= 1 crashes Accessibility Insights
}
com_array<ITextRangeProvider> EditorBaseControlAutomationPeer::GetVisibleRanges()
{
// Visual Studio implements this line by line
// Todo: Consider folding and line visible messages
// Todo: Not sure if this is the best method for top line
const auto editor{ Owner().as<WinUIEditor::EditorBaseControl>().Editor() };
const auto firstVisibleLine{ editor.FirstVisibleLine() };
const auto maxLine{ editor.LineCount() - 1 };
// Todo: LinesOnScreen has no concept of wrapping, so you could end up with many more lines than truly visibly
const auto lastVisibleLine{ std::min(maxLine, firstVisibleLine + editor.LinesOnScreen()) };
const auto count{ lastVisibleLine - firstVisibleLine + 1 };
com_array<ITextRangeProvider> arr(count, nullptr);
const auto topLeft{ GetBoundingRectangle() };
for (int64_t i{ 0 }; i < count; i++)
{
const auto line{ firstVisibleLine + i };
const auto start{ editor.PositionFromLine(line) };
const auto end{ editor.GetLineEndPosition(line) };
arr[i] = make<TextRangeProvider>(ProviderFromPeer(*this), editor, start, end, topLeft);
}
return arr;
}
ITextRangeProvider EditorBaseControlAutomationPeer::RangeFromChild(IRawElementProviderSimple const &childElement)
{
// Todo: Does this need to be implemented?
return nullptr;
}
ITextRangeProvider EditorBaseControlAutomationPeer::RangeFromPoint(Point const &screenLocation)
{
const auto rect{ GetBoundingRectangle() };
const Point point{
screenLocation.X - rect.X,
screenLocation.Y - rect.Y };
const auto editor{ Owner().as<WinUIEditor::EditorBaseControl>().Editor() };
const auto pos{ editor.PositionFromPoint(point.X, point.Y) };
const auto line{ editor.LineFromPosition(pos) };
const auto start{ editor.PositionFromLine(line) };
const auto end{ editor.GetLineEndPosition(line) };
return make<TextRangeProvider>(ProviderFromPeer(*this), editor, start, end, rect);
}
ITextRangeProvider EditorBaseControlAutomationPeer::GetActiveComposition()
{
// Todo: implement
throw hresult_not_implemented{};
}
ITextRangeProvider EditorBaseControlAutomationPeer::GetConversionTarget()
{
// Todo: implement
throw hresult_not_implemented{};
}
ITextRangeProvider EditorBaseControlAutomationPeer::RangeFromAnnotation(IRawElementProviderSimple const &annotationElement)
{
// Todo: implement
throw hresult_not_implemented{};
}
ITextRangeProvider EditorBaseControlAutomationPeer::GetCaretRange(bool &isActive)
{
const auto editor{ Owner().as<WinUIEditor::EditorBaseControl>().Editor() };
isActive = editor.Focus();
const auto pos{ editor.GetSelectionNCaret(editor.MainSelection()) };
return make<TextRangeProvider>(ProviderFromPeer(*this), editor, pos, pos, GetBoundingRectangle());
}
bool EditorBaseControlAutomationPeer::IsReadOnly()
{
const auto editor{ Owner().as<WinUIEditor::EditorBaseControl>().Editor() };
return editor.ReadOnly();
}
hstring EditorBaseControlAutomationPeer::Value()
{
const auto editor{ Owner().as<WinUIEditor::EditorBaseControl>().Editor() };
return editor.GetText(editor.Length()); // Todo: this could potentially be gigabytes of data, so provide a maximum safeguard
}
void EditorBaseControlAutomationPeer::SetValue(hstring const &value)
{
const auto editor{ Owner().as<WinUIEditor::EditorBaseControl>().Editor() };
editor.SetText(value);
}
}

View File

@ -1,43 +0,0 @@
#pragma once
#include "EditorBaseControlAutomationPeer.g.h"
namespace winrt::WinUIEditor::implementation
{
struct EditorBaseControlAutomationPeer : EditorBaseControlAutomationPeerT<EditorBaseControlAutomationPeer>
{
EditorBaseControlAutomationPeer(WinUIEditor::EditorBaseControl const &owner);
hstring GetLocalizedControlTypeCore();
Windows::Foundation::IInspectable GetPatternCore(DUX::Automation::Peers::PatternInterface const &patternInterface);
hstring GetClassNameCore();
DUX::Automation::Peers::AutomationControlType GetAutomationControlTypeCore();
DUX::Automation::Provider::ITextRangeProvider DocumentRange();
DUX::Automation::SupportedTextSelection SupportedTextSelection();
com_array<DUX::Automation::Provider::ITextRangeProvider> GetSelection();
com_array<DUX::Automation::Provider::ITextRangeProvider> GetVisibleRanges();
DUX::Automation::Provider::ITextRangeProvider RangeFromChild(DUX::Automation::Provider::IRawElementProviderSimple const &childElement);
DUX::Automation::Provider::ITextRangeProvider RangeFromPoint(Windows::Foundation::Point const &screenLocation);
DUX::Automation::Provider::ITextRangeProvider GetActiveComposition();
DUX::Automation::Provider::ITextRangeProvider GetConversionTarget();
DUX::Automation::Provider::ITextRangeProvider RangeFromAnnotation(DUX::Automation::Provider::IRawElementProviderSimple const &annotationElement);
DUX::Automation::Provider::ITextRangeProvider GetCaretRange(bool &isActive);
bool IsReadOnly();
hstring Value();
void SetValue(hstring const &value);
private:
WinUIEditor::Editor::UpdateUI_revoker _updateUIRevoker{};
void Editor_UpdateUI(WinUIEditor::Editor const &sender, WinUIEditor::UpdateUIEventArgs const &args);
};
}
namespace winrt::WinUIEditor::factory_implementation
{
struct EditorBaseControlAutomationPeer : EditorBaseControlAutomationPeerT<EditorBaseControlAutomationPeer, implementation::EditorBaseControlAutomationPeer>
{
};
}

View File

@ -1,15 +0,0 @@
#include "Defines.idl"
import "EditorBaseControl.idl";
namespace WinUIEditor
{
[default_interface]
[webhosthidden]
runtimeclass EditorBaseControlAutomationPeer : DUX.Automation.Peers.FrameworkElementAutomationPeer,
DUX.Automation.Provider.ITextEditProvider,
DUX.Automation.Provider.ITextProvider2,
DUX.Automation.Provider.IValueProvider
{
EditorBaseControlAutomationPeer(EditorBaseControl owner);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,81 +0,0 @@
#include "pch.h"
#include "Helpers.h"
namespace WinUIEditor
{
// Derived from https://github.com/microsoft/Windows-universal-samples/blob/main/Samples/ComplexInk/cpp/Common/DeviceResources.h
int ConvertFromDipToPixelUnit(float val, float dpiAdjustmentRatio, bool rounded)
{
float pixelVal = val * dpiAdjustmentRatio;
return static_cast<int>(rounded ? floorf(pixelVal + 0.5f) : pixelVal); // Todo: Test if this is ever necessary
}
typedef LONG(WINAPI *AppPolicyGetWindowingModelPtr)(HANDLE processToken, AppPolicyWindowingModel *policy);
static AppPolicyGetWindowingModelPtr s_appPolicyGetWindowingModel;
bool IsClassicWindow()
{
// To avoid issues with AppPolicyGetWindowingModel and Store certification, this method cannot be called normally
// See https://github.com/microsoft/react-native-windows/pull/5369 (though OneCoreUAP_apiset.lib did not pass either)
if (!s_appPolicyGetWindowingModel)
{
s_appPolicyGetWindowingModel =
reinterpret_cast<AppPolicyGetWindowingModelPtr>(GetProcAddress(GetModuleHandleW(L"Api-ms-win-appmodel-runtime-l1-1-2.dll"), "AppPolicyGetWindowingModel"));
}
AppPolicyWindowingModel model;
return !(s_appPolicyGetWindowingModel && SUCCEEDED(s_appPolicyGetWindowingModel(GetCurrentThreadEffectiveToken(), &model)))
|| model != AppPolicyWindowingModel_Universal;
}
winrt::Windows::System::VirtualKeyModifiers GetKeyModifiersForCurrentThread()
{
auto modifiers{ winrt::Windows::System::VirtualKeyModifiers::None };
#ifdef WINUI3
// Todo: Do we need to check Locked?
// Todo: Left vs right keys?
// does not help us
if ((winrt::Microsoft::UI::Input::InputKeyboardSource::GetKeyStateForCurrentThread(winrt::Windows::System::VirtualKey::Shift) & winrt::Windows::UI::Core::CoreVirtualKeyStates::Down) == winrt::Windows::UI::Core::CoreVirtualKeyStates::Down)
{
modifiers |= winrt::Windows::System::VirtualKeyModifiers::Shift;
}
if ((winrt::Microsoft::UI::Input::InputKeyboardSource::GetKeyStateForCurrentThread(winrt::Windows::System::VirtualKey::Control) & winrt::Windows::UI::Core::CoreVirtualKeyStates::Down) == winrt::Windows::UI::Core::CoreVirtualKeyStates::Down)
{
modifiers |= winrt::Windows::System::VirtualKeyModifiers::Control;
}
if ((winrt::Microsoft::UI::Input::InputKeyboardSource::GetKeyStateForCurrentThread(winrt::Windows::System::VirtualKey::Menu) & winrt::Windows::UI::Core::CoreVirtualKeyStates::Down) == winrt::Windows::UI::Core::CoreVirtualKeyStates::Down)
{
modifiers |= winrt::Windows::System::VirtualKeyModifiers::Menu; // Todo: KeyStatus.IsMenuKeyDown?
}
if ((winrt::Microsoft::UI::Input::InputKeyboardSource::GetKeyStateForCurrentThread(winrt::Windows::System::VirtualKey::LeftWindows) & winrt::Windows::UI::Core::CoreVirtualKeyStates::Down) == winrt::Windows::UI::Core::CoreVirtualKeyStates::Down
|| (winrt::Microsoft::UI::Input::InputKeyboardSource::GetKeyStateForCurrentThread(winrt::Windows::System::VirtualKey::RightWindows) & winrt::Windows::UI::Core::CoreVirtualKeyStates::Down) == winrt::Windows::UI::Core::CoreVirtualKeyStates::Down)
{
modifiers |= winrt::Windows::System::VirtualKeyModifiers::Windows;
}
#else
const auto window{ winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread() }; // Todo: is it worth it to store this?
// Todo: Do we need to check Locked?
// Todo: Left vs right keys?
if ((window.GetKeyState(winrt::Windows::System::VirtualKey::Shift) & winrt::Windows::UI::Core::CoreVirtualKeyStates::Down) == winrt::Windows::UI::Core::CoreVirtualKeyStates::Down)
{
modifiers |= winrt::Windows::System::VirtualKeyModifiers::Shift;
}
if ((window.GetKeyState(winrt::Windows::System::VirtualKey::Control) & winrt::Windows::UI::Core::CoreVirtualKeyStates::Down) == winrt::Windows::UI::Core::CoreVirtualKeyStates::Down)
{
modifiers |= winrt::Windows::System::VirtualKeyModifiers::Control;
}
if ((window.GetKeyState(winrt::Windows::System::VirtualKey::Menu) & winrt::Windows::UI::Core::CoreVirtualKeyStates::Down) == winrt::Windows::UI::Core::CoreVirtualKeyStates::Down)
{
modifiers |= winrt::Windows::System::VirtualKeyModifiers::Menu; // Todo: KeyStatus.IsMenuKeyDown?
}
if ((window.GetKeyState(winrt::Windows::System::VirtualKey::LeftWindows) & winrt::Windows::UI::Core::CoreVirtualKeyStates::Down) == winrt::Windows::UI::Core::CoreVirtualKeyStates::Down
|| (window.GetKeyState(winrt::Windows::System::VirtualKey::RightWindows) & winrt::Windows::UI::Core::CoreVirtualKeyStates::Down) == winrt::Windows::UI::Core::CoreVirtualKeyStates::Down)
{
modifiers |= winrt::Windows::System::VirtualKeyModifiers::Windows;
}
#endif
return modifiers;
}
}

View File

@ -1,8 +0,0 @@
#pragma once
namespace WinUIEditor
{
int ConvertFromDipToPixelUnit(float val, float dpiAdjustmentRatio, bool rounded = true);
bool IsClassicWindow();
winrt::Windows::System::VirtualKeyModifiers GetKeyModifiersForCurrentThread();
}

View File

@ -1,10 +0,0 @@
import "EditorWrapper.idl";
namespace WinUIEditor
{
interface IEditorAccess
{
Int64 SendMessage(ScintillaMessage message, UInt64 wParam, Int64 lParam);
event Windows.Foundation.EventHandler<Int64> NotifyMessageReceived;
}
}

View File

@ -1,225 +0,0 @@
// Ported from
// https://github.com/microsoft/vscode/blob/main/extensions/theme-defaults/themes/light_plus.json
// https://github.com/microsoft/vscode/blob/main/extensions/theme-defaults/themes/light_vs.json
// under the following license
/*
MIT License
Copyright (c) 2015 - present Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
namespace WinUIEditor
{
constexpr int LightPlusEditorForeground{ IntRGBA(0x00, 0x00, 0x00) };
constexpr int LightPlus(Scope scope)
{
switch (scope)
{
case Scope::MetaEmbedded: return IntRGBA(0x00, 0x00, 0x00);
case Scope::SourceGroovyEmbedded: return IntRGBA(0x00, 0x00, 0x00);
case Scope::String__MetaImageInlineMarkdown: return IntRGBA(0x00, 0x00, 0x00);
case Scope::VariableLegacyBuiltinPython: return IntRGBA(0x00, 0x00, 0x00);
case Scope::MetaDiffHeader: return IntRGBA(0x00, 0x00, 0x80);
case Scope::Comment: return IntRGBA(0x00, 0x80, 0x00);
case Scope::ConstantLanguage: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::ConstantNumeric: return IntRGBA(0x09, 0x86, 0x58);
case Scope::VariableOtherEnummember: return IntRGBA(0x00, 0x70, 0xC1);
case Scope::KeywordOperatorPlusExponent: return IntRGBA(0x09, 0x86, 0x58);
case Scope::KeywordOperatorMinusExponent: return IntRGBA(0x09, 0x86, 0x58);
case Scope::ConstantRegexp: return IntRGBA(0x81, 0x1F, 0x3F);
case Scope::EntityNameTag: return IntRGBA(0x80, 0x00, 0x00);
case Scope::EntityNameSelector: return IntRGBA(0x80, 0x00, 0x00);
case Scope::EntityOtherAttribute_Name: return IntRGBA(0xE5, 0x00, 0x00);
case Scope::EntityOtherAttribute_NameClassCss: return IntRGBA(0x80, 0x00, 0x00);
case Scope::EntityOtherAttribute_NameClassMixinCss: return IntRGBA(0x80, 0x00, 0x00);
case Scope::EntityOtherAttribute_NameIdCss: return IntRGBA(0x80, 0x00, 0x00);
case Scope::EntityOtherAttribute_NameParent_SelectorCss: return IntRGBA(0x80, 0x00, 0x00);
case Scope::EntityOtherAttribute_NamePseudo_ClassCss: return IntRGBA(0x80, 0x00, 0x00);
case Scope::EntityOtherAttribute_NamePseudo_ElementCss: return IntRGBA(0x80, 0x00, 0x00);
case Scope::SourceCssLess__EntityOtherAttribute_NameId: return IntRGBA(0x80, 0x00, 0x00);
case Scope::EntityOtherAttribute_NameScss: return IntRGBA(0x80, 0x00, 0x00);
case Scope::Invalid: return IntRGBA(0xCD, 0x31, 0x31);
case Scope::MarkupBold: return IntRGBA(0x00, 0x00, 0x80);
case Scope::MarkupHeading: return IntRGBA(0x80, 0x00, 0x00);
case Scope::MarkupInserted: return IntRGBA(0x09, 0x86, 0x58);
case Scope::MarkupDeleted: return IntRGBA(0xA3, 0x15, 0x15);
case Scope::MarkupChanged: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::PunctuationDefinitionQuoteBeginMarkdown: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::PunctuationDefinitionListBeginMarkdown: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::MarkupInlineRaw: return IntRGBA(0x80, 0x00, 0x00);
case Scope::PunctuationDefinitionTag: return IntRGBA(0x80, 0x00, 0x00);
case Scope::MetaPreprocessor: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::EntityNameFunctionPreprocessor: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::MetaPreprocessorString: return IntRGBA(0xA3, 0x15, 0x15);
case Scope::MetaPreprocessorNumeric: return IntRGBA(0x09, 0x86, 0x58);
case Scope::MetaStructureDictionaryKeyPython: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::Storage: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StorageType: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StorageModifier: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordOperatorNoexcept: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::String: return IntRGBA(0xA3, 0x15, 0x15);
case Scope::MetaEmbeddedAssembly: return IntRGBA(0xA3, 0x15, 0x15);
case Scope::StringCommentBufferedBlockPug: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringQuotedPug: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringInterpolatedPug: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringUnquotedPlainInYaml: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringUnquotedPlainOutYaml: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringUnquotedBlockYaml: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringQuotedSingleYaml: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringQuotedDoubleXml: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringQuotedSingleXml: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringUnquotedCdataXml: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringQuotedDoubleHtml: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringQuotedSingleHtml: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringUnquotedHtml: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringQuotedSingleHandlebars: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringQuotedDoubleHandlebars: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::StringRegexp: return IntRGBA(0x81, 0x1F, 0x3F);
case Scope::PunctuationDefinitionTemplate_ExpressionBegin: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::PunctuationDefinitionTemplate_ExpressionEnd: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::PunctuationSectionEmbedded: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::MetaTemplateExpression: return IntRGBA(0x00, 0x00, 0x00);
case Scope::SupportConstantProperty_Value: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::SupportConstantFont_Name: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::SupportConstantMedia_Type: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::SupportConstantMedia: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::ConstantOtherColorRgb_Value: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::ConstantOtherRgb_Value: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::SupportConstantColor: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::SupportTypeVendoredProperty_Name: return IntRGBA(0xE5, 0x00, 0x00);
case Scope::SupportTypeProperty_Name: return IntRGBA(0xE5, 0x00, 0x00);
case Scope::VariableCss: return IntRGBA(0xE5, 0x00, 0x00);
case Scope::VariableScss: return IntRGBA(0xE5, 0x00, 0x00);
case Scope::VariableOtherLess: return IntRGBA(0xE5, 0x00, 0x00);
case Scope::SourceCoffeeEmbedded: return IntRGBA(0xE5, 0x00, 0x00);
case Scope::SupportTypeProperty_NameJson: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::Keyword: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordControl: return IntRGBA(0xAF, 0x00, 0xDB);
case Scope::KeywordOperator: return IntRGBA(0x00, 0x00, 0x00);
case Scope::KeywordOperatorNew: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordOperatorExpression: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordOperatorCast: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordOperatorSizeof: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordOperatorAlignof: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordOperatorTypeid: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordOperatorAlignas: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordOperatorInstanceof: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordOperatorLogicalPython: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordOperatorWordlike: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::KeywordOtherUnit: return IntRGBA(0x09, 0x86, 0x58);
case Scope::PunctuationSectionEmbeddedBeginPhp: return IntRGBA(0x80, 0x00, 0x00);
case Scope::PunctuationSectionEmbeddedEndPhp: return IntRGBA(0x80, 0x00, 0x00);
case Scope::SupportFunctionGit_Rebase: return IntRGBA(0x04, 0x51, 0xA5);
case Scope::ConstantShaGit_Rebase: return IntRGBA(0x09, 0x86, 0x58);
case Scope::StorageModifierImportJava: return IntRGBA(0x00, 0x00, 0x00);
case Scope::VariableLanguageWildcardJava: return IntRGBA(0x00, 0x00, 0x00);
case Scope::StorageModifierPackageJava: return IntRGBA(0x00, 0x00, 0x00);
case Scope::VariableLanguage: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::EntityNameFunction: return IntRGBA(0x79, 0x5E, 0x26);
case Scope::SupportFunction: return IntRGBA(0x79, 0x5E, 0x26);
case Scope::SupportConstantHandlebars: return IntRGBA(0x79, 0x5E, 0x26);
case Scope::SourcePowershell__VariableOtherMember: return IntRGBA(0x79, 0x5E, 0x26);
case Scope::EntityNameOperatorCustom_Literal: return IntRGBA(0x79, 0x5E, 0x26);
case Scope::SupportClass: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::SupportType: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::EntityNameType: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::EntityNameNamespace: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::EntityOtherAttribute: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::EntityNameScope_Resolution: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::EntityNameClass: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeNumericGo: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeByteGo: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeBooleanGo: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeStringGo: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeUintptrGo: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeErrorGo: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeRuneGo: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeCs: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeGenericCs: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeModifierCs: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeVariableCs: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeAnnotationJava: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeGenericJava: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeJava: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeObjectArrayJava: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypePrimitiveArrayJava: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypePrimitiveJava: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeTokenJava: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeGroovy: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeAnnotationGroovy: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeParametersGroovy: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeGenericGroovy: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypeObjectArrayGroovy: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypePrimitiveArrayGroovy: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::StorageTypePrimitiveGroovy: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::MetaTypeCastExpr: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::MetaTypeNewExpr: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::SupportConstantMath: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::SupportConstantDom: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::SupportConstantJson: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::EntityOtherInherited_Class: return IntRGBA(0x26, 0x7F, 0x99);
case Scope::SourceCpp__KeywordOperatorNew: return IntRGBA(0xAF, 0x00, 0xDB);
case Scope::SourceCpp__KeywordOperatorDelete: return IntRGBA(0xAF, 0x00, 0xDB);
case Scope::KeywordOtherUsing: return IntRGBA(0xAF, 0x00, 0xDB);
case Scope::KeywordOtherDirectiveUsing: return IntRGBA(0xAF, 0x00, 0xDB);
case Scope::KeywordOtherOperator: return IntRGBA(0xAF, 0x00, 0xDB);
case Scope::EntityNameOperator: return IntRGBA(0xAF, 0x00, 0xDB);
case Scope::Variable: return IntRGBA(0x00, 0x10, 0x80);
case Scope::MetaDefinitionVariableName: return IntRGBA(0x00, 0x10, 0x80);
case Scope::SupportVariable: return IntRGBA(0x00, 0x10, 0x80);
case Scope::EntityNameVariable: return IntRGBA(0x00, 0x10, 0x80);
case Scope::ConstantOtherPlaceholder: return IntRGBA(0x00, 0x10, 0x80);
case Scope::VariableOtherConstant: return IntRGBA(0x00, 0x70, 0xC1);
case Scope::MetaObject_LiteralKey: return IntRGBA(0x00, 0x10, 0x80);
case Scope::PunctuationDefinitionGroupRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::PunctuationDefinitionGroupAssertionRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::PunctuationDefinitionCharacter_ClassRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::PunctuationCharacterSetBeginRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::PunctuationCharacterSetEndRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::KeywordOperatorNegationRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::SupportOtherParenthesisRegexp: return IntRGBA(0xD1, 0x69, 0x69);
case Scope::ConstantCharacterCharacter_ClassRegexp: return IntRGBA(0x81, 0x1F, 0x3F);
case Scope::ConstantOtherCharacter_ClassSetRegexp: return IntRGBA(0x81, 0x1F, 0x3F);
case Scope::ConstantOtherCharacter_ClassRegexp: return IntRGBA(0x81, 0x1F, 0x3F);
case Scope::ConstantCharacterSetRegexp: return IntRGBA(0x81, 0x1F, 0x3F);
case Scope::KeywordOperatorQuantifierRegexp: return IntRGBA(0x00, 0x00, 0x00);
case Scope::KeywordOperatorOrRegexp: return IntRGBA(0xEE, 0x00, 0x00);
case Scope::KeywordControlAnchorRegexp: return IntRGBA(0xEE, 0x00, 0x00);
case Scope::ConstantCharacter: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::ConstantOtherOption: return IntRGBA(0x00, 0x00, 0xFF);
case Scope::ConstantCharacterEscape: return IntRGBA(0xEE, 0x00, 0x00);
case Scope::EntityNameLabel: return IntRGBA(0x00, 0x00, 0x00);
}
}
constexpr int LightPlus2(Scope scope)
{
switch (scope)
{
case Scope::MetaPreprocessor: return IntRGBA(0x80, 0x80, 0x80);
default: return LightPlus(scope);
}
}
}

View File

@ -1,215 +0,0 @@
// Ported from
// https://github.com/microsoft/vscode/blob/main/extensions/theme-defaults/themes/light_plus.json
// https://github.com/microsoft/vscode/blob/main/extensions/theme-defaults/themes/light_vs.json
// https://github.com/microsoft/vscode/blob/main/extensions/theme-defaults/themes/dark_plus.json
// https://github.com/microsoft/vscode/blob/main/extensions/theme-defaults/themes/dark_vs.json
// under the following license
/*
MIT License
Copyright (c) 2015 - present Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
enum class Scope
{
MetaEmbedded, // meta.embedded
SourceGroovyEmbedded, // source.groovy.embedded
String__MetaImageInlineMarkdown, // string meta.image.inline.markdown
VariableLegacyBuiltinPython, // variable.legacy.builtin.python
MetaDiffHeader, // meta.diff.header
Comment, // comment
ConstantLanguage, // constant.language
ConstantNumeric, // constant.numeric
VariableOtherEnummember, // variable.other.enummember
KeywordOperatorPlusExponent, // keyword.operator.plus.exponent
KeywordOperatorMinusExponent, // keyword.operator.minus.exponent
ConstantRegexp, // constant.regexp
EntityNameTag, // entity.name.tag
EntityNameSelector, // entity.name.selector
EntityOtherAttribute_Name, // entity.other.attribute-name
EntityOtherAttribute_NameClassCss, // entity.other.attribute-name.class.css
EntityOtherAttribute_NameClassMixinCss, // entity.other.attribute-name.class.mixin.css
EntityOtherAttribute_NameIdCss, // entity.other.attribute-name.id.css
EntityOtherAttribute_NameParent_SelectorCss, // entity.other.attribute-name.parent-selector.css
EntityOtherAttribute_NamePseudo_ClassCss, // entity.other.attribute-name.pseudo-class.css
EntityOtherAttribute_NamePseudo_ElementCss, // entity.other.attribute-name.pseudo-element.css
SourceCssLess__EntityOtherAttribute_NameId, // source.css.less entity.other.attribute-name.id
EntityOtherAttribute_NameScss, // entity.other.attribute-name.scss
Invalid, // invalid
MarkupBold, // markup.bold
MarkupHeading, // markup.heading
MarkupInserted, // markup.inserted
MarkupDeleted, // markup.deleted
MarkupChanged, // markup.changed
PunctuationDefinitionQuoteBeginMarkdown, // punctuation.definition.quote.begin.markdown
PunctuationDefinitionListBeginMarkdown, // punctuation.definition.list.begin.markdown
MarkupInlineRaw, // markup.inline.raw
PunctuationDefinitionTag, // punctuation.definition.tag
MetaPreprocessor, // meta.preprocessor
EntityNameFunctionPreprocessor, // entity.name.function.preprocessor
MetaPreprocessorString, // meta.preprocessor.string
MetaPreprocessorNumeric, // meta.preprocessor.numeric
MetaStructureDictionaryKeyPython, // meta.structure.dictionary.key.python
Storage, // storage
StorageType, // storage.type
StorageModifier, // storage.modifier
KeywordOperatorNoexcept, // keyword.operator.noexcept
String, // string
MetaEmbeddedAssembly, // meta.embedded.assembly
StringCommentBufferedBlockPug, // string.comment.buffered.block.pug
StringQuotedPug, // string.quoted.pug
StringInterpolatedPug, // string.interpolated.pug
StringUnquotedPlainInYaml, // string.unquoted.plain.in.yaml
StringUnquotedPlainOutYaml, // string.unquoted.plain.out.yaml
StringUnquotedBlockYaml, // string.unquoted.block.yaml
StringQuotedSingleYaml, // string.quoted.single.yaml
StringQuotedDoubleXml, // string.quoted.double.xml
StringQuotedSingleXml, // string.quoted.single.xml
StringUnquotedCdataXml, // string.unquoted.cdata.xml
StringQuotedDoubleHtml, // string.quoted.double.html
StringQuotedSingleHtml, // string.quoted.single.html
StringUnquotedHtml, // string.unquoted.html
StringQuotedSingleHandlebars, // string.quoted.single.handlebars
StringQuotedDoubleHandlebars, // string.quoted.double.handlebars
StringRegexp, // string.regexp
PunctuationDefinitionTemplate_ExpressionBegin, // punctuation.definition.template-expression.begin
PunctuationDefinitionTemplate_ExpressionEnd, // punctuation.definition.template-expression.end
PunctuationSectionEmbedded, // punctuation.section.embedded
MetaTemplateExpression, // meta.template.expression
SupportConstantProperty_Value, // support.constant.property-value
SupportConstantFont_Name, // support.constant.font-name
SupportConstantMedia_Type, // support.constant.media-type
SupportConstantMedia, // support.constant.media
ConstantOtherColorRgb_Value, // constant.other.color.rgb-value
ConstantOtherRgb_Value, // constant.other.rgb-value
SupportConstantColor, // support.constant.color
SupportTypeVendoredProperty_Name, // support.type.vendored.property-name
SupportTypeProperty_Name, // support.type.property-name
VariableCss, // variable.css
VariableScss, // variable.scss
VariableOtherLess, // variable.other.less
SourceCoffeeEmbedded, // source.coffee.embedded
SupportTypeProperty_NameJson, // support.type.property-name.json
Keyword, // keyword
KeywordControl, // keyword.control
KeywordOperator, // keyword.operator
KeywordOperatorNew, // keyword.operator.new
KeywordOperatorExpression, // keyword.operator.expression
KeywordOperatorCast, // keyword.operator.cast
KeywordOperatorSizeof, // keyword.operator.sizeof
KeywordOperatorAlignof, // keyword.operator.alignof
KeywordOperatorTypeid, // keyword.operator.typeid
KeywordOperatorAlignas, // keyword.operator.alignas
KeywordOperatorInstanceof, // keyword.operator.instanceof
KeywordOperatorLogicalPython, // keyword.operator.logical.python
KeywordOperatorWordlike, // keyword.operator.wordlike
KeywordOtherUnit, // keyword.other.unit
PunctuationSectionEmbeddedBeginPhp, // punctuation.section.embedded.begin.php
PunctuationSectionEmbeddedEndPhp, // punctuation.section.embedded.end.php
SupportFunctionGit_Rebase, // support.function.git-rebase
ConstantShaGit_Rebase, // constant.sha.git-rebase
StorageModifierImportJava, // storage.modifier.import.java
VariableLanguageWildcardJava, // variable.language.wildcard.java
StorageModifierPackageJava, // storage.modifier.package.java
VariableLanguage, // variable.language
EntityNameFunction, // entity.name.function
SupportFunction, // support.function
SupportConstantHandlebars, // support.constant.handlebars
SourcePowershell__VariableOtherMember, // source.powershell variable.other.member
EntityNameOperatorCustom_Literal, // entity.name.operator.custom-literal
SupportClass, // support.class
SupportType, // support.type
EntityNameType, // entity.name.type
EntityNameNamespace, // entity.name.namespace
EntityOtherAttribute, // entity.other.attribute
EntityNameScope_Resolution, // entity.name.scope-resolution
EntityNameClass, // entity.name.class
StorageTypeNumericGo, // storage.type.numeric.go
StorageTypeByteGo, // storage.type.byte.go
StorageTypeBooleanGo, // storage.type.boolean.go
StorageTypeStringGo, // storage.type.string.go
StorageTypeUintptrGo, // storage.type.uintptr.go
StorageTypeErrorGo, // storage.type.error.go
StorageTypeRuneGo, // storage.type.rune.go
StorageTypeCs, // storage.type.cs
StorageTypeGenericCs, // storage.type.generic.cs
StorageTypeModifierCs, // storage.type.modifier.cs
StorageTypeVariableCs, // storage.type.variable.cs
StorageTypeAnnotationJava, // storage.type.annotation.java
StorageTypeGenericJava, // storage.type.generic.java
StorageTypeJava, // storage.type.java
StorageTypeObjectArrayJava, // storage.type.object.array.java
StorageTypePrimitiveArrayJava, // storage.type.primitive.array.java
StorageTypePrimitiveJava, // storage.type.primitive.java
StorageTypeTokenJava, // storage.type.token.java
StorageTypeGroovy, // storage.type.groovy
StorageTypeAnnotationGroovy, // storage.type.annotation.groovy
StorageTypeParametersGroovy, // storage.type.parameters.groovy
StorageTypeGenericGroovy, // storage.type.generic.groovy
StorageTypeObjectArrayGroovy, // storage.type.object.array.groovy
StorageTypePrimitiveArrayGroovy, // storage.type.primitive.array.groovy
StorageTypePrimitiveGroovy, // storage.type.primitive.groovy
MetaTypeCastExpr, // meta.type.cast.expr
MetaTypeNewExpr, // meta.type.new.expr
SupportConstantMath, // support.constant.math
SupportConstantDom, // support.constant.dom
SupportConstantJson, // support.constant.json
EntityOtherInherited_Class, // entity.other.inherited-class
SourceCpp__KeywordOperatorNew, // source.cpp keyword.operator.new
SourceCpp__KeywordOperatorDelete, // source.cpp keyword.operator.delete
KeywordOtherUsing, // keyword.other.using
KeywordOtherDirectiveUsing, // keyword.other.directive.using
KeywordOtherOperator, // keyword.other.operator
EntityNameOperator, // entity.name.operator
Variable, // variable
MetaDefinitionVariableName, // meta.definition.variable.name
SupportVariable, // support.variable
EntityNameVariable, // entity.name.variable
ConstantOtherPlaceholder, // constant.other.placeholder
VariableOtherConstant, // variable.other.constant
MetaObject_LiteralKey, // meta.object-literal.key
PunctuationDefinitionGroupRegexp, // punctuation.definition.group.regexp
PunctuationDefinitionGroupAssertionRegexp, // punctuation.definition.group.assertion.regexp
PunctuationDefinitionCharacter_ClassRegexp, // punctuation.definition.character-class.regexp
PunctuationCharacterSetBeginRegexp, // punctuation.character.set.begin.regexp
PunctuationCharacterSetEndRegexp, // punctuation.character.set.end.regexp
KeywordOperatorNegationRegexp, // keyword.operator.negation.regexp
SupportOtherParenthesisRegexp, // support.other.parenthesis.regexp
ConstantCharacterCharacter_ClassRegexp, // constant.character.character-class.regexp
ConstantOtherCharacter_ClassSetRegexp, // constant.other.character-class.set.regexp
ConstantOtherCharacter_ClassRegexp, // constant.other.character-class.regexp
ConstantCharacterSetRegexp, // constant.character.set.regexp
KeywordOperatorQuantifierRegexp, // keyword.operator.quantifier.regexp
KeywordOperatorOrRegexp, // keyword.operator.or.regexp
KeywordControlAnchorRegexp, // keyword.control.anchor.regexp
ConstantCharacter, // constant.character
ConstantOtherOption, // constant.other.option
ConstantCharacterEscape, // constant.character.escape
EntityNameLabel, // entity.name.label
Header, // header
EntityNameTagCss, // entity.name.tag.css
StringTag, // string.tag
StringValue, // string.value
KeywordOperatorDelete, // keyword.operator.delete
};

View File

@ -1,334 +0,0 @@
#include "pch.h"
#include "TextRangeProvider.h"
using namespace winrt;
using namespace Windows::Foundation;
using namespace DUX;
using namespace DUX::Automation;
using namespace DUX::Automation::Peers;
using namespace DUX::Automation::Provider;
using namespace DUX::Automation::Text;
constexpr hresult XAML_E_NOT_SUPPORTED{ static_cast<int32_t>(0x80131515) };
namespace winrt::WinUIEditor::implementation
{
TextRangeProvider::TextRangeProvider(IRawElementProviderSimple const &peer, Editor const &editor, int64_t rangeStart, int64_t rangeEnd, Rect const &bounds)
: _peer{ peer }, _editor{ editor }, _rangeStart{ rangeStart }, _rangeEnd{ rangeEnd }, _bounds{ bounds }
{
}
ITextRangeProvider TextRangeProvider::Clone()
{
return make<TextRangeProvider>(_peer, _editor.get(), _rangeStart, _rangeEnd, _bounds);
}
bool TextRangeProvider::Compare(ITextRangeProvider const &textRangeProvider)
{
const auto target{ textRangeProvider.as<TextRangeProvider>() };
return _rangeStart == target->_rangeStart && _rangeEnd == target->_rangeEnd;
}
int32_t TextRangeProvider::CompareEndpoints(TextPatternRangeEndpoint const &endpoint, ITextRangeProvider const &textRangeProvider, TextPatternRangeEndpoint const &targetEndpoint)
{
const auto target{ textRangeProvider.as<TextRangeProvider>() };
const auto thisEnd{ endpoint == TextPatternRangeEndpoint::Start ? _rangeStart : _rangeEnd };
const auto targetEnd{ targetEndpoint == TextPatternRangeEndpoint::Start ? target->_rangeStart : target->_rangeEnd };
return thisEnd - targetEnd;
}
void TextRangeProvider::ExpandToEnclosingUnit(TextUnit const &unit)
{
const auto editor{ _editor.get() };
if (!editor)
{
throw hresult_error{ E_POINTER };
}
if (unit == TextUnit::Document)
{
_rangeStart = 0;
_rangeEnd = editor.Length();
}
else if (unit == TextUnit::Line || unit == TextUnit::Paragraph)
{
const auto line{ editor.LineFromPosition(_rangeStart) };
_rangeStart = editor.PositionFromLine(line);
_rangeEnd = editor.GetLineEndPosition(line);
}
else if (unit == TextUnit::Page)
{
const auto firstVisibleLine{ editor.FirstVisibleLine() };
const auto maxLine{ editor.LineCount() - 1 };
const auto lastVisibleLine{ std::min(maxLine, firstVisibleLine + editor.LinesOnScreen()) };
_rangeStart = editor.PositionFromLine(firstVisibleLine);
_rangeEnd = editor.GetLineEndPosition(lastVisibleLine);
}
else if (unit == TextUnit::Word)
{
_rangeStart = editor.WordStartPosition(_rangeStart, false);
_rangeEnd = editor.WordEndPosition(_rangeStart, false);
}
else if (unit == TextUnit::Character)
{
_rangeEnd = std::min(_rangeStart + 1, editor.Length()); // Todo: Multibyte chars
}
}
ITextRangeProvider TextRangeProvider::FindAttribute(int32_t attributeId, IInspectable const &value, bool backward)
{
throw hresult_not_implemented{};
}
ITextRangeProvider TextRangeProvider::FindText(hstring const &text, bool backward, bool ignoreCase)
{
throw hresult_not_implemented{};
}
IInspectable TextRangeProvider::GetAttributeValue(int32_t attributeId)
{
const auto editor{ _editor.get() };
if (!editor)
{
throw hresult_error{ E_POINTER };
}
switch (static_cast<AutomationTextAttributesEnum>(attributeId))
{
case AutomationTextAttributesEnum::IsReadOnlyAttribute:
return box_value(editor.ReadOnly());
case AutomationTextAttributesEnum::CaretPositionAttribute:
{
const auto sel{ editor.MainSelection() };
const auto caret{ editor.GetSelectionNCaret(sel) };
if (caret < _rangeStart || caret > _rangeEnd)
{
// Unknown if caret is outside this text range
// Todo: Not sure if this is the correct behavior
return box_value(AutomationCaretPosition::Unknown);
}
const auto line{ editor.LineFromPosition(caret) };
if (caret == editor.PositionFromLine(line))
{
return box_value(AutomationCaretPosition::BeginningOfLine);
}
else if (caret == editor.GetLineEndPosition(line))
{
return box_value(AutomationCaretPosition::EndOfLine);
}
else
{
return box_value(AutomationCaretPosition::Unknown);
}
}
default:
// Must throw instead of returning nullptr
// https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalControl/XamlUiaTextRange.cpp#L141
throw_hresult(XAML_E_NOT_SUPPORTED);
}
}
void TextRangeProvider::GetBoundingRectangles(com_array<double> &returnValue)
{
// Structure: https://github.com/microsoft/terminal/blob/main/src/types/UiaTextRangeBase.cpp#L836
const auto editor{ _editor.get() };
if (!editor)
{
throw hresult_error{ E_POINTER };
}
// Todo: see EditorBaseControlAutomationPeer::GetVisibleRanges for caveats
// Todo: Does not account for horizontal scrolling
// Todo: Does not account for ranges that do not start and end at line starts/ends
const auto firstVisibleLine{ editor.FirstVisibleLine() };
const auto maxLine{ editor.LineCount() - 1 };
const auto lastVisibleLine{ std::min(maxLine, firstVisibleLine + editor.LinesOnScreen()) };
const auto startLine{ editor.LineFromPosition(_rangeStart) };
const auto endLine{ editor.LineFromPosition(_rangeEnd) };
const auto top{ std::max(startLine, firstVisibleLine) };
const auto end{ std::min(endLine, lastVisibleLine) };
const auto count{ end - top + 1 };
if (count < 1)
{
returnValue = {};
return;
}
auto margins{ editor.MarginLeft() };
const auto nMargins{ editor.Margins() };
for (auto i{ 0 }; i < nMargins; i++)
{
margins += editor.GetMarginWidthN(i);
}
const auto maxTextWidth{ static_cast<int>(_bounds.Width) - editor.MarginRight() };
returnValue = com_array<double>(count * 4);
// Todo: This code pretends that TextHeight gets the correct height including sublines (wrapping). It does not
for (int64_t i = 0, j = 0; i < count; i++, j += 4)
{
const auto line{ top + i };
const auto pos{ editor.PositionFromLine(line) };
const auto xStart{ editor.PointXFromPosition(line == startLine ? _rangeStart : pos) };
const auto xEnd{ editor.PointXFromPosition((line == endLine ? _rangeEnd : editor.GetLineEndPosition(line))) };
const auto textStart{ std::max(margins, xStart) };
returnValue[j + 0] = _bounds.X + textStart; // Left
returnValue[j + 1] = _bounds.Y + editor.PointYFromPosition(pos); // Top
returnValue[j + 2] = std::min(maxTextWidth, xEnd) - textStart; // Width
returnValue[j + 3] = editor.TextHeight(line); // Height
// Todo: Reconsider how off screen text is handled
if (xEnd < margins)
{
returnValue[j + 0] = _bounds.X + margins;
returnValue[j + 2] = 0;
}
if (xStart > maxTextWidth)
{
returnValue[j + 0] = _bounds.X + maxTextWidth;
returnValue[j + 2] = 0;
}
}
}
IRawElementProviderSimple TextRangeProvider::GetEnclosingElement()
{
return _peer;
}
hstring TextRangeProvider::GetText(int32_t maxLength)
{
const auto editor{ _editor.get() };
if (!editor)
{
throw hresult_error{ E_POINTER };
}
const auto length{ std::min(editor.Length() - _rangeStart, maxLength == -1 ? _rangeEnd - _rangeStart : std::min(_rangeEnd - _rangeStart, static_cast<int64_t>(maxLength))) };
std::string s(length, '\0');
Scintilla::TextRangeFull range
{
{ _rangeStart, _rangeStart + length, },
&s[0],
};
editor.GetTextRangeFull(reinterpret_cast<uint64_t>(&range));
return to_hstring(s);
}
int32_t TextRangeProvider::Move(TextUnit const &unit, int32_t count)
{
// Todo: Bounds checking and other units etc. and make sure handling this right
if (unit == TextUnit::Character)
{
_rangeStart += count;
_rangeEnd += count;
return count;
}
return 0;
}
int32_t TextRangeProvider::MoveEndpointByUnit(TextPatternRangeEndpoint const &endpoint, TextUnit const &unit, int32_t count)
{
// Todo: Bounds checking and other units etc.
if (endpoint == TextPatternRangeEndpoint::Start && unit == TextUnit::Character)
{
_rangeStart += count;
return count;
}
else if (endpoint == TextPatternRangeEndpoint::End && unit == TextUnit::Character)
{
_rangeEnd += count;
return count;
}
return 0;
}
void TextRangeProvider::MoveEndpointByRange(TextPatternRangeEndpoint const &endpoint, ITextRangeProvider const &textRangeProvider, TextPatternRangeEndpoint const &targetEndpoint)
{
const auto target{ textRangeProvider.as<TextRangeProvider>() };
const auto src{ targetEndpoint == TextPatternRangeEndpoint::Start ? target->_rangeStart : target->_rangeEnd };
if (endpoint == TextPatternRangeEndpoint::Start)
{
_rangeStart = src;
if (_rangeStart > _rangeEnd)
{
_rangeEnd = _rangeStart;
}
}
else
{
_rangeEnd = src;
if (_rangeStart > _rangeEnd)
{
_rangeStart = _rangeEnd;
}
}
}
void TextRangeProvider::Select()
{
const auto editor{ _editor.get() };
if (!editor)
{
throw hresult_error{ E_POINTER };
}
editor.SetSelection(_rangeEnd, _rangeStart);
}
void TextRangeProvider::AddToSelection()
{
const auto editor{ _editor.get() };
if (!editor)
{
throw hresult_error{ E_POINTER };
}
editor.AddSelection(_rangeEnd, _rangeStart);
}
void TextRangeProvider::RemoveFromSelection()
{
const auto editor{ _editor.get() };
if (!editor)
{
throw hresult_error{ E_POINTER };
}
const auto count{ editor.Selections() };
for (auto i{ 0 }; i < count; i++)
{
if (_rangeStart == editor.GetSelectionNStart(i)
&& _rangeEnd == editor.GetSelectionNEnd(i))
{
editor.DropSelectionN(i);
return;
}
}
}
void TextRangeProvider::ScrollIntoView(bool alignToTop)
{
const auto editor{ _editor.get() };
if (!editor)
{
throw hresult_error{ E_POINTER };
}
// Todo: You would want primary to be the caret and secondary to be anchor rather than start and end
// Todo: see if we can honor alignToTop
editor.ScrollRange(_rangeEnd, _rangeStart);
}
com_array<IRawElementProviderSimple> TextRangeProvider::GetChildren()
{
return {};
}
}

View File

@ -1,38 +0,0 @@
#pragma once
#include <winrt/WinUIEditor.h>
namespace winrt::WinUIEditor::implementation
{
struct TextRangeProvider : implements<TextRangeProvider, DUX::Automation::Provider::ITextRangeProvider>
{
TextRangeProvider(DUX::Automation::Provider::IRawElementProviderSimple const &peer, WinUIEditor::Editor const &editor, int64_t rangeStart, int64_t rangeEnd, Windows::Foundation::Rect const &bounds);
DUX::Automation::Provider::ITextRangeProvider Clone();
bool Compare(DUX::Automation::Provider::ITextRangeProvider const &textRangeProvider);
int32_t CompareEndpoints(DUX::Automation::Text::TextPatternRangeEndpoint const &endpoint, DUX::Automation::Provider::ITextRangeProvider const &textRangeProvider, DUX::Automation::Text::TextPatternRangeEndpoint const &targetEndpoint);
void ExpandToEnclosingUnit(DUX::Automation::Text::TextUnit const &unit);
DUX::Automation::Provider::ITextRangeProvider FindAttribute(int32_t attributeId, Windows::Foundation::IInspectable const &value, bool backward);
DUX::Automation::Provider::ITextRangeProvider FindText(hstring const &text, bool backward, bool ignoreCase);
Windows::Foundation::IInspectable GetAttributeValue(int32_t attributeId);
void GetBoundingRectangles(com_array<double> &returnValue);
DUX::Automation::Provider::IRawElementProviderSimple GetEnclosingElement();
hstring GetText(int32_t maxLength);
int32_t Move(DUX::Automation::Text::TextUnit const &unit, int32_t count);
int32_t MoveEndpointByUnit(DUX::Automation::Text::TextPatternRangeEndpoint const &endpoint, DUX::Automation::Text::TextUnit const &unit, int32_t count);
void MoveEndpointByRange(DUX::Automation::Text::TextPatternRangeEndpoint const &endpoint, DUX::Automation::Provider::ITextRangeProvider const &textRangeProvider, DUX::Automation::Text::TextPatternRangeEndpoint const &targetEndpoint);
void Select();
void AddToSelection();
void RemoveFromSelection();
void ScrollIntoView(bool alignToTop);
com_array<DUX::Automation::Provider::IRawElementProviderSimple> GetChildren();
private:
DUX::Automation::Provider::IRawElementProviderSimple _peer{ nullptr };
weak_ref<WinUIEditor::Editor> _editor{ nullptr };
int64_t _rangeStart;
int64_t _rangeEnd;
Windows::Foundation::Rect _bounds;
};
}

View File

@ -1,67 +0,0 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinUIEditor">
<!-- Todo: Apply corner radius to this. Remember conditional Setters do not work, so make a different style for each version. What happens with WinUI 3? -->
<Style TargetType="local:EditorBaseControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:EditorBaseControl">
<Grid
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border
x:Name="ImageTarget"
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0"
Grid.ColumnSpan="2"
AllowDrop="True" />
<ScrollBar
x:Name="VerticalScrollBar"
Grid.Row="0"
Grid.Column="1"
IndicatorMode="MouseIndicator"
IsTabStop="False"
Orientation="Vertical" />
<ScrollBar
x:Name="HorizontalScrollBar"
Grid.Row="1"
Grid.Column="0"
IndicatorMode="MouseIndicator"
IsTabStop="False"
Orientation="Horizontal" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="local:CodeEditorControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CodeEditorControl">
<ContentPresenter
x:Name="EditorContainer"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -1,3 +0,0 @@
EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE

View File

@ -1,847 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\ChangeBuild.props" />
<Import Project="..\packages\Microsoft.WindowsAppSDK.1.5.240227000\build\native\Microsoft.WindowsAppSDK.props" Condition="$(WinUIEditorUseWinUI3) And Exists('..\packages\Microsoft.WindowsAppSDK.1.5.240227000\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.3233\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.3233\build\Microsoft.Windows.SDK.BuildTools.props')" />
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
<MinimalCoreWin>true</MinimalCoreWin>
<ProjectGuid>{290647e3-d8cb-46b5-87ce-409f721e441a}</ProjectGuid>
<ProjectName>WinUIEditor</ProjectName>
<RootNamespace>WinUIEditor</RootNamespace>
<DefaultLanguage>en-US</DefaultLanguage>
<MinimumVisualStudioVersion>16.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.22621.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion Condition="$(WinUIEditorUseWinUI3)">10.0.17763.0</WindowsTargetPlatformMinVersion>
<WindowsTargetPlatformMinVersion Condition="!$(WinUIEditorUseWinUI3)">10.0.15063.0</WindowsTargetPlatformMinVersion>
<DesktopCompatible Condition="$(WinUIEditorUseWinUI3)">true</DesktopCompatible>
<UseWinUI Condition="$(WinUIEditorUseWinUI3)">true</UseWinUI>
<_NoWinAPIFamilyApp Condition="$(WinUIEditorUseWinUI3)">true</_NoWinAPIFamilyApp>
<_VC_Target_Library_Platform Condition="$(WinUIEditorUseWinUI3)">Desktop</_VC_Target_Library_Platform>
<UseCrtSDKReference Condition="$(WinUIEditorUseWinUI3)">false</UseCrtSDKReference>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="..\DualBuild.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|arm64">
<Configuration>Debug</Configuration>
<Platform>arm64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|arm64">
<Configuration>Release</Configuration>
<Platform>arm64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<LinkIncremental>true</LinkIncremental>
<UseDummyPage>true</UseDummyPage>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
<AdditionalIncludeDirectories>..\scintilla\winui;..\scintilla\include;..\scintilla\src;..\lexilla\include\;..\lexilla\lexlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<WarningLevel>Level4</WarningLevel>
<AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
<PreprocessorDefinitions>SCI_EMPTYCATALOGUE;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>NOMINMAX;_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="$(WinUIEditorUseWinUI3)">WINUI3;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
</ClCompile>
<Midl>
<PreprocessorDefinitions Condition="$(WinUIEditorUseWinUI3)">WINUI3;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</Midl>
<Link>
<SubSystem>Console</SubSystem>
<GenerateWindowsMetadata>true</GenerateWindowsMetadata>
<ModuleDefinitionFile>WinUIEditor.def</ModuleDefinitionFile>
<AdditionalDependencies Condition="$(WinUIEditorUseWinUI3)">user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)' == 'Debug'">
<ClCompile>
<PreprocessorDefinitions>USE_DUMMY_PAGE;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary Condition="$(WinUIEditorUseWinUI3)">MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<IgnoreSpecificDefaultLibraries Condition="$(WinUIEditorUseWinUI3)">%(IgnoreSpecificDefaultLibraries);libucrtd.lib</IgnoreSpecificDefaultLibraries>
<AdditionalOptions Condition="$(WinUIEditorUseWinUI3)">%(AdditionalOptions) /defaultlib:ucrtd.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)' == 'Release'">
<ClCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ControlFlowGuard>Guard</ControlFlowGuard>
<RuntimeLibrary Condition="$(WinUIEditorUseWinUI3)">MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<IgnoreSpecificDefaultLibraries Condition="$(WinUIEditorUseWinUI3)">%(IgnoreSpecificDefaultLibraries);libucrt.lib</IgnoreSpecificDefaultLibraries>
<AdditionalOptions Condition="$(WinUIEditorUseWinUI3)">%(AdditionalOptions) /defaultlib:ucrt.lib</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="CodeEditorHandler.SciEdit.h" />
<ClInclude Include="CodeEditorHandler.h" />
<ClInclude Include="ControlIncludes.h" />
<ClInclude Include="DarkPlus.h" />
<ClInclude Include="DummyPage.h" Condition="'$(UseDummyPage)' == 'true'">
<DependentUpon>DummyPage.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="Helpers.h" />
<ClInclude Include="EditorWrapper.h">
<DependentUpon>EditorWrapper.cpp</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="LightPlus.h" />
<ClInclude Include="EditorBaseControl.h">
<DependentUpon>EditorBaseControl.cpp</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="CodeEditorControl.h">
<DependentUpon>CodeEditorControl.cpp</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="EditorBaseControlAutomationPeer.h">
<DependentUpon>EditorBaseControlAutomationPeer.cpp</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="pch.h" />
<ClInclude Include="..\scintilla\winui\PlatWin.h" />
<ClInclude Include="..\scintilla\winui\ScintillaWin.h" />
<ClInclude Include="..\scintilla\winui\WinTypes.h" />
<ClInclude Include="TextMateScope.h" />
<ClInclude Include="TextRangeProvider.h" />
<ClInclude Include="Wrapper.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="CodeEditorHandler.SciEdit.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="CodeEditorHandler.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="DummyPage.cpp" Condition="'$(UseDummyPage)' == 'true'">
<DependentUpon>DummyPage.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="Helpers.cpp" />
<ClCompile Include="EditorWrapper.cpp">
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="EditorBaseControl.cpp">
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="CodeEditorControl.cpp">
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="CodeEditorHandler.SyntaxHighlighting.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="EditorBaseControlAutomationPeer.cpp">
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<ClCompile Include="..\lexilla\src\Lexilla.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\winui\PlatWin.cxx" />
<ClCompile Include="..\scintilla\winui\ScintillaWin.cxx" />
<ClCompile Include="TextRangeProvider.cpp" />
<ClCompile Include="Wrapper.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="WinUIEditor.def" />
<None Include="packages.config" />
<None Include="Defines.idl" />
</ItemGroup>
<ItemGroup>
<Midl Include="DummyPage.idl" Condition="'$(UseDummyPage)' == 'true'">
<DependentUpon>DummyPage.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="EditorWrapper.idl">
<DependentUpon>EditorWrapper.cpp</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="EditorBaseControl.idl">
<DependentUpon>EditorBaseControl.cpp</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="CodeEditorControl.idl">
<DependentUpon>CodeEditorControl.cpp</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="EditorBaseControlAutomationPeer.idl">
<DependentUpon>EditorBaseControlAutomationPeer.cpp</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="IEditorAccess.idl" />
</ItemGroup>
<ItemGroup>
<Page Include="DummyPage.xaml" Condition="'$(UseDummyPage)' == 'true'">
<SubType>Designer</SubType>
</Page>
<Page Include="Themes\Generic.xaml" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.3233\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.3233\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="..\packages\Microsoft.WindowsAppSDK.1.5.240227000\build\native\Microsoft.WindowsAppSDK.targets" Condition="$(WinUIEditorUseWinUI3) And Exists('..\packages\Microsoft.WindowsAppSDK.1.5.240227000\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\packages\Microsoft.Windows.ImplementationLibrary.1.0.240122.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\packages\Microsoft.Windows.ImplementationLibrary.1.0.240122.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.3233\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.3233\build\Microsoft.Windows.SDK.BuildTools.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.3233\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.3233\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
<Error Condition="$(WinUIEditorUseWinUI3) And !Exists('..\packages\Microsoft.WindowsAppSDK.1.5.240227000\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.WindowsAppSDK.1.5.240227000\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="$(WinUIEditorUseWinUI3) And !Exists('..\packages\Microsoft.WindowsAppSDK.1.5.240227000\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.WindowsAppSDK.1.5.240227000\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\packages\Microsoft.Windows.ImplementationLibrary.1.0.240122.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.ImplementationLibrary.1.0.240122.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
</Target>
<ItemGroup>
<!--<WildcardClInclude Include="..\scintilla\include\*.h">-->
<ClInclude Include="..\scintilla\include\ILexer.h" />
<ClInclude Include="..\scintilla\include\ILoader.h" />
<ClInclude Include="..\scintilla\include\Sci_Position.h" />
<ClInclude Include="..\scintilla\include\Scintilla.h" />
<ClInclude Include="..\scintilla\include\ScintillaCall.h" />
<ClInclude Include="..\scintilla\include\ScintillaMessages.h" />
<ClInclude Include="..\scintilla\include\ScintillaStructures.h" />
<ClInclude Include="..\scintilla\include\ScintillaTypes.h" />
<ClInclude Include="..\scintilla\include\ScintillaWidget.h" />
<!--</WildcardClInclude>-->
<!--<WildcardClInclude Include="..\scintilla\src\*.h">-->
<ClInclude Include="..\scintilla\src\AutoComplete.h" />
<ClInclude Include="..\scintilla\src\CallTip.h" />
<ClInclude Include="..\scintilla\src\CaseConvert.h" />
<ClInclude Include="..\scintilla\src\CaseFolder.h" />
<ClInclude Include="..\scintilla\src\CellBuffer.h" />
<ClInclude Include="..\scintilla\src\ChangeHistory.h" />
<ClInclude Include="..\scintilla\src\CharacterCategoryMap.h" />
<ClInclude Include="..\scintilla\src\CharacterType.h" />
<ClInclude Include="..\scintilla\src\CharClassify.h" />
<ClInclude Include="..\scintilla\src\ContractionState.h" />
<ClInclude Include="..\scintilla\src\DBCS.h" />
<ClInclude Include="..\scintilla\src\Debugging.h" />
<ClInclude Include="..\scintilla\src\Decoration.h" />
<ClInclude Include="..\scintilla\src\Document.h" />
<ClInclude Include="..\scintilla\src\EditModel.h" />
<ClInclude Include="..\scintilla\src\Editor.h" />
<ClInclude Include="..\scintilla\src\EditView.h" />
<ClInclude Include="..\scintilla\src\ElapsedPeriod.h" />
<ClInclude Include="..\scintilla\src\Geometry.h" />
<ClInclude Include="..\scintilla\src\Indicator.h" />
<ClInclude Include="..\scintilla\src\KeyMap.h" />
<ClInclude Include="..\scintilla\src\LineMarker.h" />
<ClInclude Include="..\scintilla\src\MarginView.h" />
<ClInclude Include="..\scintilla\src\Partitioning.h" />
<ClInclude Include="..\scintilla\src\PerLine.h" />
<ClInclude Include="..\scintilla\src\Platform.h" />
<ClInclude Include="..\scintilla\src\Position.h" />
<ClInclude Include="..\scintilla\src\PositionCache.h" />
<ClInclude Include="..\scintilla\src\RESearch.h" />
<ClInclude Include="..\scintilla\src\RunStyles.h" />
<ClInclude Include="..\scintilla\src\ScintillaBase.h" />
<ClInclude Include="..\scintilla\src\Selection.h" />
<ClInclude Include="..\scintilla\src\SparseVector.h" />
<ClInclude Include="..\scintilla\src\SplitVector.h" />
<ClInclude Include="..\scintilla\src\Style.h" />
<ClInclude Include="..\scintilla\src\UndoHistory.h" />
<ClInclude Include="..\scintilla\src\UniConversion.h" />
<ClInclude Include="..\scintilla\src\UniqueString.h" />
<ClInclude Include="..\scintilla\src\ViewStyle.h" />
<ClInclude Include="..\scintilla\src\XPM.h" />
<!--</WildcardClInclude>-->
<!--<WildcardClInclude Include="..\lexilla\include\*.h">-->
<ClInclude Include="..\lexilla\include\Lexilla.h" />
<ClInclude Include="..\lexilla\include\SciLexer.h" />
<!--</WildcardClInclude>-->
<!--<WildcardClInclude Include="..\lexilla\lexlib\*.h">-->
<ClInclude Include="..\lexilla\lexlib\Accessor.h" />
<ClInclude Include="..\lexilla\lexlib\CatalogueModules.h" />
<ClInclude Include="..\lexilla\lexlib\CharacterCategory.h" />
<ClInclude Include="..\lexilla\lexlib\CharacterSet.h" />
<ClInclude Include="..\lexilla\lexlib\DefaultLexer.h" />
<ClInclude Include="..\lexilla\lexlib\InList.h" />
<ClInclude Include="..\lexilla\lexlib\LexAccessor.h" />
<ClInclude Include="..\lexilla\lexlib\LexerBase.h" />
<ClInclude Include="..\lexilla\lexlib\LexerModule.h" />
<ClInclude Include="..\lexilla\lexlib\LexerNoExceptions.h" />
<ClInclude Include="..\lexilla\lexlib\LexerSimple.h" />
<ClInclude Include="..\lexilla\lexlib\OptionSet.h" />
<ClInclude Include="..\lexilla\lexlib\PropSetSimple.h" />
<ClInclude Include="..\lexilla\lexlib\SparseState.h" />
<ClInclude Include="..\lexilla\lexlib\StringCopy.h" />
<ClInclude Include="..\lexilla\lexlib\StyleContext.h" />
<ClInclude Include="..\lexilla\lexlib\SubStyles.h" />
<ClInclude Include="..\lexilla\lexlib\WordList.h" />
<!--</WildcardClInclude>-->
</ItemGroup>
<ItemGroup>
<!--<WildcardClCompile Include="..\scintilla\src\*.cxx" PrecompiledHeader="NotUsing">-->
<ClCompile Include="..\scintilla\src\AutoComplete.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\CallTip.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\CaseConvert.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\CaseFolder.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\CellBuffer.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\ChangeHistory.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\CharacterCategoryMap.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\CharacterType.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\CharClassify.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\ContractionState.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\DBCS.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\Decoration.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\Document.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\EditModel.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\Editor.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\EditView.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\Geometry.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\Indicator.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\KeyMap.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\LineMarker.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\MarginView.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\PerLine.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\PositionCache.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\RESearch.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\RunStyles.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\ScintillaBase.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\Selection.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\Style.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\UndoHistory.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\UniConversion.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\UniqueString.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\ViewStyle.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\scintilla\src\XPM.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<!--</WildcardClInclude>-->
<!--<WildcardClCompile Include="..\scintilla\call\*.cxx" PrecompiledHeader="NotUsing">-->
<ClCompile Include="..\scintilla\call\ScintillaCall.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<!--</WildcardClInclude>-->
<!--<WildcardClCompile Include="..\lexilla\lexers\*.cxx" PrecompiledHeader="NotUsing">-->
<ClCompile Include="..\lexilla\lexers\LexA68k.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAbaqus.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAda.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAPDL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAsciidoc.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAsm.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAsn1.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexASY.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAU3.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAVE.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAVS.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBaan.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBash.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBasic.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBatch.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBibTeX.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBullant.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCaml.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCIL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCLW.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCmake.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCOBOL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCoffeeScript.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexConf.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCPP.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCrontab.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCsound.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCSS.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexD.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexDataflex.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexDiff.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexDMAP.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexDMIS.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexECL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexEDIFACT.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexEiffel.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexErlang.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexErrorList.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexEScript.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexFlagship.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexForth.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexFortran.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexFSharp.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexGAP.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexGDScript.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexGui4Cli.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexHaskell.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexHex.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexHollywood.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexHTML.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexIndent.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexInno.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexJSON.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexJulia.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexKix.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexKVIrc.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexLaTeX.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexLisp.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexLout.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexLua.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMagik.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMake.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMarkdown.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMatlab.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMaxima.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMetapost.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMMIXAL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexModula.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMPT.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMSSQL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMySQL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexNim.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexNimrod.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexNsis.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexNull.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexOpal.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexOScript.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPascal.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPB.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPerl.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPLM.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPO.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPOV.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPowerPro.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPowerShell.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexProgress.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexProps.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPS.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPython.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexR.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexRaku.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexRebol.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexRegistry.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexRuby.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexRust.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSAS.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexScriptol.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSmalltalk.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSML.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSorcus.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSpecman.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSpice.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSQL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexStata.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSTTXT.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTACL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTADS3.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTAL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTCL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTCMD.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTeX.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTxt2tags.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexVB.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexVerilog.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexVHDL.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexVisualProlog.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexX12.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexYAML.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<!--</WildcardClInclude>-->
<!--<WildcardClCompile Include="..\lexilla\lexlib\*.cxx" PrecompiledHeader="NotUsing">-->
<ClCompile Include="..\lexilla\lexlib\Accessor.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\CharacterCategory.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\CharacterSet.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\DefaultLexer.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\InList.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\LexAccessor.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\LexerBase.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\LexerModule.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\LexerNoExceptions.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\LexerSimple.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\PropSetSimple.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\StyleContext.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\WordList.cxx">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<!--</WildcardClInclude>-->
</ItemGroup>
</Project>

View File

@ -1,785 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="15.0">
<ItemGroup>
<Filter Include="Resources">
<UniqueIdentifier>accd3aa8-1ba0-4223-9bbe-0c431709210b</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Generated Files">
<UniqueIdentifier>{926ab91d-31b4-48c3-b9a4-e681349f27f0}</UniqueIdentifier>
</Filter>
<Filter Include="Scintilla">
<UniqueIdentifier>{d2af1cc1-e66c-4161-aa1f-2dce16d662a7}</UniqueIdentifier>
</Filter>
<Filter Include="Lexilla">
<UniqueIdentifier>{dcec4768-41d4-43a2-9eaa-ebecc2ebbcca}</UniqueIdentifier>
</Filter>
<Filter Include="Lexers">
<UniqueIdentifier>{d97ff389-708f-4fce-a1ad-4f6ad3a99854}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="CodeEditorControl.cpp" />
<ClCompile Include="CodeEditorHandler.cpp" />
<ClCompile Include="CodeEditorHandler.SciEdit.cpp" />
<ClCompile Include="CodeEditorHandler.SyntaxHighlighting.cpp" />
<ClCompile Include="DummyPage.cpp" />
<ClCompile Include="EditorBaseControl.cpp" />
<ClCompile Include="EditorBaseControlAutomationPeer.cpp" />
<ClCompile Include="EditorWrapper.cpp" />
<ClCompile Include="Helpers.cpp" />
<ClCompile Include="pch.cpp" />
<ClCompile Include="TextRangeProvider.cpp" />
<ClCompile Include="Wrapper.cpp" />
<ClCompile Include="..\scintilla\winui\PlatWin.cxx" />
<ClCompile Include="..\scintilla\winui\ScintillaWin.cxx" />
<ClCompile Include="..\scintilla\src\AutoComplete.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\CallTip.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\CaseConvert.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\CaseFolder.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\CellBuffer.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\ChangeHistory.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\CharacterCategoryMap.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\CharacterType.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\CharClassify.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\ContractionState.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\DBCS.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\Decoration.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\Document.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\EditModel.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\Editor.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\EditView.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\Geometry.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\Indicator.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\KeyMap.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\LineMarker.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\MarginView.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\PerLine.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\PositionCache.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\RESearch.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\RunStyles.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\ScintillaBase.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\Selection.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\Style.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\UndoHistory.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\UniConversion.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\UniqueString.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\ViewStyle.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\src\XPM.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\scintilla\call\ScintillaCall.cxx">
<Filter>Scintilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexA68k.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAbaqus.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAda.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAPDL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAsciidoc.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAsm.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAsn1.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexASY.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAU3.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAVE.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexAVS.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBaan.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBash.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBasic.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBatch.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBibTeX.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexBullant.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCaml.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCIL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCLW.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCmake.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCOBOL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCoffeeScript.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexConf.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCPP.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCrontab.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCsound.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexCSS.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexD.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexDataflex.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexDiff.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexDMAP.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexDMIS.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexECL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexEDIFACT.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexEiffel.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexErlang.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexErrorList.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexEScript.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexFlagship.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexForth.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexFortran.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexFSharp.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexGAP.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexGDScript.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexGui4Cli.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexHaskell.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexHex.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexHollywood.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexHTML.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexIndent.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexInno.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexJSON.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexJulia.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexKix.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexKVIrc.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexLaTeX.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexLisp.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexLout.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexLua.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMagik.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMake.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMarkdown.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMatlab.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMaxima.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMetapost.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMMIXAL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexModula.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMPT.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMSSQL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexMySQL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexNim.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexNimrod.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexNsis.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexNull.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexOpal.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexOScript.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPascal.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPB.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPerl.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPLM.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPO.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPOV.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPowerPro.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPowerShell.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexProgress.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexProps.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPS.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexPython.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexR.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexRaku.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexRebol.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexRegistry.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexRuby.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexRust.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSAS.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexScriptol.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSmalltalk.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSML.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSorcus.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSpecman.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSpice.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSQL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexStata.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexSTTXT.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTACL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTADS3.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTAL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTCL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTCMD.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTeX.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexTxt2tags.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexVB.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexVerilog.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexVHDL.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexVisualProlog.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexX12.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexers\LexYAML.cxx">
<Filter>Lexers</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\Accessor.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\CharacterCategory.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\CharacterSet.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\DefaultLexer.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\InList.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\LexAccessor.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\LexerBase.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\LexerModule.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\LexerNoExceptions.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\LexerSimple.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\PropSetSimple.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\StyleContext.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\lexlib\WordList.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
<ClCompile Include="..\lexilla\src\Lexilla.cxx">
<Filter>Lexilla</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="CodeEditorControl.h" />
<ClInclude Include="CodeEditorHandler.h" />
<ClInclude Include="CodeEditorHandler.SciEdit.h" />
<ClInclude Include="ControlIncludes.h" />
<ClInclude Include="DarkPlus.h" />
<ClInclude Include="DummyPage.h" />
<ClInclude Include="EditorBaseControl.h" />
<ClInclude Include="EditorBaseControlAutomationPeer.h" />
<ClInclude Include="EditorWrapper.h" />
<ClInclude Include="Helpers.h" />
<ClInclude Include="LightPlus.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="TextMateScope.h" />
<ClInclude Include="TextRangeProvider.h" />
<ClInclude Include="Wrapper.h" />
<ClInclude Include="..\scintilla\winui\PlatWin.h" />
<ClInclude Include="..\scintilla\winui\ScintillaWin.h" />
<ClInclude Include="..\scintilla\winui\WinTypes.h" />
<ClInclude Include="..\scintilla\include\ILexer.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\include\ILoader.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\include\Sci_Position.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\include\Scintilla.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\include\ScintillaCall.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\include\ScintillaMessages.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\include\ScintillaStructures.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\include\ScintillaTypes.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\include\ScintillaWidget.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\AutoComplete.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\CallTip.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\CaseConvert.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\CaseFolder.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\CellBuffer.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\ChangeHistory.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\CharacterCategoryMap.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\CharacterType.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\CharClassify.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\ContractionState.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\DBCS.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\Debugging.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\Decoration.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\Document.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\EditModel.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\Editor.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\EditView.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\ElapsedPeriod.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\Geometry.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\Indicator.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\KeyMap.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\LineMarker.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\MarginView.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\Partitioning.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\PerLine.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\Platform.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\Position.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\PositionCache.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\RESearch.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\RunStyles.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\ScintillaBase.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\Selection.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\SparseVector.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\SplitVector.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\Style.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\UndoHistory.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\UniConversion.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\UniqueString.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\ViewStyle.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\scintilla\src\XPM.h">
<Filter>Scintilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\Accessor.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\CatalogueModules.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\CharacterCategory.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\CharacterSet.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\DefaultLexer.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\InList.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\LexAccessor.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\LexerBase.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\LexerModule.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\LexerNoExceptions.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\LexerSimple.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\OptionSet.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\PropSetSimple.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\SparseState.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\StringCopy.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\StyleContext.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\SubStyles.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\lexlib\WordList.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\include\Lexilla.h">
<Filter>Lexilla</Filter>
</ClInclude>
<ClInclude Include="..\lexilla\include\SciLexer.h">
<Filter>Lexilla</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="WinUIEditor.def" />
<None Include="packages.config" />
<None Include="Defines.idl" />
</ItemGroup>
<ItemGroup>
<Page Include="Themes\Generic.xaml" />
<Page Include="DummyPage.xaml" />
</ItemGroup>
<ItemGroup>
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
</ItemGroup>
<ItemGroup>
<Midl Include="CodeEditorControl.idl" />
<Midl Include="DummyPage.idl" />
<Midl Include="EditorBaseControl.idl" />
<Midl Include="EditorBaseControlAutomationPeer.idl" />
<Midl Include="EditorWrapper.idl" />
<Midl Include="IEditorAccess.idl" />
</ItemGroup>
</Project>

View File

@ -1,261 +0,0 @@
#include "pch.h"
#include "Wrapper.h"
namespace WinUIEditor
{
winrt::com_ptr<::IVirtualSurfaceImageSourceNative> Wrapper::VsisNative()
{
return _vsisNative;
}
void Wrapper::VsisNative(winrt::com_ptr<::IVirtualSurfaceImageSourceNative> const &value)
{
_vsisNative = value;
_sisNativeWithD2D = _vsisNative.as<::ISurfaceImageSourceNativeWithD2D>();
}
winrt::com_ptr<::ISurfaceImageSourceNativeWithD2D> Wrapper::SisNativeWithD2D()
{
return _sisNativeWithD2D;
}
winrt::com_ptr<::ID2D1DeviceContext> Wrapper::D2dDeviceContext()
{
return _d2dDeviceContext;
}
void Wrapper::TrimDxgiDevice()
{
if (_dxgiDevice)
{
_dxgiDevice->Trim();
}
}
float Wrapper::LogicalDpi()
{
return _logicalDpi;
}
void Wrapper::LogicalDpi(float value)
{
_logicalDpi = value;
}
int Wrapper::Width()
{
return _width;
}
void Wrapper::Width(int value)
{
_width = value;
}
int Wrapper::Height()
{
return _height;
}
void Wrapper::Height(int value)
{
_height = value;
}
void Wrapper::SetMouseCapture(bool on)
{
if (!_mouseCaptureElement)
{
return;
}
if (on)
{
if (_lastPointer) // Todo: Check if works
{
_captured = _mouseCaptureElement.CapturePointer(_lastPointer);
}
}
else
{
_mouseCaptureElement.ReleasePointerCaptures(); // Todo: Or just one?
_captured = false;
}
}
bool Wrapper::HaveMouseCapture()
{
return _captured;
}
void Wrapper::SetMouseCaptureElement(winrt::DUX::UIElement const &element)
{
_mouseCaptureElement = element;
// Todo: Do we need to revoke?
// Todo: Do we need a strong/weak reference?
_mouseCaptureElement.PointerPressed([&](winrt::Windows::Foundation::IInspectable const &sender, winrt::DUX::Input::PointerRoutedEventArgs const &args)
{
_lastPointer = args.Pointer();
});
_mouseCaptureElement.PointerCaptureLost([&](winrt::Windows::Foundation::IInspectable const &sender, winrt::DUX::Input::PointerRoutedEventArgs const &args)
{
_captured = false;
});
}
void Wrapper::SetCursor(winrt::DCUR cursor)
{
#ifdef WINUI3
if (_mouseCaptureElement)
{
_mouseCaptureElement.try_as<winrt::Microsoft::UI::Xaml::IUIElementProtected>().ProtectedCursor(winrt::Microsoft::UI::Input::InputSystemCursor::Create(cursor));
}
#else
winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread().PointerCursor(winrt::Windows::UI::Core::CoreCursor{ cursor, 0 });
#endif
}
void Wrapper::SetScrollBars(winrt::DUX::Controls::Primitives::ScrollBar const &horizontalScrollBar, winrt::DUX::Controls::Primitives::ScrollBar const &verticalScrollBar)
{
_horizontalScrollBar = horizontalScrollBar;
_verticalScrollBar = verticalScrollBar;
}
bool Wrapper::HasScrollBars()
{
return _horizontalScrollBar && _verticalScrollBar;
}
void Wrapper::HorizontalScrollBarValue(double value)
{
_horizontalScrollBar.Value(value);
}
void Wrapper::VerticalScrollBarValue(double value)
{
_verticalScrollBar.Value(value);
}
void Wrapper::HorizontalScrollBarMinimum(double value)
{
_horizontalScrollBar.Minimum(value);
}
void Wrapper::VerticalScrollBarMinimum(double value)
{
_verticalScrollBar.Minimum(value);
}
void Wrapper::HorizontalScrollBarMaximum(double value)
{
_horizontalScrollBar.Maximum(value);
}
void Wrapper::VerticalScrollBarMaximum(double value)
{
_verticalScrollBar.Maximum(value);
}
void Wrapper::HorizontalScrollBarViewportSize(double value)
{
_horizontalScrollBar.ViewportSize(value);
}
void Wrapper::VerticalScrollBarViewportSize(double value)
{
_verticalScrollBar.ViewportSize(value);
}
double Wrapper::HorizontalScrollBarValue()
{
return _horizontalScrollBar.Value();
}
double Wrapper::VerticalScrollBarValue()
{
return _verticalScrollBar.Value();
}
double Wrapper::HorizontalScrollBarMinimum()
{
return _horizontalScrollBar.Minimum();
}
double Wrapper::VerticalScrollBarMinimum()
{
return _verticalScrollBar.Minimum();
}
double Wrapper::HorizontalScrollBarMaximum()
{
return _horizontalScrollBar.Maximum();
}
double Wrapper::VerticalScrollBarMaximum()
{
return _verticalScrollBar.Maximum();
}
double Wrapper::HorizontalScrollBarViewportSize()
{
return _horizontalScrollBar.ViewportSize();
}
double Wrapper::VerticalScrollBarViewportSize()
{
return _verticalScrollBar.ViewportSize();
}
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::ApplicationModel::DataTransfer::DataPackageOperation> Wrapper::StartDragAsync(winrt::DUI::PointerPoint const &pointerPoint)
{
return _mouseCaptureElement.StartDragAsync(pointerPoint);
}
void Wrapper::CreateGraphicsDevices()
{
// Todo: Is there any cleanup that needs to be done when the control is deleted or if the device gets re-created?
uint32_t creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1,
};
// Create the Direct3D device
winrt::com_ptr<ID3D11Device> d3dDevice;
D3D_FEATURE_LEVEL supportedFeatureLevel;
winrt::check_hresult(D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
0,
creationFlags,
featureLevels,
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION,
d3dDevice.put(),
&supportedFeatureLevel,
nullptr));
// Get the Direct3D device.
_dxgiDevice = d3dDevice.as<IDXGIDevice3>();
// Create the Direct2D device and a corresponding context
winrt::com_ptr<ID2D1Device> d2dDevice;
D2D1CreateDevice(_dxgiDevice.get(), nullptr, d2dDevice.put());
winrt::check_hresult(
d2dDevice->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
_d2dDeviceContext.put()));
// Associate the Direct2D device with the SurfaceImageSource
SisNativeWithD2D()->SetDevice(d2dDevice.get());
}
}

View File

@ -1,70 +0,0 @@
#pragma once
namespace WinUIEditor
{
class Wrapper
{
public:
winrt::com_ptr<::IVirtualSurfaceImageSourceNative> VsisNative();
void VsisNative(winrt::com_ptr<::IVirtualSurfaceImageSourceNative> const &value);
winrt::com_ptr<::ISurfaceImageSourceNativeWithD2D> SisNativeWithD2D();
winrt::com_ptr<::ID2D1DeviceContext> D2dDeviceContext();
void TrimDxgiDevice();
float LogicalDpi();
void LogicalDpi(float value);
int Width();
void Width(int value);
int Height();
void Height(int value);
// Todo: Make abstract
void SetMouseCapture(bool on);
bool HaveMouseCapture();
// Todo: Move to separate XAML class
void SetMouseCaptureElement(winrt::DUX::UIElement const &element);
void SetCursor(winrt::DCUR cursor);
void SetScrollBars(winrt::DUX::Controls::Primitives::ScrollBar const &horizontalScrollBar, winrt::DUX::Controls::Primitives::ScrollBar const &verticalScrollBar);
bool HasScrollBars();
void HorizontalScrollBarValue(double value);
void VerticalScrollBarValue(double value);
void HorizontalScrollBarMinimum(double value);
void VerticalScrollBarMinimum(double value);
void HorizontalScrollBarMaximum(double value);
void VerticalScrollBarMaximum(double value);
void HorizontalScrollBarViewportSize(double value);
void VerticalScrollBarViewportSize(double value);
double HorizontalScrollBarValue();
double VerticalScrollBarValue();
double HorizontalScrollBarMinimum();
double VerticalScrollBarMinimum();
double HorizontalScrollBarMaximum();
double VerticalScrollBarMaximum();
double HorizontalScrollBarViewportSize();
double VerticalScrollBarViewportSize();
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::ApplicationModel::DataTransfer::DataPackageOperation> StartDragAsync(winrt::DUI::PointerPoint const &pointerPoint);
void CreateGraphicsDevices();
// Font used for arrows in folding column markers. Stored here to allow retrieval from SurfaceD2D
// Do not access outside of GetChevronFontFromSurface
std::shared_ptr<Scintilla::Internal::Font> chevronFont{ nullptr };
Scintilla::Internal::XYPOSITION chevronFontSize{ -1.0 };
private:
winrt::DUX::Input::Pointer _lastPointer{ nullptr };
winrt::DUX::UIElement _mouseCaptureElement{ nullptr };
winrt::DUX::Controls::Primitives::ScrollBar _horizontalScrollBar{ nullptr };
winrt::DUX::Controls::Primitives::ScrollBar _verticalScrollBar{ nullptr };
bool _captured;
winrt::com_ptr<IVirtualSurfaceImageSourceNative> _vsisNative{ nullptr };
winrt::com_ptr<::ISurfaceImageSourceNativeWithD2D> _sisNativeWithD2D{ nullptr };
winrt::com_ptr<::ID2D1DeviceContext> _d2dDeviceContext{ nullptr };
winrt::com_ptr<::IDXGIDevice3> _dxgiDevice{ nullptr };
float _logicalDpi;
int _width;
int _height;
};
}

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.240122.1" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.22621.3233" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.5.240227000" targetFramework="native" />
</packages>

View File

@ -1 +0,0 @@
#include "pch.h"

View File

@ -1,144 +0,0 @@
#pragma once
#include <unknwn.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Foundation.Metadata.h>
#include <winrt/Windows.Graphics.Display.h>
#include <winrt/Windows.System.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.UI.Text.Core.h>
#include <winrt/Windows.UI.Core.h>
#include <winrt/Windows.ApplicationModel.DataTransfer.h>
#include <winrt/Windows.UI.Xaml.Interop.h>
#include <winrt/Windows.UI.Popups.h>
#include <winrt/Windows.UI.ViewManagement.h>
#ifdef WINUI3
#include <winrt/Microsoft.UI.Input.h>
#include <winrt/Microsoft.UI.Composition.h>
#include <winrt/Microsoft.UI.Xaml.h>
#include <winrt/Microsoft.UI.Xaml.Automation.Peers.h>
#include <winrt/Microsoft.UI.Xaml.Automation.Provider.h>
#include <winrt/Microsoft.UI.Xaml.Automation.Text.h>
#include <winrt/Microsoft.UI.Xaml.Controls.h>
#include <winrt/Microsoft.UI.Xaml.Input.h>
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
#include <winrt/Microsoft.UI.Xaml.Data.h>
#include <winrt/Microsoft.UI.Xaml.Markup.h>
#include <winrt/Microsoft.UI.Xaml.Navigation.h>
#include <winrt/Microsoft.UI.Dispatching.h>
#include <winrt/Microsoft.UI.Xaml.Media.Imaging.h>
#include <microsoft.ui.xaml.media.dxinterop.h>
#include <microsoft.ui.xaml.window.h>
#include <wil/cppwinrt_helpers.h>
#define DUX Microsoft::UI::Xaml
#define DUXC Microsoft::UI::Xaml::Controls
#define DUI Microsoft::UI::Input
#define DCUR Microsoft::UI::Input::InputSystemCursorShape
#define DUD Microsoft::UI::Dispatching
#else
#include <winrt/Windows.UI.Input.h>
#include <winrt/Windows.UI.Composition.h>
#include <winrt/Windows.UI.Xaml.h>
#include <winrt/Windows.UI.Xaml.Automation.Peers.h>
#include <winrt/Windows.UI.Xaml.Automation.Provider.h>
#include <winrt/Windows.UI.Xaml.Automation.Text.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Input.h>
#include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
#include <winrt/Windows.UI.Xaml.Data.h>
#include <winrt/Windows.UI.Xaml.Markup.h>
#include <winrt/Windows.UI.Xaml.Navigation.h>
#include <winrt/Windows.UI.Xaml.Media.Imaging.h>
#include <windows.ui.xaml.media.dxinterop.h>
#define DUX Windows::UI::Xaml
#define DUXC Windows::UI::Xaml::Controls
#define DUI Windows::UI::Input
#define DCUR Windows::UI::Core::CoreCursorType
#define DUD Windows::System
#endif
#include <d3d11_4.h>
#include <d2d1_1.h>
#include <cstddef>
#include <cstdlib>
#include <cstdint>
#include <cassert>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <climits>
#include <stdexcept>
#include <new>
#include <string>
#include <string_view>
#include <sstream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <optional>
#include <algorithm>
#include <memory>
#include <chrono>
#include <mutex>
#include <functional>
#include <olectl.h>
#include <msctf.h>
#include <appmodel.h>
#include "ScintillaTypes.h"
#include "ScintillaMessages.h"
#include "ScintillaStructures.h"
#include "ILoader.h"
#include "ILexer.h"
#include "Debugging.h"
#include "Geometry.h"
#include "Platform.h"
#include "CharacterCategoryMap.h"
#include "Position.h"
#include "UniqueString.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "CallTip.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "LineMarker.h"
#include "Style.h"
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
#include "CaseFolder.h"
#include "Document.h"
#include "CaseConvert.h"
#include "UniConversion.h"
#include "Selection.h"
#include "PositionCache.h"
#include "EditModel.h"
#include "MarginView.h"
#include "EditView.h"
#include "Editor.h"
#include "ElapsedPeriod.h"
#include "AutoComplete.h"
#include "ScintillaBase.h"
#include "Scintilla.h"
#include "Lexilla.h"
#include "SciLexer.h"
#ifndef USE_DUMMY_PAGE
#include "ControlIncludes.h"
#endif

View File

@ -1,49 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\ChangeBuild.props" />
<Import Project="..\DualBuild.props" />
<PropertyGroup>
<TargetFramework>net6.0-windows10.0.17763.0</TargetFramework>
<Platform>AnyCPU</Platform>
</PropertyGroup>
<PropertyGroup>
<CsWinRTIncludes Condition="$(WinUIEditorUseWinUI3)">WinUIEditor</CsWinRTIncludes>
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
</PropertyGroup>
<PropertyGroup>
<GeneratedNugetDir>.\nuget\</GeneratedNugetDir>
<NuspecFile Condition="$(WinUIEditorUseWinUI3)">$(GeneratedNugetDir)WinUIEditorWinUI3.nuspec</NuspecFile>
<NuspecFile Condition="!$(WinUIEditorUseWinUI3)">$(GeneratedNugetDir)WinUIEditorUWP.nuspec</NuspecFile>
<OutputPath>$(GeneratedNugetDir)</OutputPath>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<None Include="nuget\WinUIEditor.targets" />
<None Include="nuget\WinUIEditorWinUI3.nuspec" />
<None Include="nuget\WinUIEditorUWP.nuspec" />
<None Include="nuget\WinUIEditor.xml" />
<None Include="nuget\WinUIEditorCsWinRT.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" />
<PackageReference Condition="$(WinUIEditorUseWinUI3)" Include="Microsoft.WindowsAppSDK" Version="1.5.240227000" />
</ItemGroup>
<ItemGroup>
<CsWinRTInputs Condition="$(WinUIEditorUseWinUI3)" Include="..\_buildWinUI3\x64\Release\WinUIEditor\bin\WinUIEditor\WinUIEditor.winmd" />
<CsWinRTInputs Condition="!$(WinUIEditorUseWinUI3)" Include="..\_buildUwp\x64\Release\WinUIEditor\bin\WinUIEditor\WinUIEditor.winmd" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WinUIEditor\WinUIEditor.vcxproj" />
</ItemGroup>
<PropertyGroup>
<!-- Workaround for MSB3271 error on processor architecture mismatch -->
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
</Project>