Index: uspace/lib/ui/src/entry.c
===================================================================
--- uspace/lib/ui/src/entry.c	(revision a1060379ce24b77cb1b63887c9375b876bc99a1f)
+++ uspace/lib/ui/src/entry.c	(revision dbb42c982dff2647002dca167e97850fbbc2f2fd)
@@ -67,5 +67,7 @@
 	ui_entry_cursor_width = 2,
 	ui_entry_sel_hpad = 0,
-	ui_entry_sel_vpad = 2
+	ui_entry_sel_vpad = 2,
+	/** Additional amount to scroll to the left after revealing cursor */
+	ui_entry_left_scroll_margin = 30
 };
 
@@ -156,4 +158,6 @@
 {
 	entry->halign = halign;
+	ui_entry_scroll_update(entry, true);
+	ui_entry_paint(entry);
 }
 
@@ -186,4 +190,6 @@
 	entry->pos = str_size(text);
 	entry->sel_start = entry->pos;
+	ui_entry_scroll_update(entry, false);
+	ui_entry_paint(entry);
 
 	return EOK;
@@ -452,4 +458,5 @@
 	entry->pos = off1;
 	entry->sel_start = off1;
+	ui_entry_scroll_update(entry, false);
 	ui_entry_paint(entry);
 }
@@ -494,4 +501,5 @@
 
 	entry->sel_start = entry->pos;
+	ui_entry_scroll_update(entry, false);
 	ui_entry_paint(entry);
 
@@ -526,4 +534,5 @@
 	entry->sel_start = off;
 
+	ui_entry_scroll_update(entry, false);
 	ui_entry_paint(entry);
 }
@@ -551,4 +560,5 @@
 	    str_size(entry->text + off) + 1);
 
+	ui_entry_scroll_update(entry, false);
 	ui_entry_paint(entry);
 }
@@ -875,5 +885,4 @@
 	gfx_coord_t hpad;
 	gfx_coord_t vpad;
-	gfx_coord_t width;
 	ui_resource_t *res;
 
@@ -895,21 +904,26 @@
 	}
 
-	width = gfx_text_width(res->font, entry->text);
+	geom->text_rect.p0.x = geom->interior_rect.p0.x + hpad;
+	geom->text_rect.p0.y = geom->interior_rect.p0.y + vpad;
+	geom->text_rect.p1.x = geom->interior_rect.p1.x - hpad;
+	geom->text_rect.p1.y = geom->interior_rect.p1.y - vpad;
+
+	geom->text_pos.x = geom->interior_rect.p0.x + hpad +
+	    entry->scroll_pos;
+	geom->text_pos.y = geom->interior_rect.p0.y + vpad;
 
 	switch (entry->halign) {
 	case gfx_halign_left:
 	case gfx_halign_justify:
-		geom->text_pos.x = geom->interior_rect.p0.x + hpad;
+		geom->anchor_x = geom->text_rect.p0.x;
 		break;
 	case gfx_halign_center:
-		geom->text_pos.x = (geom->interior_rect.p0.x +
-		    geom->interior_rect.p1.x) / 2 - width / 2;
+		geom->anchor_x = (geom->text_rect.p0.x +
+		    geom->text_rect.p1.x) / 2;
 		break;
 	case gfx_halign_right:
-		geom->text_pos.x = geom->interior_rect.p1.x - hpad - 1 - width;
-		break;
-	}
-
-	geom->text_pos.y = geom->interior_rect.p0.y + vpad;
+		geom->anchor_x = geom->text_rect.p1.x;
+		break;
+	}
 }
 
@@ -945,4 +959,6 @@
 	if (!shift)
 		entry->sel_start = entry->pos;
+
+	ui_entry_scroll_update(entry, false);
 	(void) ui_entry_paint(entry);
 }
@@ -959,4 +975,6 @@
 	if (!shift)
 		entry->sel_start = entry->pos;
+
+	ui_entry_scroll_update(entry, false);
 	(void) ui_entry_paint(entry);
 }
@@ -978,4 +996,6 @@
 	if (!shift)
 		entry->sel_start = entry->pos;
+
+	ui_entry_scroll_update(entry, false);
 	(void) ui_entry_paint(entry);
 }
@@ -997,4 +1017,6 @@
 	if (!shift)
 		entry->sel_start = entry->pos;
+
+	ui_entry_scroll_update(entry, false);
 	(void) ui_entry_paint(entry);
 }
@@ -1021,4 +1043,74 @@
 }
 
+/** Update text entry scroll position.
+ *
+ * @param entry Text entry
+ * @param realign @c true iff we should left-align short text.
+ *                This should be only used when changing text alignment,
+ *                because left-aligned text entries should not realign
+ *                the text to the left side under normal circumstances.
+ */
+void ui_entry_scroll_update(ui_entry_t *entry, bool realign)
+{
+	ui_entry_geom_t geom;
+	gfx_coord_t x;
+	gfx_coord_t width;
+	gfx_coord2_t tpos;
+	gfx_coord2_t anchor;
+	gfx_text_fmt_t fmt;
+	ui_resource_t *res;
+
+	res = ui_window_get_res(entry->window);
+
+	ui_entry_get_geom(entry, &geom);
+
+	/* Compute position where cursor is currently displayed at */
+	x = geom.text_pos.x + ui_entry_lwidth(entry);
+
+	/* Is cursor off to the left? */
+	if (x < geom.text_rect.p0.x) {
+		/*
+		 * Scroll to make cursor visible and put some space between it
+		 * and the left edge of the text rectangle.
+		 */
+		entry->scroll_pos += geom.text_rect.p0.x - x +
+		    ui_entry_left_scroll_margin;
+
+		/*
+		 * We don't want to scroll further than what's needed
+		 * to reveal the beginning of the text.
+		 */
+		if (entry->scroll_pos > 0)
+			entry->scroll_pos = 0;
+	}
+
+	/*
+	 * Is cursor off to the right? Note that the width of the cursor
+	 * is deliberately not taken into account (i.e. we only care
+	 * about the left edge of the cursor).
+	 */
+	if (x > geom.text_rect.p1.x)
+		entry->scroll_pos -= x + 2 - geom.text_rect.p1.x;
+
+	width = gfx_text_width(res->font, entry->text);
+
+	if (width < geom.text_rect.p1.x - geom.text_rect.p0.x &&
+	    (realign || entry->halign != gfx_halign_left)) {
+		/* Text fits inside entry, so we need to align it */
+		anchor.x = geom.anchor_x;
+		anchor.y = 0;
+		gfx_text_fmt_init(&fmt);
+		fmt.halign = entry->halign;
+		gfx_text_start_pos(res->font, &anchor, &fmt, entry->text,
+		    &tpos);
+		entry->scroll_pos = tpos.x - geom.text_rect.p0.x;
+	} else if (geom.text_pos.x + width < geom.text_rect.p1.x &&
+	    entry->halign != gfx_halign_left) {
+		/* Text is long, unused space on the right */
+		entry->scroll_pos += geom.text_rect.p1.x -
+		    geom.text_pos.x - width;
+	}
+}
+
 /** @}
  */
