                      cm
                      (group-by :y characters))))
     #_(log/info "character-map" (str @character-map)))
+  (set-fg! [_ x y fg]
+    (let [fg-color  (Color. (long (fg 0)) (long (fg 1)) (long (fg 2)))]
+      (alter character-map
+             (fn [cm] (assoc-in cm [y x :fg-color] fg-color)))))
+  (set-bg! [_ x y bg]
+    (let [bg-color  (Color. (long (bg 0)) (long (bg 1)) (long (bg 2)))]
+      (alter character-map
+             (fn [cm] (assoc-in cm [y x :bg-color] bg-color)))))
   (get-key-chan [_]
     key-chan)
+  (apply-font! [_ windows-font else-font size smooth]
+    (reset! normal-font
+            (if (= (LWJGLUtil/getPlatform) LWJGLUtil/PLATFORM_WINDOWS)
+              (make-font windows-font Font/PLAIN size)
+              (make-font else-font Font/PLAIN size)))
+    (reset! antialias smooth))
   (set-cursor! [_ xy]
     (reset! cursor-xy xy))
-  (refresh! [_]
-    (GL11/glClearColor 0.0 0.0 1.0 1.0)
-    (let [{{:keys [vao-id vertices-vbo-id vertices-count texture-coords-vbo-id]} :buffers
-           {:keys [font-texture glyph-texture fg-texture bg-texture]} :textures
-           program-id :program-id
-           {:keys [u-MVMatrix u-PMatrix u-font u-glyphs u-fg u-bg font-size term-dim font-tex-dim
-            font-texture-width font-texture-height glyph-tex-dim glyph-texture-width glyph-texture-height ]} :uniforms
-           {:keys [^ByteBuffer glyph-image-data
-                   ^ByteBuffer fg-image-data
-                   ^ByteBuffer bg-image-data]} :data
-           :keys [p-matrix-buffer mv-matrix-buffer]} gl
-          glyph-image-data glyph-image-data
-          fg-image-data fg-image-data
-          bg-image-data bg-image-data]
-
-      (GL20/glUseProgram program-id)
-      (GL20/glUniformMatrix4 u-PMatrix false p-matrix-buffer)
-      (GL20/glUniformMatrix4 u-MVMatrix false mv-matrix-buffer)
-      ; Setup vertex buffer
-      (GL15/glBindBuffer GL15/GL_ARRAY_BUFFER, vertices-vbo-id)
-      (except-gl-errors (str "vbo bind - glBindBuffer" vertices-vbo-id))
-      (GL20/glEnableVertexAttribArray 0);pos-vertex-attribute)
-      (except-gl-errors "vbo bind - glEnableVertexAttribArray")
-      (GL20/glVertexAttribPointer 0 3 GL11/GL_FLOAT false 0 0)
-      (except-gl-errors "vbo bind - glVertexAttribPointer")
-      ; Setup uv buffer
-      (GL15/glBindBuffer GL15/GL_ARRAY_BUFFER, texture-coords-vbo-id)
-      (GL20/glEnableVertexAttribArray 1);texture-coords-vertex-attribute)
-      (GL20/glVertexAttribPointer 1 2 GL11/GL_FLOAT false 0 0)
-      (except-gl-errors "texture coords bind")
-      ; Setup font texture
-      (GL13/glActiveTexture GL13/GL_TEXTURE0)
-      (GL11/glBindTexture GL11/GL_TEXTURE_2D font-texture)
-      (GL20/glUniform1i u-font, 0)
-      (except-gl-errors "font texture bind")
-      ; Setup uniforms for glyph, fg, bg, textures
-      (GL20/glUniform1i u-glyphs 1)
-      (GL20/glUniform1i u-fg 2)
-      (GL20/glUniform1i u-bg 3)
-      (except-gl-errors "uniformli bind")
-      (GL20/glUniform2f font-size, char-width char-height)
-      (GL20/glUniform2f term-dim columns rows)
-      (GL20/glUniform2f font-tex-dim font-texture-width font-texture-height)
-      (GL20/glUniform2f glyph-tex-dim glyph-texture-width glyph-texture-height)
-      (except-gl-errors "uniform2f bind")
-      (GL11/glDisable GL13/GL_SAMPLE_COVERAGE)
-      (GL11/glDisable GL11/GL_BLEND)
-      (GL11/glDisable GL11/GL_CULL_FACE)
-      (GL11/glDisable GL11/GL_STENCIL_TEST)
-      (GL11/glEnable GL11/GL_DITHER)
-      (GL11/glDisable GL11/GL_SCISSOR_TEST)
-      (GL11/glDisable GL11/GL_DEPTH_TEST)
-      (GL11/glDisable GL11/GL_POLYGON_OFFSET_FILL)
-      (GL11/glDisable GL13/GL_SAMPLE_ALPHA_TO_COVERAGE)
-      (except-gl-errors "gl(en/dis)able")
-      #_#_glyph-data       (.-data glyph-image-data)
-      #_#_fg-data          (.-data fg-image-data)
-      #_#_bg-data          (.-data bg-image-data)
-      ;; Update glyph texture in memory
-      (.clear glyph-image-data)
-      (.clear fg-image-data)
-      (.clear bg-image-data)
-      (doseq [row (range rows)
-              col (range columns)]
-        (let [c         (get-in @character-map [row col])
-              chr       (get c :character)
-              highlight (= @cursor-xy [col row])
-              [fg-r fg-g fg-b] (if highlight
-                                 (get c :bg-color)
-                                 (get c :fg-color))
-              [bg-r bg-g bg-b] (if highlight
-                                 (get c :fg-color)
-                                 (get c :bg-color))
-              ;s         (str (get c :character))
-              style     (get c :style)
-              i         (* 4 (+ (* texture-columns row) col))
-              [x y]     (get character->col-row [chr (contains? style :underline)])]
-          ;(log/info "Drawing at col row" col row "character from atlas col row" x y c "(index=" i ")")
-          (when (zero? col)
-            (.position glyph-image-data i)
-            (.position fg-image-data i)
-            (.position bg-image-data i))
-          (.put glyph-image-data (unchecked-byte x))
-          (.put glyph-image-data (unchecked-byte y))
-          (.put glyph-image-data (unchecked-byte 0))
-          (.put glyph-image-data (unchecked-byte 0))
-          (.put fg-image-data    (unchecked-byte fg-r))
-          (.put fg-image-data    (unchecked-byte fg-g))
-          (.put fg-image-data    (unchecked-byte fg-b))
-          (.put fg-image-data    (unchecked-byte 0))
-          (.put bg-image-data    (unchecked-byte bg-r))
-          (.put bg-image-data    (unchecked-byte bg-g))
-          (.put bg-image-data    (unchecked-byte bg-b))
-          (.put bg-image-data    (unchecked-byte 0))))
-      (.position glyph-image-data (.limit glyph-image-data))
-      (.position fg-image-data (.limit fg-image-data))
-      (.position bg-image-data (.limit bg-image-data))
-      (.flip glyph-image-data)
-      (.flip fg-image-data)
-      (.flip bg-image-data)
-      ; Send updated glyph texture to gl
-      (GL13/glActiveTexture GL13/GL_TEXTURE1)
-      (GL11/glBindTexture GL11/GL_TEXTURE_2D glyph-texture)
-      (GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL11/GL_RGBA texture-columns texture-rows 0 GL11/GL_RGBA GL11/GL_UNSIGNED_BYTE glyph-image-data)
-      (except-gl-errors "glyph texture data")
-      ; Send updated fg texture to gl
-      (GL13/glActiveTexture GL13/GL_TEXTURE2)
-      (GL11/glBindTexture GL11/GL_TEXTURE_2D fg-texture)
-      (GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL11/GL_RGBA texture-columns texture-rows 0 GL11/GL_RGBA GL11/GL_UNSIGNED_BYTE fg-image-data)
-      (except-gl-errors "fg color texture data")
-      ; Send updated bg texture to gl
-      (GL13/glActiveTexture GL13/GL_TEXTURE3)
-      (GL11/glBindTexture GL11/GL_TEXTURE_2D bg-texture)
-      (GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL11/GL_RGBA texture-columns texture-rows 0 GL11/GL_RGBA GL11/GL_UNSIGNED_BYTE bg-image-data)
-      (GL11/glDrawArrays GL11/GL_TRIANGLE_STRIP 0 vertices-count)
-      (except-gl-errors "bg color texture data")
-      (except-gl-errors "end of refresh")
-      ;(Display/sync 60)
-      (Display/update)))
+  (refresh! [this]
+    (locking this
+      (Display/makeCurrent)
+      (GL11/glClearColor 0.0 0.0 1.0 1.0)
+      (GL11/glClear (bit-or GL11/GL_COLOR_BUFFER_BIT GL11/GL_DEPTH_BUFFER_BIT))
+      (let [{{:keys [vertices-vbo-id vertices-count texture-coords-vbo-id]} :buffers
+             {:keys [font-texture glyph-texture fg-texture bg-texture]} :textures
+             program-id :program-id
+             {:keys [u-MVMatrix u-PMatrix u-font u-glyphs u-fg u-bg font-size term-dim font-tex-dim
+              font-texture-width font-texture-height glyph-tex-dim glyph-texture-width glyph-texture-height]} :uniforms
+             {:keys [^ByteBuffer glyph-image-data
+                     ^ByteBuffer fg-image-data
+                     ^ByteBuffer bg-image-data]} :data
+             :keys [p-matrix-buffer mv-matrix-buffer char-width char-height]} gl
+            glyph-image-data glyph-image-data
+            fg-image-data fg-image-data
+            bg-image-data bg-image-data]
+
+        (GL20/glUseProgram program-id)
+        (GL20/glUniformMatrix4 u-PMatrix false p-matrix-buffer)
+        (GL20/glUniformMatrix4 u-MVMatrix false mv-matrix-buffer)
+        ; Setup vertex buffer
+        (GL15/glBindBuffer GL15/GL_ARRAY_BUFFER, vertices-vbo-id)
+        (except-gl-errors (str "vbo bind - glBindBuffer" vertices-vbo-id))
+        (GL20/glEnableVertexAttribArray 0);pos-vertex-attribute)
+        (except-gl-errors "vbo bind - glEnableVertexAttribArray")
+        (GL20/glVertexAttribPointer 0 3 GL11/GL_FLOAT false 0 0)
+        (except-gl-errors "vbo bind - glVertexAttribPointer")
+        ; Setup uv buffer
+        (GL15/glBindBuffer GL15/GL_ARRAY_BUFFER, texture-coords-vbo-id)
+        (GL20/glEnableVertexAttribArray 1);texture-coords-vertex-attribute)
+        (GL20/glVertexAttribPointer 1 2 GL11/GL_FLOAT false 0 0)
+        (except-gl-errors "texture coords bind")
+        ; Setup font texture
+        (GL13/glActiveTexture GL13/GL_TEXTURE0)
+        (GL11/glBindTexture GL11/GL_TEXTURE_2D font-texture)
+        (GL20/glUniform1i u-font, 0)
+        (except-gl-errors "font texture bind")
+        ; Setup uniforms for glyph, fg, bg, textures
+        (GL20/glUniform1i u-glyphs 1)
+        (GL20/glUniform1i u-fg 2)
+        (GL20/glUniform1i u-bg 3)
+        (except-gl-errors "uniformli bind")
+        (GL20/glUniform2f font-size, char-width char-height)
+        (GL20/glUniform2f term-dim columns rows)
+        (GL20/glUniform2f font-tex-dim font-texture-width font-texture-height)
+        (GL20/glUniform2f glyph-tex-dim glyph-texture-width glyph-texture-height)
+        (except-gl-errors "uniform2f bind")
+        (except-gl-errors "gl(en/dis)able")
+        #_#_glyph-data       (.-data glyph-image-data)
+        #_#_fg-data          (.-data fg-image-data)
+        #_#_bg-data          (.-data bg-image-data)
+        ;; Update glyph texture in memory
+        (.clear glyph-image-data)
+        (.clear fg-image-data)
+        (.clear bg-image-data)
+        (doseq [[row line] (map-indexed vector @character-map)
+                [col c] (map-indexed vector line)]
+          (let [;c         (get-in @character-map [row col])
+                chr       (get c :character)
+                highlight (= @cursor-xy [col row])
+                [fg-r fg-g fg-b] (if highlight
+                                   (get c :bg-color)
+                                   (get c :fg-color))
+                [bg-r bg-g bg-b] (if highlight
+                                   (get c :fg-color)
+                                   (get c :bg-color))
+                ;s         (str (get c :character))
+                style     (get c :style)
+                i         (* 4 (+ (* texture-columns row) col))
+                [x y]     (get character->col-row [chr (contains? style :underline)])]
+            ;(log/info "Drawing at col row" col row "character from atlas col row" x y c "(index=" i ")")
+            (when (zero? col)
+              (.position glyph-image-data i)
+              (.position fg-image-data i)
+              (.position bg-image-data i))
+            (.put glyph-image-data (unchecked-byte x))
+            (.put glyph-image-data (unchecked-byte y))
+            (.put glyph-image-data (unchecked-byte 0))
+            (.put glyph-image-data (unchecked-byte 0))
+            (.put fg-image-data    (unchecked-byte fg-r))
+            (.put fg-image-data    (unchecked-byte fg-g))
+            (.put fg-image-data    (unchecked-byte fg-b))
+            (.put fg-image-data    (unchecked-byte 0))
+            (.put bg-image-data    (unchecked-byte bg-r))
+            (.put bg-image-data    (unchecked-byte bg-g))
+            (.put bg-image-data    (unchecked-byte bg-b))
+            (.put bg-image-data    (unchecked-byte 0))))
+        (.position glyph-image-data (.limit glyph-image-data))
+        (.position fg-image-data (.limit fg-image-data))
+        (.position bg-image-data (.limit bg-image-data))
+        (.flip glyph-image-data)
+        (.flip fg-image-data)
+        (.flip bg-image-data)
+        ; Send updated glyph texture to gl
+        (GL13/glActiveTexture GL13/GL_TEXTURE1)
+        (GL11/glBindTexture GL11/GL_TEXTURE_2D glyph-texture)
+        (GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL11/GL_RGBA texture-columns texture-rows 0 GL11/GL_RGBA GL11/GL_UNSIGNED_BYTE glyph-image-data)
+        (except-gl-errors "glyph texture data")
+        ; Send updated fg texture to gl
+        (GL13/glActiveTexture GL13/GL_TEXTURE2)
+        (GL11/glBindTexture GL11/GL_TEXTURE_2D fg-texture)
+        (GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL11/GL_RGBA texture-columns texture-rows 0 GL11/GL_RGBA GL11/GL_UNSIGNED_BYTE fg-image-data)
+        (except-gl-errors "fg color texture data")
+        ; Send updated bg texture to gl
+        (GL13/glActiveTexture GL13/GL_TEXTURE3)
+        (GL11/glBindTexture GL11/GL_TEXTURE_2D bg-texture)
+        (GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL11/GL_RGBA texture-columns texture-rows 0 GL11/GL_RGBA GL11/GL_UNSIGNED_BYTE bg-image-data)
+        (GL11/glDrawArrays GL11/GL_TRIANGLE_STRIP 0 vertices-count)
+        (except-gl-errors "bg color texture data")
+        (except-gl-errors "end of refresh")
+        ;(Display/sync 60)
+        (Display/update)
+        (Display/releaseContext))))
   (clear! [_]
-    (reset! character-map character-map-cleared)))
+    (ref-set character-map character-map-cleared))
+  (set-fx-fg! [_ x y fg]
+    (let [fg-color  (when fg (Color. (long (fg 0)) (long (fg 1)) (long (fg 2))))]
+      (alter character-map
+             (fn [cm] (assoc-in cm [y x :fx-fg-color] fg-color)))))
+  (set-fx-bg! [_ x y bg]
+    (let [bg-color  (when bg (Color. (long (bg 0)) (long (bg 1)) (long (bg 2))))]
+      (alter character-map
+             (fn [cm] (assoc-in cm [y x :fx-bg-color] bg-color)))))
+  (set-fx-char! [_ x y c]
+    (alter character-map
+           (fn [cm] (assoc-in cm [y x :fx-character] c))))
+  (clear-fx! [_]
+    (alter character-map
+           (fn [cm]
+             (mapv (fn [line]
+                     (mapv (fn [c]
+                             (assoc c :fx-fg-color nil
+                                      :fx-bg-color nil
+                                      :fx-character nil))
+                           line))
+                   cm)))))
 
 (defn make-terminal
   ([]
-    (make-terminal 80 24))
-  ([columns rows]
-   (make-terminal columns rows nil))
-  ([columns rows  on-key-fn]
-    (make-terminal columns rows on-key-fn "Courier New" "Monospaced" 14))
-  ([columns rows on-key-fn windows-font else-font font-size]
-    (let [title            "Robinson"
-          is-windows       (>= (.. System (getProperty "os.name" "") (toLowerCase) (indexOf "win")) 0)
+    (make-terminal "" 80 24))
+  ([title columns rows]
+   (make-terminal title columns rows [255 255 255] [0 0 0]))
+  ([title columns rows default-fg-color default-bg-color]
+   (make-terminal title columns rows default-fg-color default-bg-color nil))
+  ([title columns rows default-fg-color default-bg-color on-key-fn]
+    (make-terminal title columns rows default-fg-color default-bg-color on-key-fn "Courier New" "Monospaced" 16 true))
+  ([title columns rows default-fg-color  default-bg-color on-key-fn windows-font else-font font-size antialias]
+    (let [is-windows       (>= (.. System (getProperty "os.name" "") (toLowerCase) (indexOf "win")) 0)
           normal-font      (atom (if is-windows
                                    (make-font windows-font Font/PLAIN font-size)
                                    (make-font else-font Font/PLAIN font-size)))
           _                    (log/info "Using font" normal-font)
+
+          antialias        (atom antialias)
           default-bg-color     [(long 0) (long 0) (long 0)]
           ;; create texture atlas
-          character-map-cleared (vec (repeat rows (vec (repeat columns (make-terminal-character \space default-bg-color default-bg-color #{})))))
-          character-map         (atom character-map-cleared)
+          character-map-cleared (vec (repeat rows (vec (repeat columns (make-terminal-character \space default-fg-color default-bg-color #{})))))
+          character-map         (ref character-map-cleared)
           cursor-xy             (atom nil)
 
           key-chan         (async/chan)
-          on-key-fn        (or on-key-fn
+          #_#_on-key-fn        (or on-key-fn
                                (fn default-on-key-fn [k]
                                  (async/put! key-chan k)))
-          keyListener      (reify KeyListener
+          #_#_keyListener      (reify KeyListener
                              (keyPressed [_ e]
                                ;(println "keyPressed keyCode" (.getKeyCode e) "escape" KeyEvent/VK_ESCAPE "escape?" (= (.getKeyCode e) KeyEvent/VK_ESCAPE))
                                (convert-key-code e on-key-fn))

  ;; characters is a list of {:c \character :x col :y row :fg [r g b] :bg [r g b]}
  (put-chars! [_ characters]
    #_(log/info "characters" (str characters))
    (swap! character-map
           (fn [cm]
             (reduce (fn [cm [row row-characters]]
                       (if (< -1 row rows)

                  (when (Keyboard/getEventKeyState)
                    (async/>! key-chan (Keyboard/getEventCharacter))))
                (recur)))
      ;; Access to terminal will be multi threaded. Release context so that other threads can access it
      (Display/releaseContext)
      ;; Create and return terminal
      (OpenGlTerminal. columns
                       rows
                       next-pow-2-columns
                       next-pow-2-rows
                       normal-font
                       antialias
                       character-map-cleared
                       character-map
                       cursor-xy
                       {:p-matrix-buffer (ortho-matrix-buffer screen-width screen-height)
                        :mv-matrix-buffer (position-matrix-buffer [(- (/ screen-width 2)) (- (/ screen-height 2)) -1.0 0.0])
                        :char-width char-width
                        :char-height char-height
                        :buffers {:vao-id vao-id
                                  :vertices-vbo-id vertices-vbo-id
                                  :vertices-count vertices-count
