/FileInput.cs
using System;
using System.IO;
using System.Collections;
using Cairo;
using Gtk;
using Gdk;

class FileSelector : TextInput {
	private string filestr;

	public FileSelector() : base(Directory.GetCurrentDirectory() + System.IO.Path.DirectorySeparatorChar) {
		Complete();
	}

	protected override void draw(Cairo.Context gr, int width, int height) {
		base.draw(gr, width, height);

		gr.LineWidth = 1.0;
		gr.NewPath();
		gr.MoveTo(0, 13.5);
		gr.LineTo(width, 13.5);
		gr.Stroke();

		if (filestr != null) {
			Pango.Layout layout = new Pango.Layout(this.PangoContext);
			layout.Width = Pango.Units.FromPixels(width);
			layout.FontDescription = Pango.FontDescription.FromString("Courier 12");
			layout.Wrap = Pango.WrapMode.WordChar;
			layout.SetMarkup(filestr);
			gr.MoveTo(0, 15);
			Pango.CairoHelper.ShowLayout(gr, layout);
		}
	}

	[GLib.ConnectBefore()]
	public override void KeyPress(object o, KeyPressEventArgs args) {
		base.KeyPress(o, args);
		switch(args.Event.Key) {
		case Gdk.Key.Tab:
			Complete();
			QueueDraw();
			break;
		}
	}

	private void Complete() {
		string dir = System.IO.Path.GetDirectoryName(Value);
		string search = System.IO.Path.GetFileName(Value);
		string[] files = Directory.GetFileSystemEntries(dir, search + "*");
		filestr = null;
		if (files.Length == 1 && Directory.Exists(files[0])) {
			Value = files[0] + System.IO.Path.DirectorySeparatorChar;
			Complete();
			return;
		} else if (files.Length > 0) {
			int i;
			filestr = "";

			string common = System.IO.Path.GetFileName(files[0]);

			for (i = 0; i < files.Length; i++) {
				files[i] = System.IO.Path.GetFileName(files[i]);
				common = CommonPart(common, files[i]);
			}

			Value = dir + System.IO.Path.DirectorySeparatorChar + common;
			cursor = Value.Length;

			for (i = 0; i < files.Length; i++) {
				string f = files[i];
				filestr += "<span color=\"#7F7F7F\">" + common + "</span>" + f.Substring(common.Length) + "  ";
			}
		}
	}

	private string CommonPart(string s1, string s2) {
		CharEnumerator i1 = s1.GetEnumerator();
		CharEnumerator i2 = s2.GetEnumerator();
		int c = 0;

		while (i1.MoveNext() && i2.MoveNext()) {
			if (i1.Current != i2.Current) break;
			c++;
		}
		return s1.Substring(0, c);
	}
}