diff --git a/src/ConsoleBuffer/Buffer.cs b/src/ConsoleBuffer/Buffer.cs
index 07c0258..66d33c3 100644
--- a/src/ConsoleBuffer/Buffer.cs
+++ b/src/ConsoleBuffer/Buffer.cs
@@ -124,7 +124,13 @@ private void HandleControlCharacter(ControlCharacterCommand.ControlCode code)
break;
case ControlCharacterCommand.ControlCode.FF: // NB: could clear screen with this if we were so inclined. apparently xterm treats this as LF though, let's emulate.
case ControlCharacterCommand.ControlCode.LF:
- if (this.currentLine == this.lines.Count - 1)
+ if (this.currentLine == short.MaxValue)
+ {
+ // XXX: perf nightmare, need to turn lines into a circular buffer probs.
+ this.lines.RemoveAt(0);
+ this.lines.Add(new Line());
+ }
+ else if (this.currentLine == this.lines.Count - 1)
{
this.lines.Add(new Line());
}
@@ -149,20 +155,20 @@ public void Render(IRenderTarget target)
{
lock (this.renderLock)
{
- for (var x = 0; x < this.Height; ++x)
+ for (var y = 0; y < this.Height; ++y)
{
- var renderLine = this.bufferTopVisibleLine + x;
+ var renderLine = this.bufferTopVisibleLine + y;
var line = renderLine < this.lines.Count ? this.lines[renderLine] : Line.Empty;
- short y = 0;
+ short x = 0;
foreach (var c in line)
{
target.RenderCharacter(c, x, y);
- ++y;
+ ++x;
}
- while (y < this.Width)
+ while (x < this.Width)
{
target.RenderCharacter(new Character { Glyph = ' ' }, x, y);
- ++y;
+ ++x;
}
}
}
diff --git a/src/ConsoleBuffer/ConsoleWrapper.cs b/src/ConsoleBuffer/ConsoleWrapper.cs
index 9ac056d..0b5b804 100644
--- a/src/ConsoleBuffer/ConsoleWrapper.cs
+++ b/src/ConsoleBuffer/ConsoleWrapper.cs
@@ -166,11 +166,13 @@ private void ReadConsoleTask()
// this can happen when our parent disposes, safe to bail out silently.
return;
}
+ /*
catch (Exception ex) // XXX: this is some lousy logging I don't normally recommend, need to kill later.
{
Logger.Verbose(ex.ToString());
throw;
}
+ */
}
}
}
diff --git a/src/ConsoleBuffer/IRenderTarget.cs b/src/ConsoleBuffer/IRenderTarget.cs
index 0b43f4b..0029ee9 100644
--- a/src/ConsoleBuffer/IRenderTarget.cs
+++ b/src/ConsoleBuffer/IRenderTarget.cs
@@ -5,9 +5,9 @@ public interface IRenderTarget
///
/// Instructs the target to render the character 'c' at x/y coordinates.
///
- /// Character to render.
/// Horizontal offset.
/// Vertical offset.
+ /// Character to render.
void RenderCharacter(Character c, int x, int y);
}
}
diff --git a/src/condo/MainWindow.xaml b/src/condo/MainWindow.xaml
index 912b935..84f94ca 100644
--- a/src/condo/MainWindow.xaml
+++ b/src/condo/MainWindow.xaml
@@ -6,7 +6,7 @@
xmlns:local="clr-namespace:condo"
mc:Ignorable="d"
Title="MainWindow" SizeToContent="WidthAndHeight">
-
-
+
+
diff --git a/src/condo/MainWindow.xaml.cs b/src/condo/MainWindow.xaml.cs
index 182a216..017a800 100644
--- a/src/condo/MainWindow.xaml.cs
+++ b/src/condo/MainWindow.xaml.cs
@@ -1,6 +1,7 @@
namespace condo
{
using System.ComponentModel;
+ using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.Windows;
@@ -13,7 +14,7 @@
///
public partial class MainWindow : Window, IRenderTarget
{
- private DpiScale dpiInfo;
+ private Screen screen;
private ConsoleWrapper console;
private KeyHandler keyHandler;
private Character[,] characters;
@@ -26,36 +27,24 @@ public MainWindow()
System.Diagnostics.Debugger.Launch();
}
+
private void UpdateContents(object sender, PropertyChangedEventArgs args)
{
this.console.Buffer.Render(this);
- this.Dispatcher.InvokeAsync(() => this.Redraw());
- }
-
- private Size DetermineSize()
- {
- DpiScale dpi = this.dpiInfo;
-
- // because we only ever expect to work with monospace fonts we can extrapolate from any single character.
- // lord help if someone gets real excited about proportional font console.
- var sampleText = new FormattedText("x", CultureInfo.CurrentUICulture, FlowDirection.LeftToRight,
- new Typeface(this.stuff.FontFamily, this.stuff.FontStyle, this.stuff.FontWeight, this.stuff.FontStretch),
- this.stuff.FontSize, Brushes.Black, dpi.PixelsPerDip);
-
- return new Size(sampleText.Width * this.console.Width, sampleText.Height * this.console.Height);
+ this.Dispatcher.InvokeAsync(() => this.Redraw());
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
- this.dpiInfo = VisualTreeHelper.GetDpi(this);
+ this.screen = new Screen();
+ this.screenCanvas.Children.Add(this.screen);
+ this.screenCanvas.Width = this.screen.Width;
+ this.screenCanvas.Height = this.screen.Height;
+
this.console = TerminalManager.Instance.GetOrCreate(0, "cmd.exe");
this.keyHandler = new KeyHandler(this.console);
- var stuffSize = this.DetermineSize();
- this.stuff.Height = stuffSize.Height;
- this.stuff.Width = stuffSize.Width;
-
- this.characters = new Character[this.console.Height, this.console.Width];
+ this.characters = new Character[this.console.Width, this.console.Height];
this.Redraw();
this.console.PropertyChanged += this.UpdateContents;
@@ -82,17 +71,13 @@ private void HandleClosing(object sender, CancelEventArgs e)
private void Redraw()
{
- var sb = new StringBuilder();
- for (var x = 0; x < this.console.Height; ++x)
+ for (var x = 0; x < this.console.Width; ++x)
{
- for (var y = 0; y < this.console.Width; ++y)
+ for (var y = 0; y < this.console.Height; ++y)
{
- sb.Append((char)this.characters[x, y].Glyph);
+ this.screen.SetCellCharacter(x, y, (char)this.characters[x, y].Glyph);
}
- sb.Append('\n');
}
-
- this.stuff.Text = sb.ToString();
}
public void RenderCharacter(Character c, int x, int y)
diff --git a/src/condo/Screen.cs b/src/condo/Screen.cs
new file mode 100644
index 0000000..7b620fa
--- /dev/null
+++ b/src/condo/Screen.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Windows;
+using System.Windows.Media;
+
+namespace condo
+{
+ public sealed class Screen : FrameworkElement
+ {
+ private VisualCollection cells;
+ private DpiScale dpiInfo;
+ private readonly GlyphTypeface typeface;
+ private readonly int fontSize = 14;
+ private readonly double cellWidth, cellHeight;
+ private readonly Point baselineOrigin;
+ private readonly Rect cellRectangle;
+ private int horizontalCells, verticalCells;
+
+ public Screen() : this(80, 25) { }
+
+ public Screen(int width, int height)
+ {
+ this.cells = new VisualCollection(this);
+ if (!new Typeface("Consolas").TryGetGlyphTypeface(out this.typeface))
+ {
+ throw new InvalidOperationException("Could not get desired font.");
+ }
+
+ this.horizontalCells = width;
+ this.verticalCells = height;
+
+ this.cellWidth = this.typeface.AdvanceWidths[0] * this.fontSize;
+ this.cellHeight = this.typeface.Height * this.fontSize;
+ this.baselineOrigin = new Point(0, this.typeface.Baseline * this.fontSize);
+ this.cellRectangle = new Rect(new Size(this.cellWidth, this.cellHeight));
+
+ this.dpiInfo = VisualTreeHelper.GetDpi(this);
+ this.Resize();
+ }
+
+ protected override int VisualChildrenCount => this.cells.Count;
+
+ protected override Visual GetVisualChild(int index)
+ {
+ return this.cells[index];
+ }
+
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ return new Size(this.cellWidth * this.horizontalCells, this.cellHeight * this.verticalCells);
+ }
+
+ private void Resize()
+ {
+ this.cells.Clear();
+ for (var y = 0; y < this.verticalCells; ++y)
+ {
+ for (var x = 0; x < this.horizontalCells; ++x)
+ {
+ var dv = new DrawingVisual();
+ dv.Offset = new Vector(x * this.cellWidth, y * this.cellHeight);
+ this.cells.Add(dv);
+ }
+ }
+
+ this.Width = this.horizontalCells * this.cellWidth;
+ this.Height = this.verticalCells * this.cellHeight;
+ }
+
+ private DrawingVisual GetCell(int x, int y)
+ {
+ return this.cells[x + y * this.horizontalCells] as DrawingVisual;
+ }
+
+ public void SetCellCharacter(int x, int y, char c)
+ {
+ using (var dc = this.GetCell(x, y).RenderOpen())
+ {
+ GlyphRun gr;
+ try
+ {
+ gr = new GlyphRun(this.typeface, 0, false, this.fontSize, (float)this.dpiInfo.PixelsPerDip, new[] { this.typeface.CharacterToGlyphMap[c] },
+ this.baselineOrigin, new[] { 0.0 }, new[] { new Point(0, 0) }, null, null, null, null, null);
+ }
+ catch (KeyNotFoundException)
+ {
+ gr = new GlyphRun(this.typeface, 0, false, this.fontSize, (float)this.dpiInfo.PixelsPerDip, new[] { this.typeface.CharacterToGlyphMap[0] },
+ this.baselineOrigin, new[] { 0.0 }, new[] { new Point(0, 0) }, null, null, null, null, null);
+ }
+
+ dc.DrawRectangle(Brushes.Black, null, new Rect(new Point(0, 0), new Point(this.cellWidth, this.cellHeight)));
+ dc.DrawGlyphRun(Brushes.Gray, gr);
+ }
+ }
+ }
+}
diff --git a/src/condo/condo.csproj b/src/condo/condo.csproj
index 47577da..d648eec 100644
--- a/src/condo/condo.csproj
+++ b/src/condo/condo.csproj
@@ -56,6 +56,7 @@
Designer
+
MSBuild:Compile