From c0fb20310425246e211eb3fad8140de32890955a Mon Sep 17 00:00:00 2001 From: Yoshi Askharoun Date: Tue, 3 May 2022 11:53:36 -0500 Subject: [PATCH] Switched to Gemini for UI --- ZuneUIXTools/App.xaml | 10 +- ZuneUIXTools/MainWindow.xaml.cs | 11 +- .../Commands/BuildAndRunCommandDefinition.cs | 24 +++ .../Modules/Shell/ToolBarDefinitions.cs | 24 +++ .../Shell/ViewModels/ShellViewModel.cs | 48 ++++++ ZuneUIXTools/Modules/Startup/Module.cs | 62 +++++++ .../Modules/UIXCompiled/UIBEditorProvider.cs | 38 +++++ .../UIXCompiled/UIXCompiledEditorView.xaml | 11 ++ .../UIXCompiled/UIXCompiledEditorView.xaml.cs | 28 ++++ .../UIXCompiled/UIXCompiledEditorViewModel.cs | 65 ++++++++ .../Modules/UIXSource/UIXEditorProvider.cs | 38 +++++ .../UIXSource/UIXSourceEditorView.xaml | 14 ++ .../UIXSource/UIXSourceEditorView.xaml.cs | 28 ++++ .../UIXSource/UIXSourceEditorViewModel.cs | 157 ++++++++++++++++++ ZuneUIXTools/ZuneUIXTools.csproj | 19 +-- test/ZuneTestHost.0.decomp.uix | 8 + test/ZuneTestHost.uib | Bin 0 -> 617 bytes test/ZuneTestHost.uix | 18 ++ test/text.uib | Bin 2354 -> 2354 bytes 19 files changed, 586 insertions(+), 17 deletions(-) create mode 100644 ZuneUIXTools/Modules/Shell/Commands/BuildAndRunCommandDefinition.cs create mode 100644 ZuneUIXTools/Modules/Shell/ToolBarDefinitions.cs create mode 100644 ZuneUIXTools/Modules/Shell/ViewModels/ShellViewModel.cs create mode 100644 ZuneUIXTools/Modules/Startup/Module.cs create mode 100644 ZuneUIXTools/Modules/UIXCompiled/UIBEditorProvider.cs create mode 100644 ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorView.xaml create mode 100644 ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorView.xaml.cs create mode 100644 ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorViewModel.cs create mode 100644 ZuneUIXTools/Modules/UIXSource/UIXEditorProvider.cs create mode 100644 ZuneUIXTools/Modules/UIXSource/UIXSourceEditorView.xaml create mode 100644 ZuneUIXTools/Modules/UIXSource/UIXSourceEditorView.xaml.cs create mode 100644 ZuneUIXTools/Modules/UIXSource/UIXSourceEditorViewModel.cs create mode 100644 test/ZuneTestHost.0.decomp.uix create mode 100644 test/ZuneTestHost.uib create mode 100644 test/ZuneTestHost.uix diff --git a/ZuneUIXTools/App.xaml b/ZuneUIXTools/App.xaml index d15a8af..339fc2a 100644 --- a/ZuneUIXTools/App.xaml +++ b/ZuneUIXTools/App.xaml @@ -2,8 +2,14 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ZuneUIXTools" - StartupUri="MainWindow.xaml"> + xmlns:gemini="http://schemas.timjones.io/gemini"> - + + + + + + + diff --git a/ZuneUIXTools/MainWindow.xaml.cs b/ZuneUIXTools/MainWindow.xaml.cs index 8289432..5925575 100644 --- a/ZuneUIXTools/MainWindow.xaml.cs +++ b/ZuneUIXTools/MainWindow.xaml.cs @@ -231,18 +231,19 @@ namespace ZuneUIXTools try { + Microsoft.Iris.Debug.Trace.EnableAllCategories(true); Application.Initialize(); } catch { } try { - Application.Window.RequestLoad("file://" + compiledFile + (string.IsNullOrEmpty(uiRoot) ? string.Empty : "#" + uiRoot)); - InterpreterContext.UseDecompile = true; - Application.Run(); - InterpreterContext.UseDecompile = false; + Application.Window.RequestLoad("res://ZuneShellResources!Frame.uix#Frame"); - File.WriteAllText(System.IO.Path.ChangeExtension(compiledFile, $".decomp.uix"), InterpreterContext.DecompileResults.Last().InnerXml); + //Application.Window.RequestLoad("file://" + compiledFile + (string.IsNullOrEmpty(uiRoot) ? string.Empty : "#" + uiRoot)); + Application.DebugSettings.UseDecompiler = true; + Application.Run(); + Application.DebugSettings.UseDecompiler = false; } catch (Exception ex) { diff --git a/ZuneUIXTools/Modules/Shell/Commands/BuildAndRunCommandDefinition.cs b/ZuneUIXTools/Modules/Shell/Commands/BuildAndRunCommandDefinition.cs new file mode 100644 index 0000000..c29fb93 --- /dev/null +++ b/ZuneUIXTools/Modules/Shell/Commands/BuildAndRunCommandDefinition.cs @@ -0,0 +1,24 @@ +using Gemini.Framework.Commands; +using System; +using System.ComponentModel.Composition; +using System.Windows.Input; + +namespace ZuneUIXTools.Modules.Shell.Commands +{ + [CommandDefinition] + public class BuildAndRunCommandDefinition : CommandDefinition + { + public const string CommandName = "Project.BuildAndRun"; + + public override string Name => CommandName; + + public override string Text => "Build and Run"; + + public override string ToolTip => "Compiles the current UIX document and runs it."; + + public override Uri IconSource => new("pack://application:,,,/ZuneUIXTools;component/Images/StartWithoutDebug_16x.png"); + + [Export] + public static CommandKeyboardShortcut KeyGesture = new CommandKeyboardShortcut(new KeyGesture(Key.F5)); + } +} diff --git a/ZuneUIXTools/Modules/Shell/ToolBarDefinitions.cs b/ZuneUIXTools/Modules/Shell/ToolBarDefinitions.cs new file mode 100644 index 0000000..5a102c1 --- /dev/null +++ b/ZuneUIXTools/Modules/Shell/ToolBarDefinitions.cs @@ -0,0 +1,24 @@ +using Gemini.Framework.ToolBars; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ZuneUIXTools.Modules.Shell.Commands; + +namespace ZuneUIXTools.Modules.Shell +{ + internal static class ToolBarDefinitions + { + [Export] + public static ToolBarDefinition StandardToolBar = new(0, "Standard"); + + [Export] + public static ToolBarItemGroupDefinition StandardOpenSaveToolBarGroup = new(StandardToolBar, 8); + + [Export] + public static ToolBarItemDefinition OpenFileToolBarItem = new CommandToolBarItemDefinition( + StandardOpenSaveToolBarGroup, 0); + } +} diff --git a/ZuneUIXTools/Modules/Shell/ViewModels/ShellViewModel.cs b/ZuneUIXTools/Modules/Shell/ViewModels/ShellViewModel.cs new file mode 100644 index 0000000..a2cf54d --- /dev/null +++ b/ZuneUIXTools/Modules/Shell/ViewModels/ShellViewModel.cs @@ -0,0 +1,48 @@ +using Caliburn.Micro; +using Gemini.Framework.Services; +using Gemini.Framework.Threading; +using Gemini.Modules.Shell.Views; +using Gemini.Modules.ToolBars; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Threading; +using System.Threading.Tasks; + +namespace ZuneUIXTools.Modules.Shell.ViewModels +{ + [Export(typeof(IShell))] + public class ShellViewModel : Gemini.Modules.Shell.ViewModels.ShellViewModel + { + static ShellViewModel() + { + ViewLocator.AddNamespaceMapping(typeof(ShellViewModel).Namespace, typeof(ShellView).Namespace); + } + + public override Task CanCloseAsync(CancellationToken cancellationToken) + { + var tcs = new TaskCompletionSource(); + + Coroutine.BeginExecute(CanClose().GetEnumerator(), null, (s, e) => tcs.SetResult(!e.WasCancelled)); + + return tcs.Task; + } + + private IEnumerable CanClose() + { + yield return new MessageBoxResult(); + } + + private class MessageBoxResult : IResult + { + public event EventHandler Completed; + + public void Execute(CoroutineExecutionContext context) + { + var result = System.Windows.MessageBoxResult.Yes; + + Completed(this, new ResultCompletionEventArgs { WasCancelled = (result != System.Windows.MessageBoxResult.Yes) }); + } + } + } +} diff --git a/ZuneUIXTools/Modules/Startup/Module.cs b/ZuneUIXTools/Modules/Startup/Module.cs new file mode 100644 index 0000000..26b72b5 --- /dev/null +++ b/ZuneUIXTools/Modules/Startup/Module.cs @@ -0,0 +1,62 @@ +using Gemini.Framework; +using Gemini.Modules.ErrorList; +using Gemini.Modules.Output; +using Microsoft.Iris.Markup; +using Microsoft.Iris.Session; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media.Imaging; + +namespace ZuneUIXTools.Modules.Startup +{ + [Export(typeof(IModule))] + public class Module : ModuleBase + { + private readonly IOutput _output; + private readonly IErrorList _errorList; + + [ImportingConstructor] + public Module(IOutput output, IErrorList errorList) + { + _output = output; + _errorList = errorList; + } + + public override void Initialize() + { + Shell.ShowFloatingWindowsInTaskbar = true; + Shell.ToolBars.Visible = true; + + //MainWindow.WindowState = WindowState.Maximized; + MainWindow.Title = "Zune UIX Tools"; + MainWindow.Icon = new BitmapImage(new Uri("pack://application:,,,/ZuneUIXTools;component/Images/VCSIrisProject.ico")); + + MarkupSystem.Startup(true); + ErrorManager.OnErrors += (IList errors) => { + foreach (object obj in errors) + { + if (obj is not ErrorRecord err) continue; + +#if DEBUG + System.Diagnostics.Debug.WriteLine(err.Message); +#else + Console.WriteLine(err.Message); +#endif + + _errorList.AddItem(err.Warning ? ErrorListItemType.Warning : ErrorListItemType.Error, + err.Message, err.Context, err.Line < 0 ? null : err.Line, err.Column < 0 ? null : err.Column); + } + }; + + Shell.StatusBar.AddItem("UIX ready", new GridLength(1, GridUnitType.Star)); + + _output.AppendLine("Initialized UIX markup system"); + } + } +} diff --git a/ZuneUIXTools/Modules/UIXCompiled/UIBEditorProvider.cs b/ZuneUIXTools/Modules/UIXCompiled/UIBEditorProvider.cs new file mode 100644 index 0000000..08a5ac4 --- /dev/null +++ b/ZuneUIXTools/Modules/UIXCompiled/UIBEditorProvider.cs @@ -0,0 +1,38 @@ +using Gemini.Framework; +using Gemini.Framework.Services; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using System.Threading.Tasks; + +namespace ZuneUIXTools.Modules.UIXCompiled +{ + [Export(typeof(IEditorProvider))] + public class UIBEditorProvider : IEditorProvider + { + private static readonly List _extensions = new() + { + ".uib", + }; + + public IEnumerable FileTypes + { + get { yield return new EditorFileType("Compiled Microsoft Iris UI", ".uib"); } + } + + public bool CanCreateNew => false; + + public bool Handles(string path) + { + var extension = Path.GetExtension(path); + return _extensions.Contains(extension.ToLowerInvariant()); + } + + public IDocument Create() => new UIXCompiledEditorViewModel(); + + public async Task New(IDocument document, string name) => await ((UIXCompiledEditorViewModel)document).New(name); + + public async Task Open(IDocument document, string path) => await ((UIXCompiledEditorViewModel)document).Load(path); + } +} diff --git a/ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorView.xaml b/ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorView.xaml new file mode 100644 index 0000000..6a79056 --- /dev/null +++ b/ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorView.xaml @@ -0,0 +1,11 @@ + + + diff --git a/ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorView.xaml.cs b/ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorView.xaml.cs new file mode 100644 index 0000000..cdfea58 --- /dev/null +++ b/ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace ZuneUIXTools.Modules.UIXCompiled +{ + /// + /// Interaction logic for UIXCompiledEditorView.xaml + /// + public partial class UIXCompiledEditorView : UserControl + { + public UIXCompiledEditorView() + { + InitializeComponent(); + } + } +} diff --git a/ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorViewModel.cs b/ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorViewModel.cs new file mode 100644 index 0000000..9d82890 --- /dev/null +++ b/ZuneUIXTools/Modules/UIXCompiled/UIXCompiledEditorViewModel.cs @@ -0,0 +1,65 @@ +using Gemini.Framework; +using Gemini.Framework.Threading; +using System; +using System.ComponentModel.Composition; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace ZuneUIXTools.Modules.UIXCompiled +{ + [Export(typeof(UIXCompiledEditorViewModel))] +#pragma warning disable 659 + public class UIXCompiledEditorViewModel : PersistedDocument +#pragma warning restore 659 + { + private UIXCompiledEditorView _view; + private byte[] _originalBytes; + + protected override Task DoNew() + { + _originalBytes = Array.Empty(); + ApplyOriginalText(); + return TaskUtility.Completed; + } + + protected override Task DoLoad(string filePath) + { + _originalBytes = File.ReadAllBytes(filePath); + ApplyOriginalText(); + return TaskUtility.Completed; + } + + protected override Task DoSave(string filePath) + { + _view.HexEditor.SaveCurrentState(filePath); + _originalBytes = _view.HexEditor.GetAllBytes(); + return TaskUtility.Completed; + } + + private void ApplyOriginalText() + { + _view.HexEditor.Stream?.Dispose(); + _view.HexEditor.Stream = new MemoryStream(_originalBytes); + _view.HexEditor.UpdateVisual(); + + _view.HexEditor.BytesModified += delegate + { + IsDirty = !_originalBytes.SequenceEqual(_view.HexEditor.GetAllBytes()); + }; + } + + protected override void OnViewLoaded(object view) + { + _view = (UIXCompiledEditorView)view; + } + + public override bool Equals(object obj) + { + var other = obj as UIXCompiledEditorViewModel; + return other != null + && string.Equals(FilePath, other.FilePath, StringComparison.InvariantCultureIgnoreCase) + && string.Equals(FileName, other.FileName, StringComparison.InvariantCultureIgnoreCase); + } + } +} \ No newline at end of file diff --git a/ZuneUIXTools/Modules/UIXSource/UIXEditorProvider.cs b/ZuneUIXTools/Modules/UIXSource/UIXEditorProvider.cs new file mode 100644 index 0000000..61bef61 --- /dev/null +++ b/ZuneUIXTools/Modules/UIXSource/UIXEditorProvider.cs @@ -0,0 +1,38 @@ +using Gemini.Framework; +using Gemini.Framework.Services; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using System.Threading.Tasks; + +namespace ZuneUIXTools.Modules.UIXSource +{ + [Export(typeof(IEditorProvider))] + public class UIXEditorProvider : IEditorProvider + { + private static readonly List _extensions = new() + { + ".uix", + ".xml" + }; + + public IEnumerable FileTypes + { + get { yield return new EditorFileType("Microsoft Iris UI", ".uix"); } + } + + public bool CanCreateNew => true; + + public bool Handles(string path) + { + var extension = Path.GetExtension(path); + return _extensions.Contains(extension.ToLowerInvariant()); + } + + public IDocument Create() => new UIXSourceEditorViewModel(); + + public async Task New(IDocument document, string name) => await ((UIXSourceEditorViewModel)document).New(name); + + public async Task Open(IDocument document, string path) => await ((UIXSourceEditorViewModel)document).Load(path); + } +} diff --git a/ZuneUIXTools/Modules/UIXSource/UIXSourceEditorView.xaml b/ZuneUIXTools/Modules/UIXSource/UIXSourceEditorView.xaml new file mode 100644 index 0000000..4cf3e3c --- /dev/null +++ b/ZuneUIXTools/Modules/UIXSource/UIXSourceEditorView.xaml @@ -0,0 +1,14 @@ + + + + + diff --git a/ZuneUIXTools/Modules/UIXSource/UIXSourceEditorView.xaml.cs b/ZuneUIXTools/Modules/UIXSource/UIXSourceEditorView.xaml.cs new file mode 100644 index 0000000..41a4040 --- /dev/null +++ b/ZuneUIXTools/Modules/UIXSource/UIXSourceEditorView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace ZuneUIXTools.Modules.UIXSource +{ + /// + /// Interaction logic for UIXSourceEditorView.xaml + /// + public partial class UIXSourceEditorView : UserControl + { + public UIXSourceEditorView() + { + InitializeComponent(); + } + } +} diff --git a/ZuneUIXTools/Modules/UIXSource/UIXSourceEditorViewModel.cs b/ZuneUIXTools/Modules/UIXSource/UIXSourceEditorViewModel.cs new file mode 100644 index 0000000..2347817 --- /dev/null +++ b/ZuneUIXTools/Modules/UIXSource/UIXSourceEditorViewModel.cs @@ -0,0 +1,157 @@ +using System; +using System.ComponentModel.Composition; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using Gemini.Framework; +using Gemini.Framework.Commands; +using Gemini.Framework.Threading; +using Microsoft.Iris; +using Microsoft.Iris.Markup; +using ZuneUIXTools.Modules.Shell.Commands; +using Application = Microsoft.Iris.Application; +using Command = Gemini.Framework.Commands.Command; + +namespace ZuneUIXTools.Modules.UIXSource +{ + [Export(typeof(UIXSourceEditorViewModel))] +#pragma warning disable 659 + public class UIXSourceEditorViewModel : PersistedDocument, ICommandHandler +#pragma warning restore 659 + { + private UIXSourceEditorView _view; + private string _originalText; + + protected override Task DoNew() + { + _originalText = string.Empty; + ApplyOriginalText(); + return TaskUtility.Completed; + } + + protected override Task DoLoad(string filePath) + { + _originalText = File.ReadAllText(filePath); + ApplyOriginalText(); + return TaskUtility.Completed; + } + + protected override Task DoSave(string filePath) + { + _view.CodeEditor.Save(filePath); + _originalText = _view.CodeEditor.Text; + return TaskUtility.Completed; + } + + private void ApplyOriginalText() + { + _view.CodeEditor.Text = _originalText; + + _view.CodeEditor.TextChanged += delegate + { + IsDirty = string.Compare(_originalText, _view.CodeEditor.Text) != 0; + }; + } + + protected override void OnViewLoaded(object view) + { + _view = (UIXSourceEditorView)view; + } + + public override bool Equals(object obj) + { + var other = obj as UIXSourceEditorViewModel; + return other != null + && string.Equals(FilePath, other.FilePath, StringComparison.InvariantCultureIgnoreCase) + && string.Equals(FileName, other.FileName, StringComparison.InvariantCultureIgnoreCase); + } + + void ICommandHandler.Update(Command command) + { + command.Enabled = !string.IsNullOrWhiteSpace(_view.CodeEditor.Text); + } + + Task ICommandHandler.Run(Command command) + { + var _buildThread = new Thread(new ThreadStart(BuildAndRun)); + _buildThread.SetApartmentState(ApartmentState.STA); + _buildThread.IsBackground = true; + _buildThread.Start(); + + return TaskUtility.Completed; + } + + private void BuildAndRun() + { + string sourceFile = FilePath; + string compiledFile = Path.ChangeExtension(sourceFile, "uib"); + bool isSuccess = false; + try + { + isSuccess = MarkupCompiler.Compile( + new[] + { + new CompilerInput() + { + SourceFileName = sourceFile, + OutputFileName = compiledFile + } + }, + new CompilerInput() + ); + } + catch (Exception ex) + { + //Dispatcher.Invoke(() => + //{ + // ErrorPanel.Children.Add(new TextBlock + // { + // Text = $"Build failed: {ex.Message}", + // Margin = new Thickness(0, 0, 0, 4) + // }); + //}); + } + + if (!isSuccess) + { + var dialogResult = MessageBox.Show( + "There were build errors. Would you like to contine and run the last successful build?", + "Zune UIX Tools", MessageBoxButton.YesNo, MessageBoxImage.Information + ); + if (dialogResult != MessageBoxResult.Yes) + return; + } + + try + { + Application.Initialize(); + } + catch { } + + try + { + string uiRoot = null;// (IrisProject.SelectedDocument as UIXDocumentViewModel)?.UIRoot; + Application.Window.SetBackgroundColor(new WindowColor(0xE6, 0xE6, 0xE6)); + Application.Window.RequestLoad("file://" + compiledFile + (string.IsNullOrEmpty(uiRoot) ? string.Empty : "#" + uiRoot)); + Application.Window.CloseRequested += (object sender, WindowCloseRequestedEventArgs args) => + { + args.BlockCloseRequest(); + Application.Window.Visible = false; + }; + Application.Run(); + } + catch (Exception ex) + { + //Dispatcher.Invoke(() => + //{ + // ErrorPanel.Children.Add(new TextBlock + // { + // Text = $"Load failed: {ex.Message}", + // Margin = new Thickness(0, 0, 0, 4) + // }); + //}); + } + } + } +} \ No newline at end of file diff --git a/ZuneUIXTools/ZuneUIXTools.csproj b/ZuneUIXTools/ZuneUIXTools.csproj index 77b7952..c291475 100644 --- a/ZuneUIXTools/ZuneUIXTools.csproj +++ b/ZuneUIXTools/ZuneUIXTools.csproj @@ -21,21 +21,20 @@ - - - - - - - - - + + + + + - + + + + diff --git a/test/ZuneTestHost.0.decomp.uix b/test/ZuneTestHost.0.decomp.uix new file mode 100644 index 0000000..a5dc9bf --- /dev/null +++ b/test/ZuneTestHost.0.decomp.uix @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/test/ZuneTestHost.uib b/test/ZuneTestHost.uib new file mode 100644 index 0000000000000000000000000000000000000000..7fa8b7ed00da7c7181d4ad62e6152c0df05f751e GIT binary patch literal 617 zcmWIbbdvhQ%)p?_#K7PV#hFYD4FCV%W?*1oVPIrnU|?VblT08MGl*bd0h1spPKJN~ zSs54@{{3eIaT(Yd7#NrtIKU#D3=9lR3|wHf++dOiEY1sN|NsC0za&@>b^>GvrVPk_ zKCm793=9lx3<7W^j9^T1@PL7V;T;15!*>P-hW`u<44jM%48n{I4AP7Y49biQ3_6Sq491KM3|5Q`41OT7 zhN9GBD}DW_(!A8*jMSW*pw#00(xT+lVnvtC#GL$ez0%AI8K|OA&j{!Iypp2)9AsJP zhQ#9H)ZC<;N@R1uCWd-SW6>IrUr<^AGMBxV{ZUCG&Qe;wZS(( zB{hc?Vu( + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/text.uib b/test/text.uib index 4fbcb3c15b711bac6c3863c54fcbf7ed865e0586..34a72ecdba7e12844650289d79c3790ceec9c98c 100644 GIT binary patch delta 263 zcmdlav`J`#2}gYcGs6Z327ZPHW(E#M1|bFpW`+d}36a-FnEAy z0Y(Nt5dDCWA(nxGouPn%AsIw3U|`5$XkZ7KQv{-KFfder=nh7PIuNbE#LxnwS1>Vj zF*L9-oM2*@%5Z=aq<>yLg98^x;}Q^kgMncch%R7c*v8NR7T*J+Z!j<%0?`GG3@1SJ z2S$c-3=W(O0?Z6I84mD(47v}Z7celqU~u3CnfDGv-(X<)0-`4{GW-J3983&sj0bob Q8WD=28H5-dm>Cu@Fc>g2FfmMEU~pn^U}BiTz~BL* z1sECpK=cDfhFAs%c7_55hGY=EfPo>0;Q%|xoFWi?gMpy}M0YSU)PZOPCWaOey@H9M zi{Stp!wDvasSFHUApP^|85+1i8kd0R8w?DqKy(2k!#0KkVDUX5`UV5TArM`_$Z!Hg ze_&)d$I!sZAi&IUlYxO3WYB#Oy?}w?1w#Wb$h>zT`UV5T7Z5#xk>MAJ=3ruAV`SiC QXkcUzVQk=GxWU8#0EEFd$N&HU