private void NeovimOnRedraw(object sender, NeovimRedrawEventArgs e) { bool shouldInvalidate = false; backBuffer.Bind(); foreach (var method in e.Methods) { switch (method.Method) { case RedrawMethodType.Clear: shouldInvalidate = true; GL.Clear(ClearBufferMask.ColorBufferBit); break; case RedrawMethodType.Resize: var columns = method.Params[0][1].AsInteger(); var rows = method.Params[0][0].AsInteger(); if (rows == this.rows && columns == this.columns) { return; } break; case RedrawMethodType.UpdateForeground: font.Color = ColorFromRgb(method.Params[0][0].AsInteger()); break; case RedrawMethodType.UpdateBackground: bgColor = ColorFromRgb(method.Params[0][0].AsInteger()); GL.ClearColor(bgColor); break; case RedrawMethodType.HighlightSet: foreach (var arg in method.Params) { var dict = arg[0].AsDictionary(); foreach (var entry in dict) { var str = entry.Key.AsString(Encoding.Default); if (str == "foreground") { font.Color = ColorFromRgb(entry.Value.AsInteger()); } else if (str == "background") { } else if (str == "bold") { if (entry.Value.AsBoolean()) { font.FontStyle |= FontStyle.Bold; } else { font.FontStyle &= ~FontStyle.Bold; } } else if (str == "italic") { if (entry.Value.AsBoolean()) { font.FontStyle |= FontStyle.Italic; } else { font.FontStyle &= FontStyle.Italic; } } } } break; case RedrawMethodType.EolClear: shouldInvalidate = true; DrawRectangle(new RectangleF(cursor.X, cursor.Y, this.columns * this.width - cursor.X, this.height), bgColor); break; case RedrawMethodType.SetTitle: Text = method.Params[0][0].AsString(Encoding.Default); break; case RedrawMethodType.Put: shouldInvalidate = true; List <byte> bytes = new List <byte>(); foreach (var arg in method.Params) { bytes.AddRange(arg[0].AsBinary()); } var text = Encoding.Default.GetString(bytes.ToArray()); var tSize = font.Measure(text); DrawRectangle(new RectangleF(cursor.Location, tSize), bgColor); GL.Enable(EnableCap.Blend); font.Print(text, new Vector2(cursor.X, cursor.Y)); GL.Disable(EnableCap.Blend); GL.Color4(Color.White); cursor.X += tSize.Width; if (cursor.X >= this.columns * this.width) // Don't know if this is needed { cursor.X = 0; cursor.Y += this.height; } break; case RedrawMethodType.CursorGoto: shouldInvalidate = true; cursor.Y = method.Params[0][0].AsInteger() * this.height; cursor.X = method.Params[0][1].AsInteger() * this.width; break; case RedrawMethodType.Scroll: // Amount to scroll var count = method.Params[0][0].AsSByte(); if (count == 0) { return; } var srcRect = new RectangleF(); var dstRect = new RectangleF(); var clearRect = new RectangleF(); // Scroll up if (count >= 1) { srcRect = new RectangleF(scrollRegion.X, scrollRegion.Y + this.height, scrollRegion.Width, scrollRegion.Height - this.height); dstRect = new RectangleF(scrollRegion.X, scrollRegion.Y, scrollRegion.Width, scrollRegion.Height - this.height); clearRect = new RectangleF(scrollRegion.X, scrollRegion.Y + scrollRegion.Height - this.height, scrollRegion.Width, this.height + 1); } // Scroll down else if (count <= -1) { srcRect = new RectangleF(scrollRegion.X, scrollRegion.Y, scrollRegion.Width, scrollRegion.Height - this.height); dstRect = new RectangleF(scrollRegion.X, scrollRegion.Y + this.height, scrollRegion.Width, scrollRegion.Height - this.height); clearRect = new RectangleF(scrollRegion.X, scrollRegion.Y, scrollRegion.Width, this.height + 1); } pingPongBuffer.Bind(); backBuffer.Texture.Bind(); DrawTexturedRectangle(srcRect, dstRect); backBuffer.Bind(); pingPongBuffer.Texture.Bind(); DrawTexturedRectangle(dstRect, dstRect); Texture2D.Unbind(); DrawRectangle(clearRect, bgColor); break; case RedrawMethodType.SetScrollRegion: var x = method.Params[0][2].AsInteger() * this.width; var y = method.Params[0][0].AsInteger() * this.height; var width = (method.Params[0][3].AsInteger() + 1) * this.width; var height = (method.Params[0][1].AsInteger() + 1) * this.height; scrollRegion = new RectangleF(x, y, width, height); break; case RedrawMethodType.ModeChange: shouldInvalidate = true; var mode = method.Params[0][0].AsString(Encoding.Default); if (mode == "insert") { cursor.Width = this.width / 4; } else if (mode == "normal") { cursor.Width = this.width; } break; } } FrameBuffer.Unbind(); if (shouldInvalidate) { glControl.Invalidate(); } }
private void OnRedraw(object sender, NeovimRedrawEventArgs e) { foreach (var f in e.Functions) { var list = f.AsList(); string function = list[0].AsString(Encoding.Default); IList <IList <MessagePackObject> > args = new List <IList <MessagePackObject> >(); for (int i = 1; i < list.Count; i++) { args.Add(list[i].AsList()); } switch (function) { case "clear": UpdateTerminal((t) => t.Clear()); break; case "resize": UpdateTerminal((t) => t.Resize(args[0][1].AsInt32(), args[0][0].AsInt32())); break; case "update_fg": break; case "update_bg": break; case "highlight_set": System.Drawing.Color fg = System.Drawing.Color.White; bool bold = false; bool italic = false; foreach (var arg in args) { var dict = arg[0].AsDictionary(); foreach (var entry in dict) { var str = entry.Key.AsString(Encoding.Default); if (str == "foreground") { uint c = entry.Value.AsUInt32(); byte r = (byte)(c >> 16); byte g = (byte)(c >> 8); byte b = (byte)(c >> 0); fg = System.Drawing.Color.FromArgb(r, g, b); } else if (str == "bold") { bold = entry.Value.AsBoolean(); } else if (str == "italic") { italic = entry.Value.AsBoolean(); } } } UpdateTerminal((t) => t.Highlight(fg, bold, italic)); break; case "eol_clear": UpdateTerminal((t) => t.ClearToEnd()); break; case "set_title": this.Title = args[0][0].AsString(Encoding.Default); break; case "put": List <byte> bytes = new List <byte>(); foreach (var arg in args) { bytes.AddRange(arg[0].AsBinary()); } UpdateTerminal((t) => t.PutText(Encoding.Default.GetString(bytes.ToArray()))); break; case "cursor_goto": UpdateTerminal((t) => t.MoveCaret(args[0][0].AsInt32(), args[0][1].AsInt32())); break; case "scroll": UpdateTerminal((t) => t.Scroll(args[0][0].AsSByte())); break; case "set_scroll_region": break; case "normal_mode": UpdateTerminal((t) => t.Caret.Width = t.CellWidth); break; case "insert_mode": UpdateTerminal((t) => t.Caret.Width = 3); break; case "busy_start": break; case "busy_stop": break; case "mouse_on": break; case "mouse_off": break; } } UpdateTerminal((t) => t.SwapBuffers()); }