Compare commits

...
Author SHA1 Message Date
FelixSe 7bbed15874 Merge branch 'master' into Dev/NativeRenderer 2019-04-07 21:09:22 +02:00
FelixSe 997cb9814e fixed wrong thread event, made canvas resize 2019-04-03 23:03:24 +02:00
Andrew Kralovec 6524d14687 Native Renderer Collabate PR (#284)
* Load terminal options and add the inital scroll viewer

* Current Virtual Cavnas, problem with event handler calling the canvas on draw
2019-04-03 07:26:07 +02:00
FelixSe 7876984327 proof of concepts for vtnetcore, tterm inspired 2019-03-31 21:58:02 +02:00
24 changed files with 3180 additions and 439 deletions

No files matched your search

+472 -438
View File
@@ -1,445 +1,479 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{41020100-3414-4E0A-9A8E-92D3C4179DF8}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FluentTerminal.App</RootNamespace>
<AssemblyName>FluentTerminal.App</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.16299.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.16299.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
<PackageCertificateKeyFile>FluentTerminal.App_TemporaryKey.pfx</PackageCertificateKeyFile>
<PackageCertificateThumbprint>F96F3E0E485F07E8E98DA6E5C06AA4B6F112B498</PackageCertificateThumbprint>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
<AppxBundle>Always</AppxBundle>
<AppxBundlePlatforms>x86|x64</AppxBundlePlatforms>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<AppInstallerUpdateFrequency>1</AppInstallerUpdateFrequency>
<AppInstallerCheckForUpdateFrequency>OnApplicationRun</AppInstallerCheckForUpdateFrequency>
<AppxSymbolPackageEnabled>True</AppxSymbolPackageEnabled>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<Compile Include="Adapters\ApplicationViewAdapter.cs" />
<Compile Include="Adapters\AppServiceConnectionAdapter.cs" />
<Compile Include="Adapters\DispatcherTimerAdapter.cs" />
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Behaviors\MiddleClickBehavior.cs" />
<Compile Include="CommandLineArguments\NewVerb.cs" />
<Compile Include="CommandLineArguments\RunVerb.cs" />
<Compile Include="CommandLineArguments\SettingsVerb.cs" />
<Compile Include="CommandLineArguments\Target.cs" />
<Compile Include="Converters\BackgroundToApplicationThemeConverter.cs" />
<Compile Include="Converters\ColorResourceKeyFallbackConverter.cs" />
<Compile Include="Converters\EnumToDescriptionConverter.cs" />
<Compile Include="Converters\TabColorFallbackConverter.cs" />
<Compile Include="Converters\EnumValueToVisibiltyConverter.cs" />
<Compile Include="Converters\FalseToVisibleConverter.cs" />
<Compile Include="Converters\IntToExtendedVirtualKeyConverter.cs" />
<Compile Include="Converters\IntToVisibilityConverter.cs" />
<Compile Include="Converters\NegateConverter.cs" />
<Compile Include="Converters\StringToColorConverter.cs" />
<Compile Include="Converters\TabThemeSelectedConverter.cs" />
<Compile Include="Converters\TerminalViewModelToViewConverter.cs" />
<Compile Include="Converters\ToolTipValueToPixelConverter.cs" />
<Compile Include="Converters\TrueToBoldConverter.cs" />
<Compile Include="Converters\TrueToVisibleConverter.cs" />
<Compile Include="Adapters\MessageDialogAdapter.cs" />
<Compile Include="Dialogs\InputDialog.xaml.cs">
<DependentUpon>InputDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Dialogs\ShellProfileSelectionDialog.xaml.cs">
<DependentUpon>ShellProfileSelectionDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Services\ClipboardService.cs" />
<Compile Include="Services\FileSystemService.cs" />
<Compile Include="Services\StartupTaskService.cs" />
<Compile Include="Services\SystemFontService.cs" />
<Compile Include="Utilities\ColorExtensions.cs" />
<Compile Include="Utilities\ContrastHelper.cs" />
<Compile Include="Utilities\DebouncedAction.cs" />
<Compile Include="Views\KeyBindingsView.xaml.cs">
<DependentUpon>KeyBindingsView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Dialogs\CreateKeyBindingDialog.xaml.cs">
<DependentUpon>CreateKeyBindingDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPage.xaml.cs">
<DependentUpon>SettingsPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\About.xaml.cs">
<DependentUpon>About.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\MouseSettings.xaml.cs">
<DependentUpon>MouseSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\ThemeSettings.xaml.cs">
<DependentUpon>ThemeSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\TerminalSettings.xaml.cs">
<DependentUpon>TerminalSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\GeneralSettings.xaml.cs">
<DependentUpon>GeneralSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\KeyBindingSettings.xaml.cs">
<DependentUpon>KeyBindingSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\ShellProfileSettings.xaml.cs">
<DependentUpon>ShellProfileSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Dialogs\SshInfoDialog.xaml.cs">
<DependentUpon>SshInfoDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Views\TabBar.xaml.cs">
<DependentUpon>TabBar.xaml</DependentUpon>
</Compile>
<Compile Include="Views\TabBarBackgroundBindingHelper.cs" />
<Compile Include="Views\TerminalKeybindTemplateSelector.cs" />
<Compile Include="Views\TabThemeTemplateSelector.cs" />
<Compile Include="Views\TerminalColorPicker.xaml.cs">
<DependentUpon>TerminalColorPicker.xaml</DependentUpon>
</Compile>
<Compile Include="Views\NoValueTemplateSelector.cs" />
<Compile Include="Views\TerminalThemeTemplateSelector.cs" />
<Compile Include="Views\ITerminalView.cs" />
<Compile Include="Views\TerminalView.xaml.cs">
<DependentUpon>TerminalView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\XtermTerminalView.xaml.cs">
<DependentUpon>XtermTerminalView.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<Content Include="Assets\AppIcons\Square106x106Logo.black.png" />
<Content Include="Assets\settingsicons.ttf" />
<Content Include="Win32\Autofac.dll" />
<Content Include="Win32\FluentTerminal.App.Services.dll" />
<Content Include="Win32\FluentTerminal.App.Services.pdb" />
<Content Include="Win32\FluentTerminal.Models.dll" />
<Content Include="Win32\FluentTerminal.Models.pdb" />
<Content Include="Win32\FluentTerminal.SystemTray.exe" />
<Content Include="Win32\FluentTerminal.SystemTray.pdb" />
<Content Include="Win32\GlobalHotKey.dll" />
<Content Include="Win32\Newtonsoft.Json.dll" />
<Content Include="Win32\PListNet.dll" />
<Content Include="Win32\RestSharp.dll" />
<Content Include="Win32\Serilog.dll" />
<Content Include="Win32\Serilog.Sinks.Async.dll" />
<Content Include="Win32\Serilog.Sinks.File.dll" />
<Content Include="Win32\System.Data.Common.dll" />
<Content Include="Win32\System.Diagnostics.StackTrace.dll" />
<Content Include="Win32\System.Diagnostics.Tracing.dll" />
<Content Include="Win32\System.Globalization.Extensions.dll" />
<Content Include="Win32\System.IO.Compression.dll" />
<Content Include="Win32\System.Net.Http.dll" />
<Content Include="Win32\System.Net.Sockets.dll" />
<Content Include="Win32\System.Runtime.Serialization.Primitives.dll" />
<Content Include="Win32\System.Security.Cryptography.Algorithms.dll" />
<Content Include="Win32\System.Security.SecureString.dll" />
<Content Include="Win32\System.Threading.Overlapped.dll" />
<Content Include="Win32\System.Xml.XPath.XDocument.dll" />
<Content Include="Win32\winpty-agent.exe" />
<Content Include="Win32\winpty-debugserver.exe" />
<Content Include="Win32\winpty.dll" />
<Content Include="Win32\winpty.NET.dll" />
<None Include="FluentTerminal.App_StoreKey.pfx" />
<Content Include="Client\bundle.js" />
<Content Include="Client\index.html" />
<Content Include="Client\style.css" />
<Content Include="Client\xterm.css" />
<Content Include="Win32\FluentTerminal.SystemTray.exe.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\AppIcons\LargeTile.scale-100.png" />
<Content Include="Assets\AppIcons\LargeTile.scale-125.png" />
<Content Include="Assets\AppIcons\LargeTile.scale-150.png" />
<Content Include="Assets\AppIcons\LargeTile.scale-200.png" />
<Content Include="Assets\AppIcons\LargeTile.scale-400.png" />
<Content Include="Assets\AppIcons\SmallTile.scale-100.png" />
<Content Include="Assets\AppIcons\SmallTile.scale-125.png" />
<Content Include="Assets\AppIcons\SmallTile.scale-150.png" />
<Content Include="Assets\AppIcons\SmallTile.scale-200.png" />
<Content Include="Assets\AppIcons\SmallTile.scale-400.png" />
<Content Include="Assets\AppIcons\SplashScreen.scale-100.png" />
<Content Include="Assets\AppIcons\SplashScreen.scale-125.png" />
<Content Include="Assets\AppIcons\SplashScreen.scale-150.png" />
<Content Include="Assets\AppIcons\SplashScreen.scale-200.png" />
<Content Include="Assets\AppIcons\SplashScreen.scale-400.png" />
<Content Include="Assets\AppIcons\Square150x150Logo.scale-100.png" />
<Content Include="Assets\AppIcons\Square150x150Logo.scale-125.png" />
<Content Include="Assets\AppIcons\Square150x150Logo.scale-150.png" />
<Content Include="Assets\AppIcons\Square150x150Logo.scale-200.png" />
<Content Include="Assets\AppIcons\Square150x150Logo.scale-400.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-16.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-24.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-256.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-32.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-48.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.scale-100.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.scale-125.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.scale-150.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.scale-200.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.scale-400.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-16.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-24.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-256.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-32.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-48.png" />
<Content Include="Assets\AppIcons\StoreLogo.scale-100.png" />
<Content Include="Assets\AppIcons\StoreLogo.scale-125.png" />
<Content Include="Assets\AppIcons\StoreLogo.scale-150.png" />
<Content Include="Assets\AppIcons\StoreLogo.scale-200.png" />
<Content Include="Assets\AppIcons\StoreLogo.scale-400.png" />
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-100.png" />
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-125.png" />
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-150.png" />
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-200.png" />
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-400.png" />
<Content Include="Properties\Default.rd.xml" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="Dialogs\InputDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Dialogs\ShellProfileSelectionDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\KeyBindingsView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Styles\Custom.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="Dialogs\CreateKeyBindingDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\About.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\SettingsPages\MouseSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\ThemeSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\TerminalSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\GeneralSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\KeyBindingSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\ShellProfileSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Dialogs\SshInfoDialog.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\TabBar.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\TerminalColorPicker.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\TerminalView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\XtermTerminalView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac">
<Version>4.9.1</Version>
</PackageReference>
<PackageReference Include="CommandLineParser">
<Version>2.4.3</Version>
</PackageReference>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.2.8</Version>
</PackageReference>
<PackageReference Include="Microsoft.Toolkit.Uwp.UI">
<Version>5.1.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls">
<Version>5.1.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.Xaml.Behaviors.Uwp.Managed">
<Version>2.0.0</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>12.0.1</Version>
</PackageReference>
<PackageReference Include="Win2D.uwp">
<Version>1.21.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<SDKReference Include="WindowsDesktop, Version=10.0.16299.0">
<Name>Windows Desktop Extensions for the UWP</Name>
</SDKReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FluentTerminal.App.Services\FluentTerminal.App.Services.csproj">
<Project>{a1ad7385-f92e-46ac-a349-43dc99b1e72d}</Project>
<Name>FluentTerminal.App.Services</Name>
</ProjectReference>
<ProjectReference Include="..\FluentTerminal.App.ViewModels\FluentTerminal.App.ViewModels.csproj">
<Project>{44e8e225-f46c-47ec-9290-ffa08fccf1b5}</Project>
<Name>FluentTerminal.App.ViewModels</Name>
</ProjectReference>
<ProjectReference Include="..\FluentTerminal.Models\FluentTerminal.Models.csproj">
<Project>{5EA40453-A0AA-449E-8406-D6EA51D7E70E}</Project>
<Name>FluentTerminal.Models</Name>
</ProjectReference>
<ProjectReference Include="..\FluentTerminal.RuntimeComponent\FluentTerminal.RuntimeComponent.csproj">
<Project>{BAAE6239-343F-454C-977F-F81F91715961}</Project>
<Name>FluentTerminal.RuntimeComponent</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<PreBuildEvent>xcopy /y "$(SolutionDir)FluentTerminal.Client\dist" "$(ProjectDir)Client\"</PreBuildEvent>
</PropertyGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{41020100-3414-4E0A-9A8E-92D3C4179DF8}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FluentTerminal.App</RootNamespace>
<AssemblyName>FluentTerminal.App</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.16299.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.16299.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
<PackageCertificateKeyFile>FluentTerminal.App_TemporaryKey.pfx</PackageCertificateKeyFile>
<PackageCertificateThumbprint>F96F3E0E485F07E8E98DA6E5C06AA4B6F112B498</PackageCertificateThumbprint>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
<AppxBundle>Always</AppxBundle>
<AppxBundlePlatforms>x86|x64</AppxBundlePlatforms>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<AppInstallerUpdateFrequency>1</AppInstallerUpdateFrequency>
<AppInstallerCheckForUpdateFrequency>OnApplicationRun</AppInstallerCheckForUpdateFrequency>
<AppxSymbolPackageEnabled>True</AppxSymbolPackageEnabled>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<Compile Include="Adapters\ApplicationViewAdapter.cs" />
<Compile Include="Adapters\AppServiceConnectionAdapter.cs" />
<Compile Include="Adapters\DispatcherTimerAdapter.cs" />
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Behaviors\MiddleClickBehavior.cs" />
<Compile Include="CommandLineArguments\NewVerb.cs" />
<Compile Include="CommandLineArguments\RunVerb.cs" />
<Compile Include="CommandLineArguments\SettingsVerb.cs" />
<Compile Include="CommandLineArguments\Target.cs" />
<Compile Include="Converters\BackgroundToApplicationThemeConverter.cs" />
<Compile Include="Converters\ColorResourceKeyFallbackConverter.cs" />
<Compile Include="Converters\EnumToDescriptionConverter.cs" />
<Compile Include="Converters\TabColorFallbackConverter.cs" />
<Compile Include="Converters\EnumValueToVisibiltyConverter.cs" />
<Compile Include="Converters\FalseToVisibleConverter.cs" />
<Compile Include="Converters\IntToExtendedVirtualKeyConverter.cs" />
<Compile Include="Converters\IntToVisibilityConverter.cs" />
<Compile Include="Converters\NegateConverter.cs" />
<Compile Include="Converters\StringToColorConverter.cs" />
<Compile Include="Converters\TabThemeSelectedConverter.cs" />
<Compile Include="Converters\TerminalViewModelToViewConverter.cs" />
<Compile Include="Converters\ToolTipValueToPixelConverter.cs" />
<Compile Include="Converters\TrueToBoldConverter.cs" />
<Compile Include="Converters\TrueToVisibleConverter.cs" />
<Compile Include="Adapters\MessageDialogAdapter.cs" />
<Compile Include="Dialogs\InputDialog.xaml.cs">
<DependentUpon>InputDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Dialogs\ShellProfileSelectionDialog.xaml.cs">
<DependentUpon>ShellProfileSelectionDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Services\ClipboardService.cs" />
<Compile Include="Services\FileSystemService.cs" />
<Compile Include="Services\StartupTaskService.cs" />
<Compile Include="Services\SystemFontService.cs" />
<Compile Include="Utilities\ColorExtensions.cs" />
<Compile Include="Utilities\ContrastHelper.cs" />
<Compile Include="Utilities\DebouncedAction.cs" />
<Compile Include="Views\KeyBindingsView.xaml.cs">
<DependentUpon>KeyBindingsView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Dialogs\CreateKeyBindingDialog.xaml.cs">
<DependentUpon>CreateKeyBindingDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Views\NativeFrontend\Ansi\AnsiParser.cs" />
<Compile Include="Views\NativeFrontend\Ansi\C0.cs" />
<Compile Include="Views\NativeFrontend\Ansi\CharAttributes.cs" />
<Compile Include="Views\NativeFrontend\Ansi\TerminalCode.cs" />
<Compile Include="Views\NativeFrontend\Ansi\TerminalCodeType.cs" />
<Compile Include="Views\NativeFrontend\TerminalColorHelper.cs" />
<Compile Include="Views\NativeFrontend\TerminalControl.xaml.cs">
<DependentUpon>TerminalControl.xaml</DependentUpon>
</Compile>
<Compile Include="Views\NativeFrontend\Terminal\SelectionMode.cs" />
<Compile Include="Views\NativeFrontend\Terminal\SpecialColorIds.cs" />
<Compile Include="Views\NativeFrontend\Terminal\TerminalBuffer.cs" />
<Compile Include="Views\NativeFrontend\Terminal\TerminalBufferChar.cs" />
<Compile Include="Views\NativeFrontend\Terminal\TerminalBufferLine.cs" />
<Compile Include="Views\NativeFrontend\Terminal\TerminalPoint.cs" />
<Compile Include="Views\NativeFrontend\Terminal\TerminalSelection.cs" />
<Compile Include="Views\NativeFrontend\Terminal\TerminalSize.cs" />
<Compile Include="Views\NativeFrontend\Terminal\TerminalTag.cs" />
<Compile Include="Views\NativeFrontend\Terminal\TerminalTagArray.cs" />
<Compile Include="Views\NativeFrontend\Utility\ArrayReader.cs" />
<Compile Include="Views\SettingsPage.xaml.cs">
<DependentUpon>SettingsPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\About.xaml.cs">
<DependentUpon>About.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\MouseSettings.xaml.cs">
<DependentUpon>MouseSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\ThemeSettings.xaml.cs">
<DependentUpon>ThemeSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\TerminalSettings.xaml.cs">
<DependentUpon>TerminalSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\GeneralSettings.xaml.cs">
<DependentUpon>GeneralSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\KeyBindingSettings.xaml.cs">
<DependentUpon>KeyBindingSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPages\ShellProfileSettings.xaml.cs">
<DependentUpon>ShellProfileSettings.xaml</DependentUpon>
</Compile>
<Compile Include="Dialogs\SshInfoDialog.xaml.cs">
<DependentUpon>SshInfoDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Views\TabBar.xaml.cs">
<DependentUpon>TabBar.xaml</DependentUpon>
</Compile>
<Compile Include="Views\TabBarBackgroundBindingHelper.cs" />
<Compile Include="Views\TerminalKeybindTemplateSelector.cs" />
<Compile Include="Views\TabThemeTemplateSelector.cs" />
<Compile Include="Views\TerminalColorPicker.xaml.cs">
<DependentUpon>TerminalColorPicker.xaml</DependentUpon>
</Compile>
<Compile Include="Views\NoValueTemplateSelector.cs" />
<Compile Include="Views\TerminalThemeTemplateSelector.cs" />
<Compile Include="Views\ITerminalView.cs" />
<Compile Include="Views\TerminalView.xaml.cs">
<DependentUpon>TerminalView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\VtNetCoreFrontend\VtNetCoreTerminal.xaml.cs">
<DependentUpon>VtNetCoreTerminal.xaml</DependentUpon>
</Compile>
<Compile Include="Views\XtermTerminalView.xaml.cs">
<DependentUpon>XtermTerminalView.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<Content Include="Assets\AppIcons\Square106x106Logo.black.png" />
<Content Include="Assets\settingsicons.ttf" />
<Content Include="Win32\Autofac.dll" />
<Content Include="Win32\FluentTerminal.App.Services.dll" />
<Content Include="Win32\FluentTerminal.App.Services.pdb" />
<Content Include="Win32\FluentTerminal.Models.dll" />
<Content Include="Win32\FluentTerminal.Models.pdb" />
<Content Include="Win32\FluentTerminal.SystemTray.exe" />
<Content Include="Win32\FluentTerminal.SystemTray.pdb" />
<Content Include="Win32\GlobalHotKey.dll" />
<Content Include="Win32\Newtonsoft.Json.dll" />
<Content Include="Win32\PListNet.dll" />
<Content Include="Win32\RestSharp.dll" />
<Content Include="Win32\Serilog.dll" />
<Content Include="Win32\Serilog.Sinks.Async.dll" />
<Content Include="Win32\Serilog.Sinks.File.dll" />
<Content Include="Win32\System.Data.Common.dll" />
<Content Include="Win32\System.Diagnostics.StackTrace.dll" />
<Content Include="Win32\System.Diagnostics.Tracing.dll" />
<Content Include="Win32\System.Globalization.Extensions.dll" />
<Content Include="Win32\System.IO.Compression.dll" />
<Content Include="Win32\System.Net.Http.dll" />
<Content Include="Win32\System.Net.Sockets.dll" />
<Content Include="Win32\System.Runtime.Serialization.Primitives.dll" />
<Content Include="Win32\System.Security.Cryptography.Algorithms.dll" />
<Content Include="Win32\System.Security.SecureString.dll" />
<Content Include="Win32\System.Threading.Overlapped.dll" />
<Content Include="Win32\System.Xml.XPath.XDocument.dll" />
<Content Include="Win32\winpty-agent.exe" />
<Content Include="Win32\winpty-debugserver.exe" />
<Content Include="Win32\winpty.dll" />
<Content Include="Win32\winpty.NET.dll" />
<None Include="FluentTerminal.App_StoreKey.pfx" />
<Content Include="Client\bundle.js" />
<Content Include="Client\index.html" />
<Content Include="Client\style.css" />
<Content Include="Client\xterm.css" />
<Content Include="Win32\FluentTerminal.SystemTray.exe.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\AppIcons\LargeTile.scale-100.png" />
<Content Include="Assets\AppIcons\LargeTile.scale-125.png" />
<Content Include="Assets\AppIcons\LargeTile.scale-150.png" />
<Content Include="Assets\AppIcons\LargeTile.scale-200.png" />
<Content Include="Assets\AppIcons\LargeTile.scale-400.png" />
<Content Include="Assets\AppIcons\SmallTile.scale-100.png" />
<Content Include="Assets\AppIcons\SmallTile.scale-125.png" />
<Content Include="Assets\AppIcons\SmallTile.scale-150.png" />
<Content Include="Assets\AppIcons\SmallTile.scale-200.png" />
<Content Include="Assets\AppIcons\SmallTile.scale-400.png" />
<Content Include="Assets\AppIcons\SplashScreen.scale-100.png" />
<Content Include="Assets\AppIcons\SplashScreen.scale-125.png" />
<Content Include="Assets\AppIcons\SplashScreen.scale-150.png" />
<Content Include="Assets\AppIcons\SplashScreen.scale-200.png" />
<Content Include="Assets\AppIcons\SplashScreen.scale-400.png" />
<Content Include="Assets\AppIcons\Square150x150Logo.scale-100.png" />
<Content Include="Assets\AppIcons\Square150x150Logo.scale-125.png" />
<Content Include="Assets\AppIcons\Square150x150Logo.scale-150.png" />
<Content Include="Assets\AppIcons\Square150x150Logo.scale-200.png" />
<Content Include="Assets\AppIcons\Square150x150Logo.scale-400.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-16.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-24.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-256.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-32.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.altform-unplated_targetsize-48.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.scale-100.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.scale-125.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.scale-150.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.scale-200.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.scale-400.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-16.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-24.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-256.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-32.png" />
<Content Include="Assets\AppIcons\Square44x44Logo.targetsize-48.png" />
<Content Include="Assets\AppIcons\StoreLogo.scale-100.png" />
<Content Include="Assets\AppIcons\StoreLogo.scale-125.png" />
<Content Include="Assets\AppIcons\StoreLogo.scale-150.png" />
<Content Include="Assets\AppIcons\StoreLogo.scale-200.png" />
<Content Include="Assets\AppIcons\StoreLogo.scale-400.png" />
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-100.png" />
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-125.png" />
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-150.png" />
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-200.png" />
<Content Include="Assets\AppIcons\Wide310x150Logo.scale-400.png" />
<Content Include="Properties\Default.rd.xml" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="Dialogs\InputDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Dialogs\ShellProfileSelectionDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\KeyBindingsView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Styles\Custom.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="Dialogs\CreateKeyBindingDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\NativeFrontend\TerminalControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\About.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\SettingsPages\MouseSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\ThemeSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\TerminalSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\GeneralSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\KeyBindingSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsPages\ShellProfileSettings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Dialogs\SshInfoDialog.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\TabBar.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\TerminalColorPicker.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\TerminalView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\VtNetCoreFrontend\VtNetCoreTerminal.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\XtermTerminalView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac">
<Version>4.9.1</Version>
</PackageReference>
<PackageReference Include="CommandLineParser">
<Version>2.4.3</Version>
</PackageReference>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.2.8</Version>
</PackageReference>
<PackageReference Include="Microsoft.Toolkit.Uwp.UI">
<Version>5.1.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls">
<Version>5.1.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.Xaml.Behaviors.Uwp.Managed">
<Version>2.0.0</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>12.0.1</Version>
</PackageReference>
<PackageReference Include="VtNetCore">
<Version>1.0.15</Version>
</PackageReference>
<PackageReference Include="Win2D.uwp">
<Version>1.21.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<SDKReference Include="WindowsDesktop, Version=10.0.16299.0">
<Name>Windows Desktop Extensions for the UWP</Name>
</SDKReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FluentTerminal.App.Services\FluentTerminal.App.Services.csproj">
<Project>{a1ad7385-f92e-46ac-a349-43dc99b1e72d}</Project>
<Name>FluentTerminal.App.Services</Name>
</ProjectReference>
<ProjectReference Include="..\FluentTerminal.App.ViewModels\FluentTerminal.App.ViewModels.csproj">
<Project>{44e8e225-f46c-47ec-9290-ffa08fccf1b5}</Project>
<Name>FluentTerminal.App.ViewModels</Name>
</ProjectReference>
<ProjectReference Include="..\FluentTerminal.Models\FluentTerminal.Models.csproj">
<Project>{5EA40453-A0AA-449E-8406-D6EA51D7E70E}</Project>
<Name>FluentTerminal.Models</Name>
</ProjectReference>
<ProjectReference Include="..\FluentTerminal.RuntimeComponent\FluentTerminal.RuntimeComponent.csproj">
<Project>{BAAE6239-343F-454C-977F-F81F91715961}</Project>
<Name>FluentTerminal.RuntimeComponent</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<PreBuildEvent>xcopy /y "$(SolutionDir)FluentTerminal.Client\dist" "$(ProjectDir)Client\"</PreBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
-->
</Project>
@@ -0,0 +1,679 @@
using FluentTerminal.App.Views.NativeFrontend.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Ansi
{
internal class AnsiParser
{
private ParserState _state;
private int _position;
private object _currentParam;
private List<object> _params = new List<object>();
private List<TerminalCode> _terminalCodes = new List<TerminalCode>();
/// <summary>
/// CSI codes can have prefixes of '?', '>'
/// </summary>
private string _prefix;
/// <summary>
/// CSI codes can have postfixes of '$',
/// </summary>
private string _postfix;
private readonly StringBuilder _currentTextEmit = new StringBuilder(capacity: 128);
public TerminalCode[] Parse(ArrayReader<char> reader)
{
_terminalCodes.Clear();
while (reader.TryRead(out char ch))
{
int code = ch;
// if (0xD800 <= code && code <= 0xDBFF)
// {
// // we got a surrogate high
// // get surrogate low (next 2 bytes)
// if (!reader.TryPeek(out char low))
// {
// // end of data stream, save surrogate high
// // this._terminal.surrogate_high = ch;
// continue;
// }
// code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
// // ch += low;
// }
// // surrogate low - already handled above
// if (0xDC00 <= code && code <= 0xDFFF)
// {
// continue;
// }
switch (_state)
{
case ParserState.Normal:
if (!NormalStateHandler(ch))
{
Emit(ch);
}
break;
case ParserState.Escaped:
if (!EscapedStateHandler(ch))
{
switch (ch)
{
// ESC (,),*,+,-,. Designate G0-G2 Character Set.
case '(': // <-- this seems to get all the attention
// this._terminal.gcharset = 0;
_state = ParserState.Charset;
break;
case ')':
case '-':
// this._terminal.gcharset = 1;
_state = ParserState.Charset;
break;
case '*':
case '.':
// this._terminal.gcharset = 2;
_state = ParserState.Charset;
break;
case '+':
// this._terminal.gcharset = 3;
_state = ParserState.Charset;
break;
// Designate G3 Character Set (VT300).
// A = ISO Latin-1 Supplemental.
// Not implemented.
case '/':
// _terminal.gcharset = 3;
_state = ParserState.Charset;
// _position--
break;
// ESC N
// Single Shift Select of G2 Character Set
// ( SS2 is 0x8e). This affects next character only.
case 'N':
break;
// ESC O
// Single Shift Select of G3 Character Set
// ( SS3 is 0x8f). This affects next character only.
case 'O':
break;
// ESC n
// Invoke the G2 Character Set as GL (LS2).
case 'n':
// this._terminal.setgLevel(2);
break;
// ESC o
// Invoke the G3 Character Set as GL (LS3).
case 'o':
// this._terminal.setgLevel(3);
break;
// ESC |
// Invoke the G3 Character Set as GR (LS3R).
case '|':
// this._terminal.setgLevel(3);
break;
// ESC }
// Invoke the G2 Character Set as GR (LS2R).
case '}':
// this._terminal.setgLevel(2);
break;
// ESC ~
// Invoke the G1 Character Set as GR (LS1R).
case '~':
// this._terminal.setgLevel(1);
break;
// ESC 7 Save Cursor (DECSC).
case '7':
Emit(TerminalCodeType.SaveCursor);
_state = ParserState.Normal;
break;
// ESC 8 Restore Cursor (DECRC).
case '8':
Emit(TerminalCodeType.RestoreCursor);
_state = ParserState.Normal;
break;
// ESC # 3 DEC line height/width
case '#':
_state = ParserState.Normal;
// _position++;
break;
// ESC H Tab Set (HTS is 0x88).
case 'H':
Emit(TerminalCodeType.TabSet);
_state = ParserState.Normal;
break;
// ESC = Application Keypad (DECKPAM).
case '=':
// this._terminal.log('Serial port requested application keypad.');
// this._terminal.applicationKeypad = true;
// this._terminal.viewport.syncScrollArea();
_state = ParserState.Normal;
break;
// ESC > Normal Keypad (DECKPNM).
case '>':
// this._terminal.log('Switching back to normal keypad.');
// this._terminal.applicationKeypad = false;
// this._terminal.viewport.syncScrollArea();
_state = ParserState.Normal;
break;
default:
_state = ParserState.Normal;
// _terminal.error('Unknown ESC control: %s.', ch);
break;
}
}
break;
case ParserState.Charset:
// if (ch in CHARSETS)
// {
// cs = CHARSETS[ch];
// if (ch === '/')
// { // ISOLatin is actually /A
// this.skipNextChar();
// }
// }
// else
// {
// cs = DEFAULT_CHARSET;
// }
// this._terminal.setgCharset(this._terminal.gcharset, cs);
// this._terminal.gcharset = null;
_state = ParserState.Normal;
break;
case ParserState.Osc:
// OSC Ps ; Pt ST
// OSC Ps ; Pt BEL
// Set Text Parameters.
if (ch == C0.ESC || ch == C0.BEL)
{
if (ch == C0.ESC)
{
_position++;
}
_params.Add(_currentParam);
switch ((int)_params[0])
{
case 0:
case 1:
case 2:
if (_params.Count >= 1 && _params[1] != null)
{
Emit(new TerminalCode(TerminalCodeType.SetTitle, (string)_params[1]));
}
break;
case 3:
// set X property
break;
case 4:
case 5:
// change dynamic colors
break;
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
// change dynamic ui colors
break;
case 46:
// change log file
break;
case 50:
// dynamic font
break;
case 51:
// emacs shell
break;
case 52:
// manipulate selection data
break;
case 104:
case 105:
case 110:
case 111:
case 112:
case 113:
case 114:
case 115:
case 116:
case 117:
case 118:
// reset colors
break;
}
_params.Clear();
_currentParam = 0;
_state = ParserState.Normal;
}
else
{
if (_params.Count == 0)
{
if (ch >= '0' && ch <= '9')
{
_currentParam = ((int)_currentParam * 10) + ch - 48;
}
else if (ch == ';')
{
_params.Add(_currentParam);
_currentParam = "";
}
}
else
{
_currentParam = (string)_currentParam + ch;
}
}
break;
case ParserState.CsiParam:
if (!CsiParamStateHandler(ch))
{
FinaliseParam();
_state = ParserState.Csi;
goto case ParserState.Csi;
}
break;
case ParserState.Csi:
if (!CsiStateHandler(ch))
{
//throw new Exception($"Unknown CSI code: {ch}"); // conpty is sending 'X' ?!
}
_state = ParserState.Normal;
_prefix = "";
_postfix = "";
break;
case ParserState.Dcs:
if (ch == C0.ESC || ch == C0.BEL)
{
if (ch == C0.ESC)
{
// _position++;
}
switch (_prefix)
{
// User-Defined Keys (DECUDK)
case "":
break;
// Request Status String (DECRQSS).
// test: echo -e '\eP$q"p\e\\'
case "$q":
{
string pt = (string)_currentParam;
bool valid = false;
switch (pt)
{
// DECSCA
case "\"q":
pt = "0\"q";
break;
// DECSCL
case "\"p":
pt = "61\"p";
break;
// DECSTBM
case "r":
// pt = ""
// + (this._terminal.scrollTop + 1)
// + ";"
// + (this._terminal.scrollBottom + 1)
// + "r";
break;
// SGR
case "m":
pt = "0m";
break;
default:
throw new Exception($"Unknown DCS Pt: {pt}.");
pt = "";
break;
}
// this._terminal.send(C0.ESC + 'P' + +valid + '$r' + pt + C0.ESC + '\\');
break;
}
// Set Termcap/Terminfo Data (xterm, experimental).
case "+p":
break;
// Request Termcap/Terminfo String (xterm, experimental)
// Regular xterm does not even respond to this sequence.
// This can cause a small glitch in vim.
// test: echo -ne '\eP+q6b64\e\\'
case "+q":
{
string pt = (string)_currentParam;
bool valid = false;
// this._terminal.send(C0.ESC + 'P' + +valid + '+r' + pt + C0.ESC + '\\');
break;
}
default:
throw new Exception($"Unknown DCS prefix: {_prefix}");
break;
}
_currentParam = 0;
_prefix = "";
_state = ParserState.Normal;
}
else if (_currentParam == null)
{
if (_prefix.Length == 0 && ch != '$' && ch != '+')
{
_currentParam = ch;
}
else if (_prefix.Length == 2)
{
_currentParam = ch;
}
else
{
_prefix += ch;
}
}
else
{
_currentParam = (string)_currentParam + ch;
}
break;
case ParserState.Ignore:
// For PM and APC.
if (ch == C0.ESC || ch == C0.BEL)
{
if (ch == C0.ESC)
{
_position++;
}
_state = ParserState.Normal;
}
break;
}
}
FinialiseEmit();
return _terminalCodes.ToArray();
}
private bool NormalStateHandler(char c)
{
switch (c)
{
case C0.BEL:
Emit(TerminalCodeType.Bell);
return true;
case C0.LF:
case C0.VT:
case C0.FF:
Emit(TerminalCodeType.LineFeed);
return true;
case C0.CR:
Emit(TerminalCodeType.CarriageReturn);
return true;
case C0.BS:
Emit(TerminalCodeType.Backspace);
return true;
case C0.HT:
Emit(TerminalCodeType.Tab);
return true;
case C0.SO:
Emit(TerminalCodeType.ShiftOut);
return true;
case C0.SI:
Emit(TerminalCodeType.ShiftIn);
return true;
case C0.ESC:
_state = ParserState.Escaped;
return true;
default:
return false;
}
}
private bool EscapedStateHandler(char ch)
{
switch (ch)
{
case '[':
// ESC [ Control Sequence Introducer (CSI is 0x9b)
_params.Clear();
_currentParam = 0;
_state = ParserState.CsiParam;
return true;
case ']':
// ESC ] Operating System Command (OSC is 0x9d)
_params.Clear();
_currentParam = 0;
_state = ParserState.Osc;
return true;
case 'P':
// ESC P Device Control String (DCS is 0x90)
_params.Clear();
_currentParam = 0;
_state = ParserState.Dcs;
return true;
case '_':
// ESC _ Application Program Command ( APC is 0x9f).
_state = ParserState.Ignore;
return true;
case '^':
// ESC ^ Privacy Message ( PM is 0x9e).
_state = ParserState.Ignore;
return true;
case 'c':
// ESC c Full Reset (RIS).
Emit(TerminalCodeType.Reset);
return true;
case 'E':
// ESC E Next Line ( NEL is 0x85).
// terminal.x = 0;
// termina.index();
_state = ParserState.Normal;
return true;
case 'D':
// ESC D Index ( IND is 0x84).
// terminal.index();
_state = ParserState.Normal;
return true;
case 'M':
// ESC M Reverse Index ( RI is 0x8d).
// terminal.reverseIndex();
_state = ParserState.Normal;
return true;
case '%':
// ESC % Select default/utf-8 character set.
// @ = default, G = utf-8
// terminal.setgLevel(0);
// terminal.setgCharset(0, DEFAULT_CHARSET); // US (default)
_state = ParserState.Normal;
// parser.skipNextChar();
return true;
case C0.CAN:
_state = ParserState.Normal;
return true;
default:
return false;
}
}
private bool CsiStateHandler(char ch)
{
switch (ch)
{
case 'A':
Emit(new TerminalCode(TerminalCodeType.CursorUp, (int)_params[0], 0));
return true;
case 'G':
Emit(new TerminalCode(TerminalCodeType.CursorCharAbsolute, 0, (int)_params[0] - 1));
return true;
case 'H':
var line = _params.Count > 1 ? (int)_params[1] - 1 : 0; // make conpty happy
Emit(new TerminalCode(TerminalCodeType.CursorPosition, line, (int)_params[0] - 1));
return true;
case 'K':
Emit(TerminalCodeType.EraseInLine);
return true;
case 'J':
Emit(TerminalCodeType.EraseInDisplay);
return true;
case 'h':
Emit(TerminalCodeType.SetMode);
return true;
case 'l':
Emit(TerminalCodeType.ResetMode);
return true;
case 'n':
return true;
case 'm':
Emit(new TerminalCode(TerminalCodeType.CharAttributes, GetCharAttributes()));
return true;
default:
return false;
}
}
private bool CsiParamStateHandler(char ch)
{
switch (ch)
{
case '?':
case '>':
case '!':
case '$':
case '"':
case ' ':
case '\'':
_prefix = ch.ToString();
return true;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
_currentParam = (int)_currentParam * 10 + (ch - '0');
return true;
case ';':
FinaliseParam();
return true;
case C0.CAN:
_state = ParserState.Normal;
return true;
default:
return false;
}
}
private void FinaliseParam()
{
_params.Add(_currentParam);
_currentParam = 0;
}
private CharAttributes GetCharAttributes()
{
var attributes = new CharAttributes();
for (int i = 0; i < _params.Count; i++)
{
int p = (int)_params[i];
if (p >= 30 && p <= 37)
{
// fg color 8
attributes.ForegroundColor = p - 30;
}
else if (p >= 40 && p <= 47)
{
// bg color 8
attributes.BackgroundColor = p - 40;
}
else if (p >= 90 && p <= 97)
{
// fg color 16
p += 8;
attributes.ForegroundColor = p - 90;
}
else if (p == 0)
{
attributes.Flags = 0;
attributes.ForegroundColor = 0;
attributes.BackgroundColor = 0;
}
else if (p == 1)
{
attributes.Flags |= 1;
}
else
{
}
}
return attributes;
}
private void Emit(TerminalCodeType type)
{
Emit(new TerminalCode(type));
}
private void Emit(char c)
{
_currentTextEmit.Append(c);
}
private void Emit(TerminalCode code)
{
FinialiseEmit();
_terminalCodes.Add(code);
}
private void FinialiseEmit()
{
if (_currentTextEmit.Length != 0)
{
string text = _currentTextEmit.ToString();
_currentTextEmit.Clear();
_terminalCodes.Add(new TerminalCode(TerminalCodeType.Text, text));
}
}
private enum ParserState
{
Normal,
Escaped,
CsiParam,
Csi,
Osc,
Charset,
Dcs,
Ignore
}
}
}
@@ -0,0 +1,74 @@
namespace FluentTerminal.App.Views.NativeFrontend.Ansi
{
public class C0
{
/// <summary>Null (Caret = ^@, C = \0)</summary>
public const char NUL = (char)0x00;
/// <summary>Start of Heading (Caret = ^A)</summary>
public const char SOH = (char)0x01;
/// <summary>Start of Text (Caret = ^B)</summary>
public const char STX = (char)0x02;
/// <summary>End of Text (Caret = ^C)</summary>
public const char ETX = (char)0x03;
/// <summary>End of Transmission (Caret = ^D)</summary>
public const char EOT = (char)0x04;
/// <summary>Enquiry (Caret = ^E)</summary>
public const char ENQ = (char)0x05;
/// <summary>Acknowledge (Caret = ^F)</summary>
public const char ACK = (char)0x06;
/// <summary>Bell (Caret = ^G, C = \a)</summary>
public const char BEL = (char)0x07;
/// <summary>Backspace (Caret = ^H, C = \b)</summary>
public const char BS = (char)0x08;
/// <summary>Character Tabulation, Horizontal Tabulation (Caret = ^I, C = \t)</summary>
public const char HT = (char)0x09;
/// <summary>Line Feed (Caret = ^J, C = \n)</summary>
public const char LF = (char)0x0a;
/// <summary>Line Tabulation, Vertical Tabulation (Caret = ^K, C = \v)</summary>
public const char VT = (char)0x0b;
/// <summary>Form Feed (Caret = ^L, C = \f)</summary>
public const char FF = (char)0x0c;
/// <summary>Carriage Return (Caret = ^M, C = \r)</summary>
public const char CR = (char)0x0d;
/// <summary>Shift Out (Caret = ^N)</summary>
public const char SO = (char)0x0e;
/// <summary>Shift In (Caret = ^O)</summary>
public const char SI = (char)0x0f;
/// <summary>Data Link Escape (Caret = ^P)</summary>
public const char DLE = (char)0x10;
/// <summary>Device Control One (XON) (Caret = ^Q)</summary>
public const char DC1 = (char)0x11;
/// <summary>Device Control Two (Caret = ^R)</summary>
public const char DC2 = (char)0x12;
/// <summary>Device Control Three (XOFF) (Caret = ^S)</summary>
public const char DC3 = (char)0x13;
/// <summary>Device Control Four (Caret = ^T)</summary>
public const char DC4 = (char)0x14;
/// <summary>Negative Acknowledge (Caret = ^U)</summary>
public const char NAK = (char)0x15;
/// <summary>Synchronous Idle (Caret = ^V)</summary>
public const char SYN = (char)0x16;
/// <summary>End of Transmission Block (Caret = ^W)</summary>
public const char ETB = (char)0x17;
/// <summary>Cancel (Caret = ^X)</summary>
public const char CAN = (char)0x18;
/// <summary>End of Medium (Caret = ^Y)</summary>
public const char EM = (char)0x19;
/// <summary>Substitute (Caret = ^Z)</summary>
public const char SUB = (char)0x1a;
/// <summary>Escape (Caret = ^[, C = \e)</summary>
public const char ESC = (char)0x1b;
/// <summary>File Separator (Caret = ^\)</summary>
public const char FS = (char)0x1c;
/// <summary>Group Separator (Caret = ^])</summary>
public const char GS = (char)0x1d;
/// <summary>Record Separator (Caret = ^^)</summary>
public const char RS = (char)0x1e;
/// <summary>Unit Separator (Caret = ^_)</summary>
public const char US = (char)0x1f;
/// <summary>Space</summary>
public const char SP = (char)0x20;
/// <summary>Delete (Caret = ^?)</summary>
public const char DEL = (char)0x7f;
}
}
@@ -0,0 +1,36 @@
using System;
namespace FluentTerminal.App.Views.NativeFrontend.Ansi
{
public struct CharAttributes : IEquatable<CharAttributes>
{
public int Flags { get; set; }
public int BackgroundColor { get; set; }
public int ForegroundColor { get; set; }
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public bool Equals(CharAttributes other)
{
return base.Equals(other);
}
public static bool operator ==(CharAttributes a, CharAttributes b)
{
return a.Equals(b);
}
public static bool operator !=(CharAttributes a, CharAttributes b)
{
return !a.Equals(b);
}
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Ansi
{
internal struct TerminalCode
{
public TerminalCodeType Type { get; }
public int Line { get; }
public int Column { get; }
public string Text { get; }
public CharAttributes CharAttributes { get; }
public TerminalCode(TerminalCodeType type) : this()
{
Type = type;
}
public TerminalCode(TerminalCodeType type, string text) : this(type)
{
Text = text;
}
public TerminalCode(TerminalCodeType type, int line, int column) : this(type)
{
Line = line;
Column = column;
}
public TerminalCode(TerminalCodeType type, CharAttributes charAttributes) : this(type)
{
CharAttributes = charAttributes;
}
public override string ToString()
{
if (Type == TerminalCodeType.Text)
{
return Text;
}
else
{
return Type.ToString();
}
}
}
}
@@ -0,0 +1,33 @@
namespace FluentTerminal.App.Views.NativeFrontend.Ansi
{
public enum TerminalCodeType
{
Text,
Bell,
LineFeed,
CarriageReturn,
Backspace,
Tab,
ShiftOut,
ShiftIn,
SaveCursor,
Reset,
SetTitle,
RestoreCursor,
TabSet,
CursorPosition,
CursorCharAbsolute,
CursorUp,
CursorDown,
CursorForward,
CursorBackward,
RestoreCursorPosition,
EraseInDisplay,
EraseInLine,
SetGraphicsMode,
SetMode,
CharAttributes,
ResetMode,
}
}
@@ -0,0 +1,8 @@
namespace FluentTerminal.App.Views.NativeFrontend.Terminal
{
public enum SelectionMode
{
Stream,
Block
}
}
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Terminal
{
internal static class SpecialColorIds
{
public const int Cursor = -1;
public const int Selection = -2;
public const int Historic = -3;
public const int Futuristic = -4;
}
}
@@ -0,0 +1,477 @@
using FluentTerminal.App.Views.NativeFrontend.Ansi;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Terminal
{
internal class TerminalBuffer
{
private const int MaxHistorySize = 1024;
private TerminalBufferChar[] _buffer;
private TerminalSize _size;
private readonly List<TerminalBufferLine> _history = new List<TerminalBufferLine>();
public bool ShowCursor { get; set; }
public int CursorX { get; set; }
public int CursorY { get; set; }
public CharAttributes CurrentCharAttributes { get; set; }
public TerminalSelection Selection { get; set; }
public int WindowTop { get; set; }
public int WindowBottom
{
get => WindowTop + _size.Rows - 1;
set
{
WindowTop = value - _size.Rows + 1;
}
}
public TerminalBuffer(TerminalSize size)
{
Initialise(size);
}
private void Initialise(TerminalSize size)
{
_buffer = new TerminalBufferChar[size.Rows * size.Columns];
_size = size;
CursorX = 0;
CursorY = 0;
Clear();
}
public TerminalSize Size
{
get => _size;
set
{
if (value != _size)
{
var srcSize = _size;
var dstSize = value;
var srcBuffer = _buffer;
var dstBuffer = new TerminalBufferChar[dstSize.Rows * dstSize.Columns];
int srcLeft = 0;
int srcRight = Math.Min(srcSize.Columns, dstSize.Columns) - 1;
int srcTop = Math.Max(0, CursorY - dstSize.Rows + 1);
int srcBottom = srcTop + Math.Min(srcSize.Rows, dstSize.Rows) - 1;
int dstLeft = 0;
int dstTop = 0;
CopyBufferToBuffer(srcBuffer, srcSize, srcLeft, srcTop, srcRight, srcBottom,
dstBuffer, dstSize, dstLeft, dstTop);
_buffer = dstBuffer;
_size = dstSize;
CursorY = Math.Min(CursorY, _size.Rows - 1);
}
}
}
public void Clear()
{
ClearBlock(0, 0, _size.Columns - 1, _size.Rows - 1);
}
public void ClearBlock(int left, int top, int right, int bottom)
{
left = Math.Max(0, left);
top = Math.Max(0, top);
right = Math.Min(right, _size.Columns - 1);
bottom = Math.Min(bottom, _size.Rows - 1);
for (int y = top; y <= bottom; y++)
{
for (int x = left; x <= right; x++)
{
int index = GetBufferIndex(x, y);
_buffer[index] = new TerminalBufferChar(' ', default(CharAttributes));
}
}
ScrollToCursor();
}
public void Type(char c)
{
if (IsInBuffer(CursorX, CursorY))
{
int index = GetBufferIndex(CursorX, CursorY);
_buffer[index] = new TerminalBufferChar(c, CurrentCharAttributes);
CursorX++;
}
ScrollToCursor();
}
internal void Type(string text)
{
foreach (char c in text)
{
if (IsInBuffer(CursorX, CursorY))
{
int index = GetBufferIndex(CursorX, CursorY);
_buffer[index] = new TerminalBufferChar(c, CurrentCharAttributes);
CursorX++;
}
}
ScrollToCursor();
}
public void ShiftUp()
{
var topLine = GetBufferLine(0);
AddHistory(topLine);
for (int y = 0; y < _size.Rows - 1; y++)
{
Array.Copy(_buffer, (y + 1) * _size.Columns, _buffer, y * _size.Columns, _size.Columns);
}
}
public string GetText(int y)
{
return GetText(0, y, _size.Columns);
}
public string[] GetText(int left, int top, int right, int bottom)
{
int width = right - left + 1;
int height = bottom - top + 1;
string[] result = new string[height];
for (int i = 0; i < height; i++)
{
result[i] = GetText(left, top + i, width);
}
return result;
}
public string GetText(int x, int y, int length)
{
if (x + length > _size.Columns)
{
throw new ArgumentException("Range overflows line length.", nameof(length));
}
(var buffer, int startIndex, int endIndex) = GetLineBufferRange(y);
if (buffer == null)
{
return string.Empty;
}
int maxLength = endIndex - startIndex;
string line = GetTextAtIndex(buffer, startIndex + x, Math.Min(length, maxLength));
return line;
}
private static string GetTextAtIndex(IList<TerminalBufferChar> buffer, int index, int length)
{
var chars = new char[length];
for (int i = 0; i < length; i++)
{
chars[i] = buffer[index + i].Char;
}
string line = new string(chars);
return line;
}
public string[] GetSelectionText()
{
var selection = Selection;
if (selection.Mode == SelectionMode.Stream)
{
(var start, var end) = selection.GetMinMax();
var result = new List<string>();
for (int y = start.Row; y <= end.Row; y++)
{
int x0 = 0;
int x1 = _size.Columns - 1;
if (y == start.Row)
{
x0 = start.Column;
}
if (y == end.Row)
{
x1 = end.Column;
}
result.Add(GetText(x0, y, x1 - x0 + 1));
}
return result.ToArray();
}
else if (selection.Mode == SelectionMode.Block)
{
int left = Math.Min(selection.Start.Column, selection.End.Column);
int right = Math.Max(selection.Start.Column, selection.End.Column);
int top = Math.Min(selection.Start.Row, selection.End.Row);
int bottom = Math.Max(selection.Start.Row, selection.End.Row);
return GetText(left, top, right, bottom);
}
else
{
throw new InvalidOperationException("Unknown selection mode.");
}
}
public void CopySelection()
{
//string[] selectionText = GetSelectionText()
// .Select(x => x.TrimEnd())
// .ToArray();
//string text = String.Join(Environment.NewLine, selectionText);
//var dataObject = new DataObject();
//dataObject.SetText(text);
//dataObject.SetData("MSDEVColumnSelect", true);
//Clipboard.SetDataObject(dataObject, copy: true);
}
private TerminalBufferLine GetBufferLine(int y)
{
int startIndex = GetBufferIndex(0, y);
var bufferLine = new TerminalBufferLine(_buffer, startIndex, _size.Columns);
return bufferLine;
}
public TerminalTagArray GetFormattedLine(int y)
{
var tags = ImmutableArray.CreateBuilder<TerminalTag>(initialCapacity: _size.Columns);
(var buffer, int startIndex, int endIndex) = GetLineBufferRange(y);
if (buffer == null)
{
AddFillerTags(tags, 0, y, _size.Columns);
return new TerminalTagArray(tags.ToImmutable());
}
// Group sequentially by attribute
int lineLength = endIndex - startIndex;
var currentTagStartIndex = startIndex;
var currentTagAttribute = GetAttributesAt(buffer[startIndex], 0, y);
for (int i = startIndex + 1; i < endIndex; i++)
{
int x = i - startIndex;
var c = buffer[i];
var attr = GetAttributesAt(c, x, y);
if (!CanContinueTag(currentTagAttribute, attr, c.Char))
{
string tagText = GetTextAtIndex(buffer, currentTagStartIndex, i - currentTagStartIndex);
tags.Add(new TerminalTag(tagText, currentTagAttribute));
currentTagStartIndex = i;
currentTagAttribute = attr;
}
}
// Last tag
{
string tagText = GetTextAtIndex(buffer, currentTagStartIndex, endIndex - currentTagStartIndex);
tags.Add(new TerminalTag(tagText, currentTagAttribute));
}
// Filler tags
if (lineLength < _size.Columns)
{
AddFillerTags(tags, lineLength, y, _size.Columns - lineLength);
}
return new TerminalTagArray(tags.ToImmutable());
}
private void AddFillerTags(ImmutableArray<TerminalTag>.Builder builder, int x, int y, int length)
{
int tagLength = 0;
var lastAttr = GetAttributesAt(default(TerminalBufferChar), x, y);
for (int i = 0; i < length; i++)
{
tagLength++;
var attr = GetAttributesAt(default(TerminalBufferChar), x + i, y);
if (attr != lastAttr)
{
string text = new string(' ', tagLength);
builder.Add(new TerminalTag(text, lastAttr));
lastAttr = attr;
tagLength = 0;
}
}
// Last tag
{
string text = new string(' ', tagLength);
builder.Add(new TerminalTag(text, lastAttr));
}
}
private CharAttributes GetAttributesAt(TerminalBufferChar bufferChar, int x, int y)
{
CharAttributes attr = bufferChar.Attributes;
if (ShowCursor && x == CursorX && y == CursorY)
{
attr.BackgroundColor = SpecialColorIds.Cursor;
}
else if (IsPointInSelection(x, y))
{
attr.BackgroundColor = SpecialColorIds.Selection;
}
else if (y < 0)
{
attr.BackgroundColor = SpecialColorIds.Historic;
}
else if (y >= _size.Rows)
{
attr.BackgroundColor = SpecialColorIds.Futuristic;
}
return attr;
}
private (IList<TerminalBufferChar> buffer, int startIndex, int endIndex) GetLineBufferRange(int y)
{
if (y < 0)
{
int historyIndex = _history.Count + y;
if (historyIndex < 0)
{
return (null, 0, 0);
}
var historyLine = _history[historyIndex];
var buffer = historyLine.Buffer;
return (buffer, 0, Math.Min(buffer.Length, _size.Columns));
}
else
{
if (y >= _size.Rows)
{
return (null, 0, 0);
}
int startIndex = GetBufferIndex(0, y);
return (_buffer, startIndex, startIndex + _size.Columns);
}
}
private bool IsPointInSelection(int x, int y)
{
var selection = Selection;
if (selection == null)
{
return false;
}
else if (selection.Mode == SelectionMode.Stream)
{
(var start, var end) = selection.GetMinMax();
if (y == start.Row)
{
if (x < start.Column)
{
return false;
}
}
if (y == end.Row)
{
if (x > end.Column)
{
return false;
}
}
if (y < start.Row || y > end.Row)
{
return false;
}
return true;
}
else if (selection.Mode == SelectionMode.Block)
{
int left = Math.Min(selection.Start.Column, selection.End.Column);
int right = Math.Max(selection.Start.Column, selection.End.Column);
int top = Math.Min(selection.Start.Row, selection.End.Row);
int bottom = Math.Max(selection.Start.Row, selection.End.Row);
return (x >= left && x <= right &&
y >= top && y <= bottom);
}
else
{
throw new InvalidOperationException("Unknown selection mode.");
}
}
private static bool CanContinueTag(CharAttributes previous, CharAttributes next, char nextC)
{
if (nextC == ' ')
{
return previous.BackgroundColor == next.BackgroundColor;
}
else
{
return previous == next;
}
}
public bool IsInBuffer(int x, int y)
{
return (x >= 0 && x < _size.Columns && y >= 0 && y < _size.Rows);
}
private int GetBufferIndex(int x, int y)
{
return x + (y * _size.Columns);
}
private TerminalPoint GetBufferPoint(int index)
{
return new TerminalPoint(index % _size.Columns, index % _size.Columns);
}
private void AddHistory(TerminalBufferLine line)
{
if (_history.Count >= MaxHistorySize)
{
_history.RemoveAt(0);
}
_history.Add(line);
}
public int CurrentHistoryLength => _history.Count;
public void Scroll(int scroll)
{
int top = WindowTop + scroll;
top = Math.Max(top, -_history.Count);
// top = Math.Min(top, _size.Rows - 1);
top = Math.Min(top, CursorY);
WindowTop = top;
}
public void ScrollToCursor()
{
int windowTop = WindowTop;
int windowBottom = WindowBottom;
if (CursorY < windowTop)
{
WindowTop = CursorY;
}
else if (CursorY > windowBottom)
{
WindowBottom = CursorY;
}
}
private static void CopyBufferToBuffer(TerminalBufferChar[] srcBuffer, TerminalSize srcSize, int srcLeft, int srcTop, int srcRight, int srcBottom,
TerminalBufferChar[] dstBuffer, TerminalSize dstSize, int dstLeft, int dstTop)
{
int cols = srcRight - srcLeft + 1;
int rows = srcBottom - srcTop + 1;
for (int y = 0; y < rows; y++)
{
int srcY = srcTop + y;
int dstY = dstTop + y;
int srcIndex = srcLeft + (srcY * srcSize.Columns);
int dstIndex = dstLeft + (dstY * dstSize.Columns);
Array.Copy(srcBuffer, srcIndex, dstBuffer, dstIndex, cols);
}
}
}
}
@@ -0,0 +1,26 @@
using FluentTerminal.App.Views.NativeFrontend.Ansi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Terminal
{
public struct TerminalBufferChar
{
public char Char { get; }
public CharAttributes Attributes { get; }
public TerminalBufferChar(char c, CharAttributes attr)
{
Char = c;
Attributes = attr;
}
public override string ToString()
{
return Char.ToString();
}
}
}
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Terminal
{
/// <summary>
/// Represents a single immutable line from a terminal buffer.
/// </summary>
internal class TerminalBufferLine
{
public int Columns { get; }
public ImmutableArray<TerminalBufferChar> Buffer { get; }
public TerminalBufferLine(TerminalBufferChar[] buffer, int index, int length)
{
Buffer = buffer.Skip(index).Take(length).ToImmutableArray();
Columns = length;
}
public override string ToString()
{
return new string(Buffer.Select(x => x.Char).ToArray());
}
}
}
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Terminal
{
[DebuggerDisplay("{Column}, {Row}")]
public struct TerminalPoint : IEquatable<TerminalPoint>, IComparable<TerminalPoint>
{
public int Column { get; set; }
public int Row { get; set; }
public TerminalPoint(int col, int row)
{
Column = col;
Row = row;
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public bool Equals(TerminalPoint other)
{
return Column == other.Column &&
Row == other.Row;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public int CompareTo(TerminalPoint other)
{
if (Row < other.Row) return -1;
if (Row > other.Row) return 1;
if (Column < other.Column) return -1;
if (Column > other.Column) return 1;
return 0;
}
public static bool operator ==(TerminalPoint a, TerminalPoint b)
{
return a.Equals(b);
}
public static bool operator !=(TerminalPoint a, TerminalPoint b)
{
return !a.Equals(b);
}
public static bool operator >(TerminalPoint a, TerminalPoint b)
{
return a.CompareTo(b) == 1;
}
public static bool operator <(TerminalPoint a, TerminalPoint b)
{
return a.CompareTo(b) == -1;
}
public static bool operator >=(TerminalPoint a, TerminalPoint b)
{
return a.CompareTo(b) >= 0;
}
public static bool operator <=(TerminalPoint a, TerminalPoint b)
{
return a.CompareTo(b) <= 0;
}
}
}
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Terminal
{
internal class TerminalSelection
{
public SelectionMode Mode { get; }
public TerminalPoint Start { get; }
public TerminalPoint End { get; }
public bool IsReversed { get; }
public TerminalSelection(SelectionMode mode, TerminalPoint start, TerminalPoint end)
{
Mode = mode;
Start = start;
End = end;
IsReversed = start > end;
}
public (TerminalPoint, TerminalPoint) GetMinMax()
{
return IsReversed ? (End, Start) : (Start, End);
}
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Terminal
{
public struct TerminalSize : IEquatable<TerminalSize>
{
public int Columns { get; }
public int Rows { get; }
public TerminalSize(int columns, int rows)
{
Columns = columns;
Rows = rows;
}
public bool Equals(TerminalSize other)
{
return base.Equals(other);
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override string ToString()
{
return $"{Columns} x {Rows}";
}
public static bool operator ==(TerminalSize a, TerminalSize b)
{
return a.Equals(b);
}
public static bool operator !=(TerminalSize a, TerminalSize b)
{
return !a.Equals(b);
}
}
}
@@ -0,0 +1,62 @@
using FluentTerminal.App.Views.NativeFrontend.Ansi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Terminal
{
public struct TerminalTag : IEquatable<TerminalTag>
{
public string Text { get; }
public CharAttributes Attributes { get; }
public TerminalTag(string text, CharAttributes attributes)
{
Text = text;
Attributes = attributes;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object obj)
{
return Equals((TerminalTag)obj);
}
public bool Equals(TerminalTag other)
{
return Text == other.Text &&
Attributes == other.Attributes;
}
public TerminalTag Substring(int index)
{
return new TerminalTag(Text.Substring(index), Attributes);
}
public TerminalTag Substring(int index, int length)
{
return new TerminalTag(Text.Substring(index, length), Attributes);
}
public override string ToString()
{
return Text;
}
public static bool operator ==(TerminalTag a, TerminalTag b)
{
return a.Equals(b);
}
public static bool operator !=(TerminalTag a, TerminalTag b)
{
return !a.Equals(b);
}
}
}
@@ -0,0 +1,106 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Terminal
{
public struct TerminalTagArray : IEquatable<TerminalTagArray>, IEnumerable<TerminalTag>
{
private readonly ImmutableArray<TerminalTag> _tags;
private readonly int _hash;
public int Length => _tags.IsDefaultOrEmpty ? 0 : _tags.Length;
public TerminalTagArray(ImmutableArray<TerminalTag> tags)
{
_tags = tags;
_hash = GetHashCode(tags);
}
private static int GetHashCode(ImmutableArray<TerminalTag> tags)
{
unchecked
{
int hash = 17;
for (int i = 0; i < tags.Length; i++)
{
hash = hash * 23 + tags[i].GetHashCode();
}
return hash;
}
}
public override int GetHashCode()
{
return _hash;
}
public override bool Equals(object obj)
{
return Equals((ImmutableArray<TerminalTag>)obj);
}
public bool Equals(TerminalTagArray other)
{
if (_hash != other._hash)
{
return false;
}
var tagsA = _tags;
var tagsB = other._tags;
if (tagsA != tagsB)
{
if (tagsA.IsDefaultOrEmpty || tagsB.IsDefaultOrEmpty)
{
return false;
}
if (tagsA.Length != tagsB.Length)
{
return false;
}
for (int i = 0; i < tagsA.Length; i++)
{
if (tagsA[i] != tagsB[i])
{
return false;
}
}
}
return true;
}
public override string ToString()
{
return base.ToString();
}
public IEnumerator<TerminalTag> GetEnumerator()
{
if (_tags.IsDefaultOrEmpty)
{
return Enumerable.Empty<TerminalTag>().GetEnumerator();
}
return ((IEnumerable<TerminalTag>)_tags).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public static bool operator ==(TerminalTagArray a, TerminalTagArray b)
{
return a.Equals(b);
}
public static bool operator !=(TerminalTagArray a, TerminalTagArray b)
{
return !a.Equals(b);
}
}
}
@@ -0,0 +1,87 @@
using FluentTerminal.App.Utilities;
using FluentTerminal.App.Views.NativeFrontend.Terminal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI;
using Windows.UI.Xaml.Media;
namespace FluentTerminal.App.Views.NativeFrontend
{
internal class TerminalColorHelper
{
private readonly Dictionary<int, Brush> _brushDictionary = new Dictionary<int, Brush>();
private readonly Brush _defaultForegroundBrush = new SolidColorBrush(Color.FromArgb(255, 204, 204, 204));
public Brush GetForegroundBrush(int id)
{
Brush brush = GetBrush(id);
if (brush == null)
{
brush = _defaultForegroundBrush;
}
return brush;
}
public Brush GetBackgroundBrush(int id)
{
return GetBrush(id);
}
public Brush GetBrush(int id)
{
Brush result = null;
if (id != 0)
{
if (!_brushDictionary.TryGetValue(id, out result))
{
result = new SolidColorBrush(GetColour(id));
_brushDictionary.Add(id, result);
}
}
return result;
}
public Color GetColour(int id)
{
switch (id)
{
case SpecialColorIds.Cursor:
return Color.FromArgb(255, 204, 204, 204);
case SpecialColorIds.Selection:
return Color.FromArgb(255, 203, 203, 203);
case SpecialColorIds.Historic:
case SpecialColorIds.Futuristic:
return Color.FromArgb(255, 24, 24, 24);
default:
return TangoColours[id % 16].FromString();
}
}
// Colors 0-15
private readonly static string[] TangoColours =
{
// dark:
"#2e3436",
"#cc0000",
"#0dbc79",
"#c4a000",
"#3465a4",
"#75507b",
"#06989a",
"#d3d7cf",
// bright:
"#555753",
"#ef2929",
"#23D18B",
"#fce94f",
"#729fcf",
"#ad7fa8",
"#34e2e2",
"#eeeeec"
};
}
}
@@ -0,0 +1,16 @@
<UserControl
x:Class="FluentTerminal.App.Views.NativeFrontend.TerminalControl"
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:FluentTerminal.App.Views.NativeFrontend"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xaml="using:Microsoft.Graphics.Canvas.UI.Xaml"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<ScrollViewer x:Name="scroll" VerticalScrollBarVisibility="Auto">
<xaml:CanvasVirtualControl x:Name="canvas" IsTabStop="True" RegionsInvalidated="OnRegionsInvalidated"/>
</ScrollViewer>
</UserControl>
@@ -0,0 +1,476 @@
using FluentTerminal.App.Services;
using FluentTerminal.App.ViewModels;
using FluentTerminal.App.Views.NativeFrontend.Ansi;
using FluentTerminal.App.Views.NativeFrontend.Terminal;
using FluentTerminal.App.Views.NativeFrontend.Utility;
using FluentTerminal.Models;
using FluentTerminal.Models.Enums;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.System;
using Windows.UI;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
namespace FluentTerminal.App.Views.NativeFrontend
{
public sealed partial class TerminalControl : UserControl, ITerminalView
{
private TerminalBuffer _buffer;
private double _characterHeight;
private double _characterWidth;
private TerminalColorHelper _colorHelper = new TerminalColorHelper();
private readonly TerminalOptions _terminalOptions;
private int _cols;
private CanvasTextFormat _format;
private Ansi.AnsiParser _parser;
private int _rows;
private int _gridSize = 150;
private CoreDispatcher _dispatcher;
public TerminalControl(ISettingsService settingsService)
{
InitializeComponent();
canvas.KeyUp += _canvas_KeyUp;
canvas.GotFocus += _canvas_GotFocus;
canvas.CharacterReceived += Canvas_CharacterReceived;
_terminalOptions = settingsService.GetTerminalOptions();
_dispatcher = Window.Current.CoreWindow.Dispatcher;
}
int regionsInvalidatedEventCount = 0;
int regionsInvalidatedCount = 0;
private void OnRegionsInvalidated(CanvasVirtualControl sender, CanvasRegionsInvalidatedEventArgs args)
{
++regionsInvalidatedEventCount;
var invalidatedRegions = args.InvalidatedRegions;
regionsInvalidatedCount += invalidatedRegions.Count();
foreach (var region in invalidatedRegions)
{
DrawRegion(sender, region);
}
}
private void DrawRegion(CanvasVirtualControl sender, Rect region)
{
var top = (int)(region.Top / _characterHeight);
var bottom = top + (int)(region.Height / _characterHeight);
using (var ds = sender.CreateDrawingSession(region))
{
var y = 0.0;
for (int i = top; i < bottom; i++)
{
var x = 0.0;
var line = _buffer.GetFormattedLine(i);
foreach (var item in line)
{
if (item.Attributes.BackgroundColor != 0)
{
ds.FillRectangle(new Windows.Foundation.Rect { Height = _characterHeight, Width = _characterWidth * item.Text.Length, X = x, Y = y }, _colorHelper.GetColour(item.Attributes.BackgroundColor));
}
var foreground = Colors.White;
if (item.Attributes.ForegroundColor != 0)
{
foreground = _colorHelper.GetColour(item.Attributes.ForegroundColor);
}
var pos = new System.Numerics.Vector2 { X = (float)x, Y = (float)y };
ds.DrawText(item.Text, pos, foreground, _format);
x += item.Text.Length * _characterWidth;
}
y += _characterHeight;
}
}
}
public void Measure()
{
var device = CanvasDevice.GetSharedDevice();
using (CanvasRenderTarget offscreen = new CanvasRenderTarget(device, (float)256, (float)256, canvas.Dpi))
{
using (CanvasDrawingSession ds = offscreen.CreateDrawingSession())
{
_format = new CanvasTextFormat
{
FontSize = _terminalOptions.FontSize,
FontFamily = _terminalOptions.FontFamily,
FontWeight = _terminalOptions.FontWeight
};
var textLayout = new CanvasTextLayout(ds, "\u2560", _format, 0.0f, 0.0f);
_characterWidth = textLayout.DrawBounds.Right;
_characterHeight = textLayout.DrawBounds.Bottom;
_cols = (int)Math.Floor(Window.Current.CoreWindow.Bounds.Width / _characterWidth);
_rows = (int)Math.Floor((Window.Current.CoreWindow.Bounds.Height - 32) / _characterHeight);
}
}
}
private void UserControl_Unloaded(object sender, RoutedEventArgs args)
{
// Explicitly remove references to allow the Win2D controls to get garbage collected
canvas.RemoveFromVisualTree();
canvas = null;
}
public TerminalViewModel ViewModel { get; private set; }
public Task ChangeKeyBindings()
{
//throw new NotImplementedException();
return Task.CompletedTask;
}
public Task ChangeOptions(TerminalOptions options)
{
//throw new NotImplementedException();
return Task.CompletedTask;
}
public Task ChangeTheme(TerminalTheme theme)
{
//throw new NotImplementedException();
return Task.CompletedTask;
}
public Task FindNext(string searchText)
{
throw new NotImplementedException();
}
public Task FindPrevious(string searchText)
{
throw new NotImplementedException();
}
public Task FocusTerminal()
{
canvas.Focus(FocusState.Programmatic);
return Task.CompletedTask;
}
public async Task Initialize(TerminalViewModel viewModel)
{
Measure();
ViewModel = viewModel;
ViewModel.Terminal.OutputReceived += Terminal_OutputReceived;
//ViewModel.Terminal.RegisterSelectedTextCallback(() => ExecuteScriptAsync("term.getSelection()"));
//ViewModel.Terminal.Closed += Terminal_Closed;
var options = ViewModel.SettingsService.GetTerminalOptions();
var keyBindings = ViewModel.SettingsService.GetCommandKeyBindings();
var profiles = ViewModel.SettingsService.GetShellProfiles();
var settings = ViewModel.SettingsService.GetApplicationSettings();
var theme = ViewModel.TerminalTheme;
var sessionType = SessionType.Unknown;
if (settings.AlwaysUseWinPty || !ViewModel.ApplicationView.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 7))
{
sessionType = SessionType.WinPty;
}
else
{
sessionType = SessionType.ConPty;
}
var size = new Models.TerminalSize { Rows = _rows, Columns = _cols };
_buffer = new TerminalBuffer(new Terminal.TerminalSize(size.Columns, size.Rows));
_parser = new Ansi.AnsiParser();
var response = await ViewModel.Terminal.StartShellProcess(ViewModel.ShellProfile, size, sessionType).ConfigureAwait(true);
if (!response.Success)
{
await ViewModel.DialogService.ShowMessageDialogAsnyc("Error", response.Error, DialogButton.OK).ConfigureAwait(true);
ViewModel.Terminal.ReportLauchFailed();
return;
}
canvas.Focus(FocusState.Keyboard);
}
private void _canvas_GotFocus(object sender, RoutedEventArgs e)
{
Debug.WriteLine("focus");
}
private void _canvas_KeyUp(object sender, KeyRoutedEventArgs e)
{
var controlPressed = (Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down));
var shiftPressed = (Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down));
var windowsPressed = (Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.LeftWindows).HasFlag(CoreVirtualKeyStates.Down));
var altPressed = (Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Menu).HasFlag(CoreVirtualKeyStates.Down));
int modCode = 0;
if (shiftPressed) modCode |= 1;
if (altPressed) modCode |= 2;
if (controlPressed) modCode |= 4;
if (windowsPressed) modCode |= 8;
//if (IsSelecting && !modifiers.HasFlag(ModifierKeys.Alt))
//{
// ClearSelection();
// if (e.Key == Key.Escape)
// {
// return;
// }
//}
string text = string.Empty;
switch (e.Key)
{
case VirtualKey.Escape:
text = $"{C0.ESC}{C0.ESC}{C0.ESC}";
break;
case VirtualKey.Back:
text = shiftPressed ?
C0.BS.ToString() :
C0.DEL.ToString();
break;
case VirtualKey.Delete:
text = (modCode == 0) ?
$"{C0.ESC}[3~" :
$"{C0.ESC}[3;{modCode + 1}~";
break;
case VirtualKey.Tab:
text = shiftPressed ?
$"{C0.ESC}[Z" :
C0.HT.ToString();
break;
case VirtualKey.Up:
text = Construct(1, 'A');
break;
case VirtualKey.Down:
text = Construct(1, 'B');
break;
case VirtualKey.Right:
text = Construct(1, 'C');
break;
case VirtualKey.Left:
text = Construct(1, 'D');
break;
case VirtualKey.Home:
text = Construct(1, 'H');
break;
case VirtualKey.End:
text = Construct(1, 'F');
break;
case VirtualKey.PageUp:
text = $"{C0.ESC}[5~";
break;
case VirtualKey.PageDown:
text = $"{C0.ESC}[6~";
break;
case VirtualKey.Enter:
text = C0.CR.ToString();
break;
case VirtualKey.Space:
text = " ";
break;
case VirtualKey.F1:
text = Construct(1, 'P');
break;
case VirtualKey.F2:
text = Construct(1, 'Q');
break;
case VirtualKey.F3:
text = Construct(1, 'R');
break;
case VirtualKey.F4:
text = Construct(1, 'S');
break;
case VirtualKey.F5:
text = (modCode == 0) ?
$"{C0.ESC}[15~" :
$"{C0.ESC}[15;{modCode + 1}~";
break;
case VirtualKey.F6:
text = (modCode == 0) ?
$"{C0.ESC}[17~" :
$"{C0.ESC}[17;{modCode + 1}~";
break;
case VirtualKey.F7:
text = (modCode == 0) ?
$"{C0.ESC}[18~" :
$"{C0.ESC}[18;{modCode + 1}~";
break;
case VirtualKey.F8:
text = (modCode == 0) ?
$"{C0.ESC}[19~" :
$"{C0.ESC}[19;{modCode + 1}~";
break;
case VirtualKey.F9:
text = (modCode == 0) ?
$"{C0.ESC}[20~" :
$"{C0.ESC}[20;{modCode + 1}~";
break;
case VirtualKey.F10:
text = (modCode == 0) ?
$"{C0.ESC}[21~" :
$"{C0.ESC}[21;{modCode + 1}~";
break;
case VirtualKey.F11:
text = (modCode == 0) ?
$"{C0.ESC}[23~" :
$"{C0.ESC}[23;{modCode + 1}~";
break;
case VirtualKey.F12:
text = (modCode == 0) ?
$"{C0.ESC}[24~" :
$"{C0.ESC}[24;{modCode + 1}~";
break;
}
if (text != string.Empty)
{
ViewModel.Terminal.Write(Encoding.UTF8.GetBytes(text));
e.Handled = true;
}
string Construct(int a, char c)
{
return (modCode == 0) ?
$"{C0.ESC}O{c}" :
$"{C0.ESC}[{a};{modCode + 1}{c}";
}
}
private void Canvas_CharacterReceived(UIElement sender, CharacterReceivedRoutedEventArgs args)
{
var text = Encoding.UTF8.GetBytes(new[] { args.Character });
ViewModel.Terminal.Write(text);
}
private void ProcessTerminalCode(TerminalCode code)
{
switch (code.Type)
{
case TerminalCodeType.ResetMode:
_buffer.ShowCursor = false;
break;
case TerminalCodeType.SetMode:
_buffer.ShowCursor = true;
// HACK We want clear to reset the window position but not general typing.
// We therefore reset the window only if the cursor is moved to the top.
if (_buffer.CursorY == 0)
{
_buffer.WindowTop = 0;
}
break;
case TerminalCodeType.Text:
_buffer.Type(code.Text);
break;
case TerminalCodeType.LineFeed:
if (_buffer.CursorY == _buffer.Size.Rows - 1)
{
_buffer.ShiftUp();
}
else
{
_buffer.CursorY++;
}
break;
case TerminalCodeType.CarriageReturn:
_buffer.CursorX = 0;
break;
case TerminalCodeType.CharAttributes:
_buffer.CurrentCharAttributes = code.CharAttributes;
break;
case TerminalCodeType.CursorPosition:
_buffer.CursorX = code.Column;
_buffer.CursorY = code.Line;
break;
case TerminalCodeType.CursorUp:
_buffer.CursorY -= code.Line;
break;
case TerminalCodeType.CursorCharAbsolute:
_buffer.CursorX = code.Column;
break;
case TerminalCodeType.EraseInLine:
if (code.Line == 0)
{
_buffer.ClearBlock(_buffer.CursorX, _buffer.CursorY, _buffer.Size.Columns - 1, _buffer.CursorY);
}
break;
case TerminalCodeType.EraseInDisplay:
_buffer.Clear();
_buffer.CursorX = 0;
_buffer.CursorY = 0;
break;
case TerminalCodeType.SetTitle:
//ViewModel.Terminal.SetTitle(code.Text);
break;
}
}
private void Terminal_OutputReceived(object sender, byte[] e)
{
var text = Encoding.UTF8.GetString(e, 0, e.Length);
var reader = new ArrayReader<char>(text.ToCharArray());
var codes = _parser.Parse(reader);
foreach (var code in codes)
{
ProcessTerminalCode(code);
}
_dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
canvas.Height = Math.Max(_buffer.CurrentHistoryLength * _characterHeight, _buffer.Size.Rows * _characterHeight);
canvas.Invalidate();
});
}
}
}
@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.Views.NativeFrontend.Utility
{
internal class ArrayReader<T>
{
private readonly T[] _array;
public int Offset { get; private set; }
public int RemainingLength { get; private set; }
public ArrayReader(T[] array)
{
_array = array;
Offset = 0;
RemainingLength = array.Length;
}
public ArrayReader(T[] array, int offset, int count)
{
_array = array;
Offset = offset;
RemainingLength = count;
}
public ArrayReader(ArraySegment<T> segment)
{
_array = segment.Array;
Offset = segment.Offset;
RemainingLength = segment.Count;
}
public bool TryRead(out T element)
{
if (RemainingLength > 0)
{
element = _array[Offset];
Offset++;
RemainingLength--;
return true;
}
else
{
element = default(T);
return false;
}
}
public bool TryPeek(out T element)
{
if (RemainingLength > 0)
{
element = _array[Offset];
return true;
}
else
{
element = default(T);
return false;
}
}
public T Read()
{
T element;
if (!TryRead(out element))
{
throw new IndexOutOfRangeException();
}
return element;
}
public T Peek()
{
T element;
if (!TryPeek(out element))
{
throw new IndexOutOfRangeException();
}
return element;
}
}
}
@@ -21,7 +21,9 @@ namespace FluentTerminal.App.Views
ViewModel.FindNextRequested += OnFindNextRequested;
ViewModel.FindPreviousRequested += OnFindPreviousRequested;
InitializeComponent();
_terminalView = new XtermTerminalView();
_terminalView = new NativeFrontend.TerminalControl(ViewModel.SettingsService);
//_terminalView = new VtNetCoreFrontend.VtNetCoreTerminal();
//_terminalView = new XtermTerminalView();
TerminalContainer.Children.Add((UIElement)_terminalView);
_terminalView.Initialize(ViewModel);
}
@@ -0,0 +1,14 @@
<UserControl
x:Class="FluentTerminal.App.Views.VtNetCoreFrontend.VtNetCoreTerminal"
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:FluentTerminal.App.Views.VtNetCoreFrontend"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xaml="using:Microsoft.Graphics.Canvas.UI.Xaml"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<xaml:CanvasControl x:Name="canvas" IsTabStop="true" />
</UserControl>
@@ -0,0 +1,267 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using FluentTerminal.App.Services;
using FluentTerminal.App.Utilities;
using FluentTerminal.App.ViewModels;
using FluentTerminal.Models;
using FluentTerminal.Models.Enums;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
using VtNetCore.VirtualTerminal;
using VtNetCore.XTermParser;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
namespace FluentTerminal.App.Views.VtNetCoreFrontend
{
public sealed partial class VtNetCoreTerminal : UserControl, ITerminalView
{
private double _characterHeight;
private double _characterWidth;
private int _cols;
private CanvasTextFormat _format;
private int _rows;
public VtNetCoreTerminal()
{
this.InitializeComponent();
canvas.Draw += _canvas_Draw;
canvas.KeyDown += Canvas_KeyDown;
canvas.GotFocus += Canvas_GotFocus;
canvas.LostFocus += Canvas_LostFocus;
canvas.Tapped += Canvas_Tapped;
}
private void Canvas_LostFocus(object sender, RoutedEventArgs e)
{
Window.Current.CoreWindow.CharacterReceived -= CoreWindow_CharacterReceived;
}
private void Canvas_Tapped(object sender, TappedRoutedEventArgs e)
{
canvas.Focus(FocusState.Pointer);
}
private void Canvas_GotFocus(object sender, RoutedEventArgs e)
{
Window.Current.CoreWindow.CharacterReceived += CoreWindow_CharacterReceived;
Debug.WriteLine("focus");
}
private void Canvas_KeyDown(object sender, KeyRoutedEventArgs e)
{
var controlPressed = (Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down));
var shiftPressed = (Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down));
//Scrolling = false;
// Since I get the same key twice in TerminalKeyDown and in CoreWindow_CharacterReceived
// I lookup whether KeyPressed should handle the key here or there.
var code = _terminal.GetKeySequence(e.Key.ToString(), controlPressed, shiftPressed);
if (code != null)
e.Handled = _terminal.KeyPressed(e.Key.ToString(), controlPressed, shiftPressed);
canvas.Invalidate();
//if (ViewTop != _terminal.ViewPort.TopRow)
//{
// ViewTop = _terminal.ViewPort.TopRow;
// canvas.Invalidate();
//}
}
private void CoreWindow_CharacterReceived(CoreWindow sender, CharacterReceivedEventArgs args)
{
//if (!Connected)
// return;
var ch = char.ConvertFromUtf32((int)args.KeyCode);
switch (ch)
{
case "\b":
case "\t":
case "\n":
return;
case "\r":
////LogText = "";
//lock(_rawText)
//{
// _rawTextLength = 0;
// _rawTextChanged = true;
//}
return;
default:
break;
}
// Since I get the same key twice in TerminalKeyDown and in CoreWindow_CharacterReceived
// I lookup whether KeyPressed should handle the key here or there.
var code = _terminal.GetKeySequence(ch, false, false);
if (code == null)
args.Handled = _terminal.KeyPressed(ch, false, false);
}
private void _canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
var spans = _terminal.ViewPort.GetPageSpans(0, _rows, _cols);
for (var i = 0; i < spans.Count; i++)
{
var span = spans[i];
var x = 0.0;
foreach (var item in span.Spans)
{
if (item.BackgroundColor != "#000000")
{
var background = item.BackgroundColor.FromString();
args.DrawingSession.FillRectangle(new Rect { Height = _characterHeight, Width = _characterWidth * item.Text.Length, X = x, Y = i * 16 }, background);
}
var foreground = item.ForgroundColor.FromString();
args.DrawingSession.DrawText(item.Text, new System.Numerics.Vector2 { X = (float)x, Y = i * 16 }, foreground, _format);
x += item.Text.Length * _characterWidth;
}
}
}
public Task ChangeKeyBindings()
{
//throw new NotImplementedException();
return Task.CompletedTask;
}
public Task ChangeOptions(TerminalOptions options)
{
//throw new NotImplementedException();
return Task.CompletedTask;
}
public Task ChangeTheme(TerminalTheme theme)
{
//throw new NotImplementedException();
return Task.CompletedTask;
}
public Task FindNext(string searchText)
{
//throw new NotImplementedException();
return Task.CompletedTask;
}
public Task FindPrevious(string searchText)
{
//throw new NotImplementedException();
return Task.CompletedTask;
}
public Task FocusTerminal()
{
canvas.Focus(FocusState.Programmatic);
return Task.CompletedTask;
}
public TerminalViewModel ViewModel { get; private set; }
public async Task Initialize(TerminalViewModel viewModel)
{
Measure();
ViewModel = viewModel;
ViewModel.Terminal.OutputReceived += Terminal_OutputReceived;
//ViewModel.Terminal.RegisterSelectedTextCallback(() => ExecuteScriptAsync("term.getSelection()"));
//ViewModel.Terminal.Closed += Terminal_Closed;
var options = ViewModel.SettingsService.GetTerminalOptions();
var keyBindings = ViewModel.SettingsService.GetCommandKeyBindings();
var profiles = ViewModel.SettingsService.GetShellProfiles();
var settings = ViewModel.SettingsService.GetApplicationSettings();
var theme = ViewModel.TerminalTheme;
var sessionType = SessionType.Unknown;
if (settings.AlwaysUseWinPty || !ViewModel.ApplicationView.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 7))
{
sessionType = SessionType.WinPty;
}
else
{
sessionType = SessionType.ConPty;
}
var size = new Models.TerminalSize { Rows = _rows, Columns = _cols };
_terminal = new VirtualTerminalController();
_terminal.SendData = new EventHandler<SendDataEventArgs>((s, e) => { });
_dataConsumer = new DataConsumer(_terminal);
var response = await ViewModel.Terminal.StartShellProcess(ViewModel.ShellProfile, size, sessionType).ConfigureAwait(true);
if (!response.Success)
{
await ViewModel.DialogService.ShowMessageDialogAsnyc("Error", response.Error, DialogButton.OK).ConfigureAwait(true);
ViewModel.Terminal.ReportLauchFailed();
return;
}
canvas.Focus(FocusState.Keyboard);
}
private DataConsumer _dataConsumer;
private VirtualTerminalController _terminal;
private void Terminal_OutputReceived(object sender, byte[] e)
{
_dataConsumer.Push(e);
if (_terminal.Changed)
{
_terminal.ClearChanges();
canvas.Invalidate();
}
}
public void Measure()
{
var device = CanvasDevice.GetSharedDevice();
using (CanvasRenderTarget offscreen = new CanvasRenderTarget(device, (float)256, (float)256, canvas.Dpi))
{
using (CanvasDrawingSession ds = offscreen.CreateDrawingSession())
{
_format = new CanvasTextFormat
{
FontSize = 13,
FontFamily = "Consolas NF"
};
var textLayout = new CanvasTextLayout(ds, "\u2560", _format, 0.0f, 0.0f);
_characterWidth = textLayout.DrawBounds.Right;
_characterHeight = textLayout.DrawBounds.Bottom;
_cols = (int)Math.Floor(Window.Current.CoreWindow.Bounds.Width / _characterWidth);
_rows = (int)Math.Floor((Window.Current.CoreWindow.Bounds.Height - 32) / _characterHeight);
}
}
}
}
}
+6
View File
@@ -1,4 +1,5 @@
using FluentTerminal.Models.Enums;
using Windows.UI.Text;
namespace FluentTerminal.Models
{
@@ -23,5 +24,10 @@ namespace FluentTerminal.Models
public int Padding { get; set; }
public uint ScrollBackLimit { get; set; }
public FontWeight FontWeight
{
get => BoldText ? FontWeights.Bold : FontWeights.Normal;
}
}
}