Skip to content

Instantly share code, notes, and snippets.

@chrisforbes
Created June 30, 2010 07:51
Show Gist options
  • Save chrisforbes/458370 to your computer and use it in GitHub Desktop.
Save chrisforbes/458370 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Globalization;
namespace formatter
{
// supported codes:
// \fb; \fr; -- font bold/regular.
// \al; \ar; -- align left/right
// \cRRGGBB; -- color
// \cz; -- reset to default color
// \n -- newline
// \t -- next tabstop
// \\; -- escaped slash
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
textBox1.Text = @"\fb;Tesla Coil (\cffff00;J\cz;)\ar;$1200\n;\fr;\al;\cff0000;Requires War Factory\cz;\ar;\fb;-150\n;\fr;\al;A hax weapon. Chews up tanks. A really insanely long LongDesc so Alzeih can see that wordwrap works, although color- and hyphenation-unaware typography really does nothing for me.\n;\t;Strong vs \fb;\c00cc00;Infantry, Vehicles\cz;\fr;\n;\t;Weak vs \fb;\ccc0000;Aircraft\cz;\fr;";
}
static IEnumerable<string> Tokens(string s)
{
var i = 0;
var inOpcode = false;
for( var j = 0; j < s.Length; j++ )
if (!inOpcode) { if (s[j] == '\\') { yield return s.Substring(i, j - i); i = j; inOpcode = true; } }
else { if (s[j] == ';') { yield return s.Substring(i, j - i + 1); i = j + 1; inOpcode = false; } }
if (i < s.Length) yield return s.Substring(i);
}
string fmt = "";
void UpdateRendering(object sender, EventArgs e)
{
fmt = textBox1.Text;
panel1.Invalidate();
}
Brush ReplaceBrush(Brush old, Color c)
{
old.Dispose();
return new SolidBrush(c);
}
int ParseHex(string s, int start, int length)
{
var t = s.Substring(start, length);
return int.Parse(t, NumberStyles.HexNumber);
}
const int tabWidth = 20;
const int layoutWidth = 250;
const int leftEdge = 20;
void PaintPanel(object sender, PaintEventArgs e)
{
var rf = panel1.Font;
var bf = new Font(rf, FontStyle.Bold);
var f = rf;
var b = new SolidBrush(Color.White) as Brush;
var y = 20;
var x = (float)leftEdge;
var rightAlign = false;
foreach (var t in Tokens(fmt.Replace("\r\n", "")))
{
if (t == @"\fb;") f = bf;
else if (t == @"\fr;") f = rf;
else if (t == @"\n;") { y += f.Height; x = rightAlign ? layoutWidth : leftEdge; }
else if (t == @"\cz;") { b = ReplaceBrush(b, Color.White); }
else if (t == @"\al;") { rightAlign = false; x = leftEdge; }
else if (t == @"\ar;") { rightAlign = true; x = layoutWidth; }
else if (t.StartsWith(@"\c")) { b = ReplaceBrush(b, Color.FromArgb(ParseHex(t, 2, 2), ParseHex(t, 4, 2), ParseHex(t, 6, 2))); }
else if (t == @"\t;") { x += tabWidth; x -= (int)(x-leftEdge) % tabWidth; }
else
{
var s = (t == @"\\;") ? @"\" : t;
var w = e.Graphics.MeasureString(t, f);
if (rightAlign)
{
e.Graphics.DrawString(t, f, b, x - w.Width, y);
x -= w.Width;
}
else
{
if (w.Width + x > layoutWidth)
{
// do wrapping
var spaceWidth = e.Graphics.MeasureString("._.", f).Width - e.Graphics.MeasureString("__",f).Width;
var words = t.Split(' ');
foreach (var ww in words)
{
var width = e.Graphics.MeasureString(ww, f);
if (x + width.Width < layoutWidth)
{
e.Graphics.DrawString(ww, f, b, x, y);
x += width.Width + spaceWidth;
}
else
{
x = leftEdge;
y += f.Height;
e.Graphics.DrawString(ww, f, b, x, y);
x += width.Width + spaceWidth;
}
}
}
else
{
e.Graphics.DrawString(t, f, b, x, y);
x += w.Width;
}
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment