diff --git a/basis/ui/freetype/freetype.factor b/basis/ui/freetype/freetype.factor
index 0f36f3dcba..89ce36af63 100644
--- a/basis/ui/freetype/freetype.factor
+++ b/basis/ui/freetype/freetype.factor
@@ -108,7 +108,9 @@ SYMBOL: dpi
         init-font ;
 
 M: freetype-renderer open-font ( font -- open-font )
-    freetype drop open-fonts get [ <font> ] cache ;
+    dup font? [
+        freetype drop open-fonts get [ <font> ] cache
+    ] unless ;
 
 : load-glyph ( font char -- glyph )
     [ handle>> dup ] dip 0 FT_Load_Char
@@ -215,7 +217,8 @@ M: freetype-renderer draw-string ( font string loc -- )
 : run-char-widths ( open-font string -- widths )
     char-widths [ scan-sums ] [ 2 v/n ] bi v+ ;
 
-M: freetype-renderer x>offset ( x open-font string -- n )
+M: freetype-renderer x>offset ( x font string -- n )
+    [ open-font ] dip
     [ run-char-widths [ <= ] with find drop ] keep swap
     [ ] [ length ] ?if ;
 
diff --git a/basis/ui/gadgets/editors/editors.factor b/basis/ui/gadgets/editors/editors.factor
index 5624c654fa..4c035c7901 100755
--- a/basis/ui/gadgets/editors/editors.factor
+++ b/basis/ui/gadgets/editors/editors.factor
@@ -101,10 +101,8 @@ M: editor ungraft*
 
 : editor-line ( n editor -- str ) control-value nth ;
 
-: editor-font* ( editor -- font ) font>> open-font ;
-
 : line-height ( editor -- n )
-    editor-font* "" string-height ;
+    font>> "" text-height ;
 
 : y>line ( y editor -- line# )
     line-height /i ;
@@ -116,7 +114,7 @@ M: editor ungraft*
         [| n |
             n
             point first
-            editor editor-font*
+            editor font>>
             n editor editor-line
             x>offset 2array
         ]
@@ -129,17 +127,13 @@ M: editor ungraft*
     [ clicked-loc ] dip set-model ;
 
 : focus-editor ( editor -- )
-    dup start-blinking
-    t >>focused?
-    relayout-1 ;
+    [ start-blinking ] [ t >>focused? relayout-1 ] bi ;
 
 : unfocus-editor ( editor -- )
-    dup stop-blinking
-    f >>focused?
-    relayout-1 ;
+    [ stop-blinking ] [ f >>focused? relayout-1 ] bi ;
 
 : offset>x ( col# line# editor -- x )
-    [ editor-line ] keep editor-font* spin head-slice string-width ;
+    [ editor-line ] keep font>> spin head text-width ;
 
 : loc>x ( loc editor -- x ) [ first2 swap ] dip offset>x ;
 
@@ -248,7 +242,7 @@ M: editor draw-gadget*
     [ draw-selection draw-lines draw-caret ] with-editor ;
 
 M: editor pref-dim*
-    dup editor-font* swap control-value text-dim ;
+    [ font>> ] [ control-value ] bi text-dim ;
 
 : contents-changed ( model editor -- )
     swap
@@ -563,7 +557,7 @@ TUPLE: field < wrapper editor min-width max-width ;
     [ <editor> dup <field-border> ] dip new-wrapper swap >>editor ; inline
 
 : column-width ( editor n -- width )
-    [ editor>> editor-font* ] dip CHAR: \s <string> string-width ;
+    [ editor>> font>> ] [ CHAR: \s <string> ] bi* text-width ;
 
 M: field pref-dim*
     [ call-next-method ]
diff --git a/basis/ui/gadgets/labels/labels.factor b/basis/ui/gadgets/labels/labels.factor
index eff3c6f7bb..30bd3438a7 100644
--- a/basis/ui/gadgets/labels/labels.factor
+++ b/basis/ui/gadgets/labels/labels.factor
@@ -27,7 +27,7 @@ TUPLE: label < gadget text font color ;
     label new-label ;
 
 M: label pref-dim*
-    [ font>> open-font ] [ text>> ] bi text-dim ;
+    [ font>> ] [ text>> ] bi text-dim ;
 
 M: label draw-gadget*
     [ color>> gl-color ]
diff --git a/basis/ui/gadgets/tables/tables.factor b/basis/ui/gadgets/tables/tables.factor
index 2d1700bb0b..def57b734a 100644
--- a/basis/ui/gadgets/tables/tables.factor
+++ b/basis/ui/gadgets/tables/tables.factor
@@ -41,7 +41,7 @@ focused? ;
 <PRIVATE
 
 : line-height ( table -- n )
-    font>> open-font "" string-height ;
+    font>> "" text-height ;
 
 CONSTANT: table-gap 6
 
@@ -51,12 +51,12 @@ CONSTANT: table-gap 6
 : (compute-column-widths) ( font rows -- total widths )
     [ drop 0 { } ] [
         tuck [ first length 0 <repetition> ] 2dip
-        [ [ string-width ] with map vmax ] with each
+        [ [ text-width ] with map vmax ] with each
         [ [ sum ] [ length 1 [-] table-gap * ] bi + ] keep
     ] if-empty ;
 
 : compute-column-widths ( table -- total-width column-widths )
-    [ font>> open-font ] [ table-rows ] bi (compute-column-widths) ;
+    [ font>> ] [ table-rows ] bi (compute-column-widths) ;
 
 : update-cached-widths ( table -- )
     dup compute-column-widths
@@ -136,7 +136,7 @@ M: table layout*
     [ rect-extent nip ] visible-row 1+ ;
 
 : column-loc ( font column width align -- loc )
-    [ [ [ open-font ] dip string-width ] dip swap - ] dip
+    [ [ text-width ] dip swap - ] dip
     * 0 2array ;
 
 : draw-column ( font column width align -- )
@@ -185,7 +185,7 @@ M: table draw-gadget*
 
 M: table pref-dim*
     [ compute-column-widths drop ] keep
-    [ font>> open-font "" string-height ]
+    [ font>> "" text-height ]
     [ control-value length ]
     bi * 2array ;
 
diff --git a/basis/ui/render/render-docs.factor b/basis/ui/render/render-docs.factor
index 7f88a904ec..1c3af46033 100644
--- a/basis/ui/render/render-docs.factor
+++ b/basis/ui/render/render-docs.factor
@@ -1,6 +1,6 @@
 USING: ui.gadgets ui.gestures help.markup help.syntax
 kernel classes strings opengl opengl.gl models
-math.geometry.rect ;
+math.geometry.rect math ;
 IN: ui.render
 
 HELP: gadget
@@ -67,10 +67,24 @@ HELP: open-font
 
 HELP: string-width
 { $values { "open-font" "a value output by " { $link open-font } } { "string" string } { "w" "a positive integer" } }
-{ $description "Outputs the width of a string." } ;
+{ $description "Outputs the width of a string." }
+{ $notes "This is a low-level word; use " { $link text-width } " instead." } ;
+
+HELP: text-width
+{ $values { "font" "a font specifier" } { "text" "a string or sequence of strings" } { "w" "a positive integer" } }
+{ $description "Outputs the width of a piece of text." } ;
+
+HELP: string-height
+{ $values { "open-font" "a value output by " { $link open-font } } { "string" string } { "w" "a positive integer" } }
+{ $description "Outputs the height of a string." }
+{ $notes "This is a low-level word; use " { $link text-height } " instead." } ;
+
+HELP: text-height
+{ $values { "font" "a font specifier" } { "text" "a string or sequence of strings" } { "w" "a positive integer" } }
+{ $description "Outputs the height of a piece of text." } ;
 
 HELP: text-dim
-{ $values { "open-font" "a value output by " { $link open-font } } { "text" "a string or an array of strings" } { "dim" "a pair of integers" } }
+{ $values { "font" "a font specifier" } { "text" "a string or sequence of strings" } { "dim" "a pair of integers" } }
 { $description "Outputs the dimensions of a piece of text, which is either a single-line string or an array of lines." } ;
 
 HELP: draw-string
@@ -79,7 +93,11 @@ HELP: draw-string
 
 HELP: draw-text
 { $values { "font" "a font specifier" } { "text" "a string or an array of strings" } { "loc" "a pair of integers" } }
-{ $description "Draws text. Text is either a single-line string or an array of lines." } ;
+{ $description "Draws a piece of text." } ;
+
+HELP: x>offset
+{ $values { "x" real } { "font" "a font specifier" } { "string" string } { "n" integer } }
+{ $description "Outputs the string index closest to the given x co-ordinate." } ;
 
 ARTICLE: "gadgets-polygons" "Polygon gadgets"
 "A polygon gadget renders a simple shaded polygon."
@@ -119,15 +137,17 @@ $nl
 ARTICLE: "text-rendering" "Rendering text"
 "Unlike OpenGL, Factor's FreeType binding only includes the bare essentials, and there is rarely any need to directly call words in the " { $vocab-link "freetype" } " vocabulary directly. Instead, the UI provides high-level wrappers."
 $nl
-"Font objects are never constructed directly, and instead are obtained by calling a word:"
-{ $subsection open-font }
 "Measuring text:"
 { $subsection text-dim }
-{ $subsection text-height }
 { $subsection text-width }
+{ $subsection text-height }
 "Rendering text:"
-{ $subsection draw-string }
-{ $subsection draw-text } ;
+{ $subsection draw-text }
+"Low-level text protocol for UI backends:"
+{ $subsection open-font }
+{ $subsection string-width }
+{ $subsection string-height }
+{ $subsection draw-string } ;
 
 ARTICLE: "ui-paint-coord" "The UI co-ordinate system"
 "The UI uses a co-ordinate system where the y axis is oriented down. The OpenGL " { $link GL_MODELVIEW } " matrix is not saved or restored when rendering a gadget. Instead, the origin of the gadget relative to the OpenGL context is stored in a variable:"
diff --git a/basis/ui/render/render.factor b/basis/ui/render/render.factor
index 5cbac9798a..bd4b201bd7 100755
--- a/basis/ui/render/render.factor
+++ b/basis/ui/render/render.factor
@@ -213,31 +213,27 @@ HOOK: string-height font-renderer ( open-font string -- h )
 
 HOOK: draw-string font-renderer ( font string loc -- )
 
-HOOK: x>offset font-renderer ( x open-font string -- n )
+HOOK: x>offset font-renderer ( x font string -- n )
 
 HOOK: free-fonts font-renderer ( world -- )
 
 : text-height ( open-font text -- n )
-    dup string? [
-        string-height
-    ] [
-        [ string-height ] with map sum
+    [ open-font ] dip
+    dup string? [ string-height ] [
+        [ string-height ] with sigma
     ] if ;
 
 : text-width ( open-font text -- n )
-    dup string? [
-        string-width
-    ] [
+    [ open-font ] dip
+    dup string? [ string-width ] [
         [ 0 ] 2dip [ string-width max ] with each
     ] if ;
 
-: text-dim ( open-font text -- dim )
-    [ text-width ] 2keep text-height 2array ;
+: text-dim ( font text -- dim )
+    [ text-width ] [ text-height ] 2bi 2array ;
 
 : draw-text ( font text loc -- )
-    over string? [
-        draw-string
-    ] [
+    over string? [ draw-string ] [
         [
             [
                 2dup { 0 0 } draw-string
diff --git a/basis/ui/tools/listener/completion/completion.factor b/basis/ui/tools/listener/completion/completion.factor
index d7c577ed83..a4f7b107e8 100644
--- a/basis/ui/tools/listener/completion/completion.factor
+++ b/basis/ui/tools/listener/completion/completion.factor
@@ -27,6 +27,7 @@ IN: ui.tools.listener.completion
 
 ! We don't directly depend on the listener tool but we use a couple
 ! of slots
+SLOT: completion-popup
 SLOT: interactor
 SLOT: history
 
diff --git a/basis/ui/tools/operations/operations.factor b/basis/ui/tools/operations/operations.factor
index 373eaea346..aa45daf9eb 100644
--- a/basis/ui/tools/operations/operations.factor
+++ b/basis/ui/tools/operations/operations.factor
@@ -1,8 +1,8 @@
 ! Copyright (C) 2006, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: continuations definitions ui.tools.browser
-ui.tools.listener ui.tools.profiler
-ui.tools.inspector ui.tools.traceback
+ui.tools.listener ui.tools.listener.completion
+ui.tools.profiler ui.tools.inspector ui.tools.traceback
 generic help.topics stack-checker
 summary io.pathnames io.styles kernel namespaces parser
 prettyprint quotations tools.annotations editors