引入一个外部editor试一试

This commit is contained in:
muqing 2024-08-09 15:05:40 +08:00
parent 0ddd8fdbc7
commit 5a48d4041d
52 changed files with 28934 additions and 59 deletions

3
.filenesting.json Normal file
View File

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

View File

@ -5,6 +5,8 @@ VisualStudioVersion = 17.10.34928.147
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RustTools", "RustTools\RustTools.csproj", "{2B938A8C-2116-4961-A9D7-5A755FFC1943}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{64F47B2C-DECA-42CB-AE37-EE7DC9F0035E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU

View File

@ -153,9 +153,9 @@ public partial class App : Microsoft.UI.Xaml.Application
{
//MainWindow.Activate();
//MainWindow = new MainWindow();
var editor=new Editor.EditorWin();
editor.Activate();
//await App.GetService<IActivationService>().ActivateAsync(args);
//new Editor.EditorWin().Activate();
MainWindow = new MainWindow();
await App.GetService<IActivationService>().ActivateAsync(args);
}
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY st0 "fill:#5AC8FA;">
]>
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
<path style="&st0;" d="M22.8,22.5h10c1.2,0,2.2,1.1,2.2,2.5v7.5c0,1.4-1,2.5-2.2,2.5h-10c-1.2,0-2.2-1.1-2.2-2.5V25
C20.6,23.6,21.6,22.5,22.8,22.5z"/>
<path d="M17.2,16.3c-0.7,0-1.1,0.6-1.1,1.2v15c0,0.8,0.4,1.2,1.1,1.2h15.6c0.7,0,1.1-0.5,1.1-1.2V20c0-0.8-0.6-1.3-1.1-1.3h-7.3
c-0.6,0-1.1-0.2-1.6-0.8l-1.2-1.4c-0.2-0.3-0.6-0.4-0.8-0.4H17.2z M17.2,15h4.7c0.6,0,1.1,0.2,1.6,0.8l1.2,1.4
c0.2,0.3,0.4,0.4,0.8,0.4h7.3c1.2,0,2.2,1.1,2.2,2.5v12.5c0,1.4-1,2.5-2.2,2.5H17.2C16,35,15,33.9,15,32.5v-15
C15,16.1,16,15,17.2,15z"/>
</svg>

After

Width:  |  Height:  |  Size: 1005 B

View File

@ -0,0 +1,183 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Payments;
namespace RustTools.Editor;
public class EditorLoad
{
/// <summary>
/// 加载所有的文件 Debug 用
/// </summary>
/// <param name="directoryInfo"></param>
/// <param name="parentItem"></param>
private void LoadDirectory(DirectoryInfo directoryInfo, ExplorerItem parentItem)
{
// 获取当前目录中的所有子目录
var directories = directoryInfo.GetDirectories();
foreach (var directory in directories)
{
// 创建新的 ExplorerItem 代表当前子目录
var folderItem = new ExplorerItem
{
Name = directory.Name,
Type = ExplorerItem.ExplorerItemType.Folder
};
// 将这个目录项添加到父级的 Children 集合中
parentItem.Children.Add(folderItem);
// 递归调用,继续加载子目录中的内容
LoadDirectory(directory, folderItem);
}
// 获取当前目录中的所有文件
var files = directoryInfo.GetFiles();
foreach (var file in files)
{
// 创建新的 ExplorerItem 代表当前文件
var fileItem = new ExplorerItem
{
Name = file.Name,
Type = ExplorerItem.ExplorerItemType.File
};
// 将这个文件项添加到父级的 Children 集合中
parentItem.Children.Add(fileItem);
}
}
public ObservableCollection<ExplorerItem> GetData(string dir)
{
var list = new ObservableCollection<ExplorerItem>();
var directoryInfos = new DirectoryInfo(dir);
// 创建根节点 ExplorerItem 根节点不显示防止用户删除
//var rootItem = new ExplorerItem
//{
// Name = directoryInfos.Name,
// Dir = directoryInfos.FullName,
// Type = ExplorerItem.ExplorerItemType.Folder,
//};
//LoadDirectory(directoryInfos,rootItem);
foreach (var file in directoryInfos.GetDirectories()) {
var explorerItem = new ExplorerItem()
{
Name = file.Name,
Dir = file.FullName,
Type = ExplorerItem.ExplorerItemType.Folder
};
list.Add(explorerItem);
foreach (var a in file.GetDirectories())
{
explorerItem.Children.Add(new ExplorerItem()
{
Name = a.Name,
Dir = a.FullName,
Type = ExplorerItem.ExplorerItemType.Folder
});
}
foreach (var a in file.GetFiles())
{
explorerItem.Children.Add(new ExplorerItem()
{
Name = a.Name,
Dir = a.FullName,
Type = ExplorerItem.ExplorerItemType.File
});
}
}
foreach (var file in directoryInfos.GetFiles())
{
list.Add(new ExplorerItem()
{
Name = file.Name,
Dir = file.FullName,
Type = ExplorerItem.ExplorerItemType.File
});
}
return list;
ExplorerItem folder1 = new ExplorerItem()
{
Name = "Work Documents",
Type = ExplorerItem.ExplorerItemType.Folder,
Children =
{
new ExplorerItem()
{
Name = "Functional Specifications",
Type = ExplorerItem.ExplorerItemType.Folder,
Children =
{
new ExplorerItem()
{
Name = "TreeView spec",
Type = ExplorerItem.ExplorerItemType.File,
}
}
},
new ExplorerItem()
{
Name = "Feature Schedule",
Type = ExplorerItem.ExplorerItemType.File,
},
new ExplorerItem()
{
Name = "Overall Project Plan",
Type = ExplorerItem.ExplorerItemType.File,
},
new ExplorerItem()
{
Name = "Feature Resources Allocation",
Type = ExplorerItem.ExplorerItemType.File,
}
}
};
ExplorerItem folder2 = new ExplorerItem()
{
Name = "Personal Folder",
Type = ExplorerItem.ExplorerItemType.Folder,
Children =
{
new ExplorerItem()
{
Name = "Home Remodel Folder",
Type = ExplorerItem.ExplorerItemType.Folder,
Children =
{
new ExplorerItem()
{
Name = "Contractor Contact Info",
Type = ExplorerItem.ExplorerItemType.File,
},
new ExplorerItem()
{
Name = "Paint Color Scheme",
Type = ExplorerItem.ExplorerItemType.File,
},
new ExplorerItem()
{
Name = "Flooring Woodgrain type",
Type = ExplorerItem.ExplorerItemType.File,
},
new ExplorerItem()
{
Name = "Kitchen Cabinet Style",
Type = ExplorerItem.ExplorerItemType.File,
}
}
}
}
};
list.Add(folder1);
list.Add(folder2);
return list;
}
}

View File

@ -3,6 +3,7 @@
x:Class="RustTools.Editor.EditorWin"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controlpages="using:RustTools.Editor"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:RustTools"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -11,14 +12,91 @@
MinHeight="500"
mc:Ignorable="d">
<Grid Name="grid">
<Grid Padding="9" Visibility="Visible">
<Page Name="page">
<Page.Resources>
<DataTemplate x:Key="FolderTemplate">
<TreeViewItem
AutomationProperties.Name="{Binding Name}"
IsExpanded="False"
ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE8B7;" />
<TextBlock Margin="0,0,10,0" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</TreeViewItem>
</DataTemplate>
<DataTemplate x:Key="FileTemplate">
<TreeViewItem AutomationProperties.Name="{Binding Name}">
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE8A5;" />
<TextBlock Margin="0,0,10,0" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</TreeViewItem>
</DataTemplate>
<controlpages:ExplorerItemTemplateSelector
x:Key="ExplorerItemTemplateSelector"
FileTemplate="{StaticResource FileTemplate}"
FolderTemplate="{StaticResource FolderTemplate}" />
<TabViewItem x:Key="FileTab">
<TextBox
x:Name="MyTextBox"
Height="200"
AcceptsReturn="True"
TextWrapping="Wrap" />
</TabViewItem>
</Page.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="这是模组名称" />
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid
Grid.Row="0"
Padding="9"
Visibility="Visible">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Name="TitleText"
Grid.Column="0"
Margin="16,0,0,0" />
</Grid>
<ScrollViewer
Grid.Row="2"
Grid.Column="0"
Width="300"
Margin="0,9,0,6"
Padding="0,0,16,0"
HorizontalScrollBarVisibility="Visible"
HorizontalScrollMode="Auto"
IsHorizontalRailEnabled="True"
IsHorizontalScrollChainingEnabled="True">
<TreeView
Name="treeView"
Grid.Row="2"
Grid.Column="0"
ItemInvoked="TreeView_ItemInvoked"
ItemTemplateSelector="{StaticResource ExplorerItemTemplateSelector}"
ItemsSource="{x:Bind DataSource}"
KeyDown="treeView_KeyDown"
KeyUp="treeView_KeyUp"
SelectionMode="Single" />
</ScrollViewer>
<Grid Grid.Row="1" Grid.Column="1" />
</Grid>
</Grid>
</Page>
</windowex:WindowEx>

View File

@ -1,12 +1,26 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using Microsoft.UI;
using Microsoft.UI.Text;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Documents;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using RustTools.muqing;
using Windows.ApplicationModel.Core;
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;
@ -17,7 +31,8 @@ namespace RustTools.Editor;
/// </summary>
public sealed partial class EditorWin : WindowEx
{
//目录列表
public ObservableCollection<ExplorerItem> DataSource=new ();
private Microsoft.UI.Windowing.AppWindow? app;
public EditorWin()
{
@ -28,27 +43,25 @@ public sealed partial class EditorWin : WindowEx
if (frame != null)
{
gj.UpdateTitleBar(this, frame.ActualTheme);
grid.RequestedTheme = frame.ActualTheme;
page.RequestedTheme = frame.ActualTheme;
}
//WindowManager.Get(this).IsMinimizable = false;
//WindowManager.Get(this).IsMaximizable = false;
//WindowManager.Get(this).IsResizable = false;
//WindowManager.Get(this).IsAlwaysOnTop = false;
//WindowManager.Get(this).IsTitleBarVisible = false;
//app = GetAppWindowForCurrentWindow();
//app.Closing += OnClosing;
//Closed += EditorWin_Closed;
var directoryInfo = new DirectoryInfo("D:\\steam\\steamapps\\common\\Rusted Warfare\\mods\\units\\赤道·联合进攻0.9补丁版0.2");
DataSource = new EditorLoad().GetData(directoryInfo.FullName);
Title=directoryInfo.Name;
TitleText.Text = directoryInfo.Name;
Closed += EditorWin_Closed;
}
private async Task SaveDataAsync()
{
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);
//EditorView.Editor.SetText(v);
//CodeEditorControl.HighlightingLanguage.
}
//用户有没有保存
private bool IsSave = false;
private ContentDialog? ClosedDialog;
@ -65,7 +78,7 @@ public sealed partial class EditorWin : WindowEx
// 显示一个对话框,告知用户窗口不能关闭
ClosedDialog = new ContentDialog
{
XamlRoot = grid.XamlRoot,
XamlRoot = page.XamlRoot,
Title = "警告",
Content = "你还有未保存的文件在编译器中。",
PrimaryButtonText = "保存关闭",
@ -96,4 +109,107 @@ public sealed partial class EditorWin : WindowEx
var myWndId = Win32Interop.GetWindowIdFromWindow(hWnd);
return Microsoft.UI.Windowing.AppWindow.GetFromWindowId(myWndId);
}
private void TreeView_ItemInvoked(TreeView sender, TreeViewItemInvokedEventArgs args)
{
// 获取当前选中的项
// 获取被点击的项
var invokedItem = args.InvokedItem;
// 检查是否重复选择
if (sender.SelectedItem is ExplorerItem selectedItem && invokedItem != null && selectedItem == invokedItem)
{
// 如果是同一个项,直接返回,不进行进一步处理
return;
}
if (invokedItem is not ExplorerItem explorerItem)
{
return;
}
if (explorerItem.Type == ExplorerItem.ExplorerItemType.Folder)
{
var directoryInfo = new DirectoryInfo(explorerItem.Dir);
}
}
private void TreeView_DragItemsStarting(TreeView sender, TreeViewDragItemsStartingEventArgs args)
{
args.Cancel = true;
// 设置拖动的数据
var items = args.Items.Cast<ExplorerItem>();
var v = items.ToList()[0];
args.Data.SetData("TreeViewItems", v.Dir);
args.Data.RequestedOperation = DataPackageOperation.Move;
}
//在拖动项目悬停在 TreeView 上时,为放置操作提供视觉反馈。
private void TreeView_DragOver(object sender, DragEventArgs e)
{
// 检查是否存在 "TreeViewItems" 数据
gj.sc("aaaaaa");
if (e.DataView.Contains("TreeViewItems"))
{
e.AcceptedOperation = DataPackageOperation.Move; // 允许将文件夹拖放
}
else
{
gj.sc("No");
e.AcceptedOperation = DataPackageOperation.None; // 不接受拖放操作
}
}
//处理项目放置的逻辑,将文件或文件夹移动到新的位置。
private async void TreeView_Drop(object sender, DragEventArgs e)
{
gj.sc(e);
// 获取拖动的数据
if (e.DataView.Contains("TreeViewItems"))
{
// 确保数据不为空
if (await e.DataView.GetDataAsync("TreeViewItems") is string Dir)
{
gj.sc(Dir);
// 获取放置位置的 TreeViewItem
var treeView = sender as TreeView;
ExplorerItem v = treeView.DataContext is ExplorerItem;
//var dropPosition = e.GetPosition(treeView);
//data.Name
gj.sc(v.Name);
}
}
}
private IList<object> initialSelectedItems;
/// <summary>
/// 如果是shift则开启多选状态
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void treeView_KeyDown(object sender, KeyRoutedEventArgs e)
{
// 检查是否按下了Shift键
if (e.Key == Windows.System.VirtualKey.Shift)
{
gj.sc(e.Key);
// 启用多选模式
treeView.SelectionMode = TreeViewSelectionMode.Multiple;
}
}
private void treeView_KeyUp(object sender, KeyRoutedEventArgs e)
{
// 检查是否松开了Shift键
if (e.Key == Windows.System.VirtualKey.Shift)
{ // 清除当前多选模式下选中的项目
var selectedItems = treeView.SelectedItems.ToList();
foreach (var item in selectedItems)
{
treeView.SelectedItems.Remove(item);
}
gj.sc("取消");
// 取消多选模式
treeView.SelectionMode = TreeViewSelectionMode.Single;
//treeView.SelectedItems.Clear();
}
}
private void tabView_TabCloseRequested(TabView sender, TabViewTabCloseRequestedEventArgs args)
{
sender.TabItems.Remove(args.Tab);
}
}

View File

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace RustTools.Editor;
public class ExplorerItemTemplateSelector : DataTemplateSelector
{
public DataTemplate FolderTemplate
{
get; set;
}
public DataTemplate FileTemplate
{
get; set;
}
protected override DataTemplate SelectTemplateCore(object item)
{
var explorerItem = (ExplorerItem)item;
return explorerItem.Type == ExplorerItem.ExplorerItemType.Folder ? FolderTemplate : FileTemplate;
}
}
public class ExplorerItem : INotifyPropertyChanged
{
public enum ExplorerItemType { Folder, File };
public event PropertyChangedEventHandler PropertyChanged;
public string Name
{
get; set;
}
public ExplorerItemType Type
{
get; set;
}
public string Dir
{
get;set;
}
private ObservableCollection<ExplorerItem> m_children;
public ObservableCollection<ExplorerItem> Children
{
get
{
if (m_children == null)
{
m_children = new ObservableCollection<ExplorerItem>();
}
return m_children;
}
set
{
m_children = value;
}
}
private bool m_isExpanded;
public bool IsExpanded
{
get
{
return m_isExpanded;
}
set
{
if (m_isExpanded != value)
{
m_isExpanded = value;
NotifyPropertyChanged("IsExpanded");
}
}
}
private void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public static implicit operator ExplorerItem(bool v)
{
throw new NotImplementedException();
}
}

View File

@ -19,7 +19,6 @@
<PackageReadmeFile>README.md</PackageReadmeFile>
<DefaultLanguage>zh-cn</DefaultLanguage>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
<PackageCertificateThumbprint>3386EC79D3BB9691D0A8DA634167500B242E109D</PackageCertificateThumbprint>
@ -28,7 +27,6 @@
<AppxSymbolPackageEnabled>False</AppxSymbolPackageEnabled>
<GenerateTestArtifacts>True</GenerateTestArtifacts>
<AppxBundle>Never</AppxBundle>
<AppInstallerUri>C:\\RustTools</AppInstallerUri>
<AppxPackageDir>D:\RustTools</AppxPackageDir>
</PropertyGroup>
@ -46,46 +44,19 @@
<PackageReference Include="RestSharp" Version="111.4.0" />
<PackageReference Include="System.Management" Version="8.0.0" />
<PackageReference Include="WinUIEx" Version="2.3.2" />
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240227000" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.3233" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Page Update="Views\ModulePage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Styles\TitleSubtitleControlStyle.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Styles\ItemView.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="WindowUI\ImportModule.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Views\ConcernPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Views\UserPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Views\RankingPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Views\HomePage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />
</ItemGroup>
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
</PropertyGroup>
</Project>

View File

@ -37,6 +37,7 @@ public class DataObject
get; set;
}
#pragma warning disable CS8765 // 参数类型的为 Null 性与重写成员不匹配(可能是由于为 Null 性特性)。
public override bool Equals(object obj)
{
if (obj is DataObject other)
@ -111,7 +112,8 @@ public sealed partial class ModulePage : Page
}
private void Button_Delete(object sender, RoutedEventArgs e)
{
var menuItem = sender as ButtonBase;
var menuItem = sender as Control;
gj.sc(menuItem);
if (menuItem != null)
{
if (menuItem.DataContext is DataObject folderItem)

1
UseWinUI3.txt Normal file
View File

@ -0,0 +1 @@
true

View File

@ -0,0 +1,336 @@
#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

@ -0,0 +1,75 @@
#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

@ -0,0 +1,19 @@
#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

@ -0,0 +1,669 @@
// 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

@ -0,0 +1,91 @@
// 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

@ -0,0 +1,395 @@
#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

@ -0,0 +1,557 @@
#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

@ -0,0 +1,102 @@
#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

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

213
WinUIEditor/DarkPlus.h Normal file
View File

@ -0,0 +1,213 @@
// 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);
}
}
}

5
WinUIEditor/Defines.idl Normal file
View File

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

13
WinUIEditor/DummyPage.cpp Normal file
View File

@ -0,0 +1,13 @@
#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

19
WinUIEditor/DummyPage.h Normal file
View File

@ -0,0 +1,19 @@
#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>
{
};
}

11
WinUIEditor/DummyPage.idl Normal file
View File

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

View File

@ -0,0 +1,8 @@
<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

@ -0,0 +1,665 @@
#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

@ -0,0 +1,121 @@
#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

@ -0,0 +1,15 @@
#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

@ -0,0 +1,190 @@
#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

@ -0,0 +1,43 @@
#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

@ -0,0 +1,15 @@
#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

4756
WinUIEditor/EditorWrapper.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

81
WinUIEditor/Helpers.cpp Normal file
View File

@ -0,0 +1,81 @@
#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;
}
}

8
WinUIEditor/Helpers.h Normal file
View File

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

View File

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

225
WinUIEditor/LightPlus.h Normal file
View File

@ -0,0 +1,225 @@
// 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);
}
}
}

215
WinUIEditor/TextMateScope.h Normal file
View File

@ -0,0 +1,215 @@
// 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

@ -0,0 +1,334 @@
#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

@ -0,0 +1,38 @@
#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

@ -0,0 +1,67 @@
<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

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

View File

@ -0,0 +1,847 @@
<?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

@ -0,0 +1,785 @@
<?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>

261
WinUIEditor/Wrapper.cpp Normal file
View File

@ -0,0 +1,261 @@
#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());
}
}

70
WinUIEditor/Wrapper.h Normal file
View File

@ -0,0 +1,70 @@
#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

@ -0,0 +1,7 @@
<?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>

1
WinUIEditor/pch.cpp Normal file
View File

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

144
WinUIEditor/pch.h Normal file
View File

@ -0,0 +1,144 @@
#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

@ -0,0 +1,49 @@
<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>