commit:1265cb3fd18d7f0144a1634d2f2a87194116455c
author:Chip Black
committer:Chip Black
date:Mon Sep 29 02:34:30 2008 -0500
parents:a6e01ee9b13ea013237ddbe8f7a8aac464eb9020
Added text scrolling
diff --git a/TextDisplay.cs b/TextDisplay.cs
line changes: +24/-36
index 0abb9e9..9389f00
--- a/TextDisplay.cs
+++ b/TextDisplay.cs
@@ -5,10 +5,18 @@ using Gtk;
 
 public class TextDisplay : DrawingArea, IKeyPress {
 	private TextDocument doc = null;
-	private FontDescription font;
+	private Font font;
+	// FIXME: Proportional fonts?
+	private float fontwidth;
+	private float fontheight;
 
 	public TextDisplay() {
-		font = Pango.FontDescription.FromString("Courier 12");
+		FontDescription fd = Pango.FontDescription.FromString("Courier 12");
+		font = this.PangoContext.LoadFont(fd);
+		FontMetrics fm = font.GetMetrics(null);
+		fontheight = Pango.Units.ToPixels(fm.Ascent + fm.Descent);
+		fontwidth = fontheight * 0.5333f;
+		Console.WriteLine("Using {0} {1}pt ({2}x{3}px)", fd.Family, fd.Size, fontwidth, fontheight);
 		ModifyBg(StateType.Normal, new Gdk.Color(0xFF, 0xFF, 0xFF));
 	}
 
@@ -20,25 +28,18 @@ public class TextDisplay : DrawingArea, IKeyPress {
 		if (doc == null) return;
 
 		Pango.Layout layout = new Pango.Layout(this.PangoContext);
-		layout.Width = Pango.Units.FromPixels(width);
-		layout.FontDescription = font;
+		layout.Width = 0x7FFFFFFF; //Pango.Units.FromPixels(width);
+		layout.FontDescription = font.Describe();
 
 		//gr.Operator = Operator.Atop;
 		gr.SetSourceRGB(0,0,0);
-		int h = Pango.Units.ToPixels(layout.FontDescription.Size) + 1;
-		int y = 0;
-		int line = 0;
-		while (line < doc.Lines.Count && y < height) {
-			layout.SetText((String)doc.Lines[line]);
-			gr.MoveTo(0, y);
-			Pango.CairoHelper.ShowLayout(gr, layout);
-			y += h;
-			line++;
-		}
+		layout.SetText(doc.GetTextWindow());
+		gr.MoveTo(0, 0);
+		Pango.CairoHelper.ShowLayout(gr, layout);
 
-		//gr.Operator = Operator.Xor;
+		gr.Operator = Operator.Xor;
 		gr.NewPath();
-		gr.Rectangle(new Cairo.Rectangle(doc.cursor.x*8, doc.cursor.y*h, 8, h));
+		gr.Rectangle(new Cairo.Rectangle((doc.cursor.x - doc.textorigin.x)*fontwidth, (doc.cursor.y - doc.textorigin.y)*fontheight, fontwidth, fontheight));
 		gr.Fill();
         }
 
@@ -70,6 +71,12 @@ public class TextDisplay : DrawingArea, IKeyPress {
                 return true;
         }
 
+	protected override void OnSizeAllocated(Gdk.Rectangle r) {
+		base.OnSizeAllocated(r);
+		if (doc != null)
+			doc.SetPageSize((int)(r.Width / fontwidth) - 1, (int)(r.Height / fontheight) - 1);
+	}
+
 	public void Update() {
 		QueueDraw();
 	}
@@ -78,25 +85,6 @@ public class TextDisplay : DrawingArea, IKeyPress {
         [GLib.ConnectBefore ()]
         public void KeyPress(object o, KeyPressEventArgs args) {
 		if (doc == null) return;
-
-                if ((args.Event.State & Gdk.ModifierType.ControlMask) != 0) {
-                } else if ((args.Event.State & Gdk.ModifierType.Mod1Mask) != 0) {
-                } else {
-                        switch(args.Event.Key) {
-                        case Gdk.Key.Up:
-                        case Gdk.Key.Down:
-                        case Gdk.Key.Left:
-                        case Gdk.Key.Right:
-                        case Gdk.Key.Page_Up:
-                        case Gdk.Key.Page_Down:
-                        case Gdk.Key.Home:
-                        case Gdk.Key.End:
-                                doc.MoveCursor(args.Event.Key);
-                                break;
-                        default:
-                                doc.AddChar((int)args.Event.KeyValue);
-                                break;
-                        }
-                }
+		doc.KeyPress(o, args);
 	}
 }

diff --git a/TextDocument.cs b/TextDocument.cs
line changes: +86/-34
index e05e992..f554af7
--- a/TextDocument.cs
+++ b/TextDocument.cs
@@ -74,12 +74,16 @@ public class TextArray {
 		if (y >= lines.Count) return;
 
 		string s = (string)lines[y];
-		if (x >= s.Length) return;
-
-		if (s.Length == 0 && x == 0) {
+		if (x >= s.Length) {
+			if (y == lines.Count - 1) return;
+			if (x > s.Length)
+				s = s.PadRight(x);
+			lines[y] = s + (String)lines[y+1];
+			lines.RemoveAt(y+1);
+		} else if (s.Length == 0 && x == 0) {
 			lines.RemoveAt(y);
 		} else {
-			s.Remove(x, 1);
+			lines[y] = s.Remove(x, 1);
 		}
 	}
 
@@ -118,15 +122,11 @@ public class TextArray {
 	}
 }
 
-public class TextDocument {
+public class TextDocument : IKeyPress {
 	private TextArray text;
 	public Cursor cursor;
-
-	public ArrayList Lines {
-		get {
-			return text.Lines;
-		}
-	}
+	public Cursor textorigin;
+	private int pagewidth, pageheight;
 
 	public TextDocument() {
 		text = new TextArray();
@@ -136,6 +136,29 @@ public class TextDocument {
 		text = new TextArray(filename);
 	}
 
+	public string GetTextWindow() {
+		string s = "";
+
+		for (int i = textorigin.y; textorigin.y + i < text.Lines.Count && i < pageheight; i++) {
+			String l = (String)text.Lines[i];
+			s += l.Substring(textorigin.x) + "\n";
+		}
+		return s;
+	}
+
+	private void FixTextWindow() {
+		if (cursor.x < textorigin.x) textorigin.x = cursor.x;
+		if (cursor.y < textorigin.y) textorigin.y = cursor.y;
+		if (cursor.x > textorigin.x + pagewidth) textorigin.x = cursor.x - pagewidth;
+		if (cursor.y > textorigin.y + pageheight) textorigin.y = cursor.y - pageheight;
+	}
+
+	public void SetPageSize(int w, int h) {
+		pagewidth = w;
+		pageheight = h;
+		FixTextWindow();
+	}
+
 	public void MoveCursor(Gdk.Key k) {
 		switch(k) {
 		case Gdk.Key.Up:
@@ -156,35 +179,64 @@ public class TextDocument {
 		case Gdk.Key.Home:
 			cursor.x = 0;
 			break;
+		case Gdk.Key.Page_Up:
+			cursor.y -= pageheight;
+			break;
+		case Gdk.Key.Page_Down:
+			cursor.y += pageheight;
+			break;
 		}
+		FixTextWindow();
 	}
 
+	[GLib.ConnectBefore ()]
+	public void KeyPress(object o, Gtk.KeyPressEventArgs args) {
+		if ((args.Event.State & Gdk.ModifierType.ControlMask) != 0) {
+		} else if ((args.Event.State & Gdk.ModifierType.Mod1Mask) != 0) {
+		} else {
+			switch(args.Event.Key) {
+			case Gdk.Key.Up:
+			case Gdk.Key.Down:
+			case Gdk.Key.Left:
+			case Gdk.Key.Right:
+			case Gdk.Key.Page_Up:
+			case Gdk.Key.Page_Down:
+			case Gdk.Key.Home:
+			case Gdk.Key.End:
+				MoveCursor(args.Event.Key);
+				break;
+			case Gdk.Key.Delete:
+				text.Delete(cursor.x, cursor.y);
+				break;
+			case Gdk.Key.BackSpace:
+				int l = 0;
+				if (cursor.y > 0) l = text.LineLength(cursor.y-1);
+				text.Backspace(cursor.x, cursor.y);
+				if (cursor.x == 0) {
+					cursor.y--;
+					if (cursor.y >= text.Lines.Count) return;
+					cursor.x = l;
+				} else {
+					cursor.x--;
+				}
+				break;
+			case Gdk.Key.Return:
+				text.Newline(cursor.x, cursor.y);
+				cursor.x = 0;
+				cursor.y++;
+				break;
+			default:
+				AddChar((int)args.Event.KeyValue);
+				break;
+			}
+		}
+	}
+	
 	public void AddChar(int c) {
 		c = c & 0xFF;
 		if (c > 128) return;
 
-		switch(c) {
-		case 8:
-			int l = 0;
-			if (cursor.y > 0) l = text.LineLength(cursor.y-1);
-			text.Backspace(cursor.x, cursor.y);
-			if (cursor.x == 0) {
-				cursor.y--;
-				if (cursor.y >= text.Lines.Count) return;
-				cursor.x = l;
-			} else {
-				cursor.x--;
-			}
-			break;
-		case 13:
-			text.Newline(cursor.x, cursor.y);
-			cursor.x = 0;
-			cursor.y++;
-			break;
-		default:
-			text.Insert(cursor.x, cursor.y, (char)c);
-			cursor.x++;
-			break;
-		}
+		text.Insert(cursor.x, cursor.y, (char)c);
+		cursor.x++;
 	}
 }