Index: uspace/app/edit/edit.c
===================================================================
--- uspace/app/edit/edit.c	(revision ec50d65ee29a48534ce00b21e79ef5e2e5b04274)
+++ uspace/app/edit/edit.c	(revision 14b2ac73258ca846c38ced9ac0a0e118f18e7c8f)
@@ -177,7 +177,10 @@
 static void pos_handle(pos_event_t *ev);
 
+static errno_t file_new(void);
+static void file_open(void);
+static errno_t file_open_file(const char *fname);
 static errno_t file_save(char const *fname);
 static void file_save_as(void);
-static errno_t file_insert(char *fname);
+static errno_t file_insert(const char *fname);
 static errno_t file_save_range(char const *fname, spt_t const *spos,
     spt_t const *epos);
@@ -257,4 +260,6 @@
 };
 
+static void edit_file_new(ui_menu_entry_t *, void *);
+static void edit_file_open(ui_menu_entry_t *, void *);
 static void edit_file_save(ui_menu_entry_t *, void *);
 static void edit_file_save_as(ui_menu_entry_t *, void *);
@@ -281,4 +286,14 @@
 };
 
+static void open_dialog_bok(ui_file_dialog_t *, void *, const char *);
+static void open_dialog_bcancel(ui_file_dialog_t *, void *);
+static void open_dialog_close(ui_file_dialog_t *, void *);
+
+static ui_file_dialog_cb_t open_dialog_cb = {
+	.bok = open_dialog_bok,
+	.bcancel = open_dialog_bcancel,
+	.close = open_dialog_close
+};
+
 static void save_as_dialog_bok(ui_file_dialog_t *, void *, const char *);
 static void save_as_dialog_bcancel(ui_file_dialog_t *, void *);
@@ -313,5 +328,4 @@
 int main(int argc, char *argv[])
 {
-	bool new_file;
 	errno_t rc;
 
@@ -319,43 +333,22 @@
 	pane.sh_column = 1;
 
-	/* Start with an empty sheet. */
-	rc = sheet_create(&doc.sh);
-	if (rc != EOK) {
-		printf("Out of memory.\n");
-		return -1;
-	}
-
-	/* Place caret at the beginning of file. */
-	spt_t sof;
-	pt_get_sof(&sof);
-	sheet_place_tag(doc.sh, &sof, &pane.caret_pos);
-	pane.ideal_column = 1;
+	/* Create UI */
+	rc = edit_ui_create(&edit);
+	if (rc != EOK)
+		return 1;
 
 	if (argc == 2) {
 		doc.file_name = str_dup(argv[1]);
+		rc = file_open_file(argv[1]);
+		if (rc != EOK) {
+			status_display("File not found. Starting empty file.");
+			rc = file_new();
+		}
 	} else if (argc > 1) {
 		printf("Invalid arguments.\n");
 		return -2;
 	} else {
-		doc.file_name = NULL;
-	}
-
-	new_file = false;
-
-	if (doc.file_name == NULL || file_insert(doc.file_name) != EOK)
-		new_file = true;
-
-	/* Place selection start tag. */
-	sheet_place_tag(doc.sh, &sof, &pane.sel_start);
-
-	/* Move to beginning of file. */
-	pt_get_sof(&sof);
-
-	/* Create UI */
-	rc = edit_ui_create(&edit);
-	if (rc != EOK)
-		return 1;
-
-	caret_move(sof, true, true);
+		rc = file_new();
+	}
 
 	/* Initial display */
@@ -365,10 +358,4 @@
 		return rc;
 	}
-
-	pane_status_display(&pane);
-	if (new_file && doc.file_name != NULL)
-		status_display("File not found. Starting empty file.");
-	pane_caret_display(&pane);
-	cursor_setvis(true);
 
 	ui_run(edit.ui);
@@ -390,4 +377,6 @@
 	ui_menu_t *mfile = NULL;
 	ui_menu_t *medit = NULL;
+	ui_menu_entry_t *mnew = NULL;
+	ui_menu_entry_t *mopen = NULL;
 	ui_menu_entry_t *msave = NULL;
 	ui_menu_entry_t *msaveas = NULL;
@@ -451,4 +440,20 @@
 	}
 
+	rc = ui_menu_entry_create(mfile, "~N~ew", "Ctrl-N", &mnew);
+	if (rc != EOK) {
+		printf("Error creating menu.\n");
+		return rc;
+	}
+
+	ui_menu_entry_set_cb(mnew, edit_file_new, (void *) edit);
+
+	rc = ui_menu_entry_create(mfile, "~O~pen", "Ctrl-O", &mopen);
+	if (rc != EOK) {
+		printf("Error creating menu.\n");
+		return rc;
+	}
+
+	ui_menu_entry_set_cb(mopen, edit_file_open, (void *) edit);
+
 	rc = ui_menu_entry_create(mfile, "~S~ave", "Ctrl-S", &msave);
 	if (rc != EOK) {
@@ -555,5 +560,5 @@
 	ui_menu_entry_set_cb(mfindr, edit_search_reverse_find, (void *) edit);
 
-	rc = ui_menu_entry_create(msearch, "Find ~N~ext", "Ctrl-N", &mfindn);
+	rc = ui_menu_entry_create(msearch, "Find ~N~ext", "Ctrl-R", &mfindn);
 	if (rc != EOK) {
 		printf("Error creating menu.\n");
@@ -741,4 +746,10 @@
 		ui_quit(edit.ui);
 		break;
+	case KC_N:
+		file_new();
+		break;
+	case KC_O:
+		file_open();
+		break;
 	case KC_S:
 		if (doc.file_name != NULL)
@@ -774,5 +785,5 @@
 		search_prompt(false);
 		break;
-	case KC_N:
+	case KC_R:
 		search_repeat();
 		break;
@@ -913,33 +924,48 @@
 }
 
-/** Save the document. */
-static errno_t file_save(char const *fname)
-{
-	spt_t sp, ep;
+/** Create new document. */
+static errno_t file_new(void)
+{
 	errno_t rc;
-
-	status_display("Saving...");
-	pt_get_sof(&sp);
-	pt_get_eof(&ep);
-
-	rc = file_save_range(fname, &sp, &ep);
-
-	switch (rc) {
-	case EINVAL:
-		status_display("Error opening file!");
-		break;
-	case EIO:
-		status_display("Error writing data!");
-		break;
-	default:
-		status_display("File saved.");
-		break;
-	}
-
-	return rc;
-}
-
-/** Open Save As dialog. */
-static void file_save_as(void)
+	sheet_t *sh;
+
+	/* Create empty sheet. */
+	rc = sheet_create(&sh);
+	if (rc != EOK) {
+		printf("Out of memory.\n");
+		return ENOMEM;
+	}
+
+	if (doc.sh != NULL)
+		sheet_destroy(doc.sh);
+
+	doc.sh = sh;
+
+	/* Place caret at the beginning of file. */
+	spt_t sof;
+	pt_get_sof(&sof);
+	sheet_place_tag(doc.sh, &sof, &pane.caret_pos);
+	pane.ideal_column = 1;
+
+	doc.file_name = NULL;
+
+	/* Place selection start tag. */
+	sheet_place_tag(doc.sh, &sof, &pane.sel_start);
+
+	/* Move to beginning of file. */
+	pt_get_sof(&sof);
+
+	caret_move(sof, true, true);
+
+	pane_status_display(&pane);
+	pane_caret_display(&pane);
+	pane_text_display(&pane);
+	cursor_setvis(true);
+
+	return EOK;
+}
+
+/** Open Open File dialog. */
+static void file_open(void)
 {
 	const char *old_fname = (doc.file_name != NULL) ? doc.file_name : "";
@@ -949,4 +975,105 @@
 
 	ui_file_dialog_params_init(&fdparams);
+	fdparams.caption = "Open File";
+	fdparams.ifname = old_fname;
+
+	rc = ui_file_dialog_create(edit.ui, &fdparams, &dialog);
+	if (rc != EOK) {
+		printf("Error creating message dialog.\n");
+		return;
+	}
+
+	ui_file_dialog_set_cb(dialog, &open_dialog_cb, &edit);
+}
+
+/** Open exising document. */
+static errno_t file_open_file(const char *fname)
+{
+	errno_t rc;
+	sheet_t *sh;
+	char *fn;
+
+	/* Create empty sheet. */
+	rc = sheet_create(&sh);
+	if (rc != EOK) {
+		printf("Out of memory.\n");
+		return ENOMEM;
+	}
+
+	fn = str_dup(fname);
+	if (fn == NULL) {
+		sheet_destroy(sh);
+		return ENOMEM;
+	}
+
+	if (doc.sh != NULL)
+		sheet_destroy(doc.sh);
+
+	doc.sh = sh;
+
+	/* Place caret at the beginning of file. */
+	spt_t sof;
+	pt_get_sof(&sof);
+	sheet_place_tag(doc.sh, &sof, &pane.caret_pos);
+	pane.ideal_column = 1;
+
+	rc = file_insert(fname);
+	if (rc != EOK)
+		return rc;
+
+	doc.file_name = fn;
+
+	/* Place selection start tag. */
+	sheet_place_tag(doc.sh, &sof, &pane.sel_start);
+
+	/* Move to beginning of file. */
+	pt_get_sof(&sof);
+
+	caret_move(sof, true, true);
+
+	pane_status_display(&pane);
+	pane_caret_display(&pane);
+	pane_text_display(&pane);
+	cursor_setvis(true);
+
+	return EOK;
+}
+
+/** Save the document. */
+static errno_t file_save(char const *fname)
+{
+	spt_t sp, ep;
+	errno_t rc;
+
+	status_display("Saving...");
+	pt_get_sof(&sp);
+	pt_get_eof(&ep);
+
+	rc = file_save_range(fname, &sp, &ep);
+
+	switch (rc) {
+	case EINVAL:
+		status_display("Error opening file!");
+		break;
+	case EIO:
+		status_display("Error writing data!");
+		break;
+	default:
+		status_display("File saved.");
+		break;
+	}
+
+	return rc;
+}
+
+/** Open Save As dialog. */
+static void file_save_as(void)
+{
+	const char *old_fname = (doc.file_name != NULL) ? doc.file_name : "";
+	ui_file_dialog_params_t fdparams;
+	ui_file_dialog_t *dialog;
+	errno_t rc;
+
+	ui_file_dialog_params_init(&fdparams);
 	fdparams.caption = "Save As";
 	fdparams.ifname = old_fname;
@@ -966,5 +1093,5 @@
  * of the caret.
  */
-static errno_t file_insert(char *fname)
+static errno_t file_insert(const char *fname)
 {
 	FILE *f;
@@ -2312,4 +2439,31 @@
 }
 
+/** File / New menu entry selected.
+ *
+ * @param mentry Menu entry
+ * @param arg Argument (edit_t *)
+ */
+static void edit_file_new(ui_menu_entry_t *mentry, void *arg)
+{
+	edit_t *edit = (edit_t *) arg;
+
+	(void)edit;
+	file_new();
+	(void) gfx_update(ui_window_get_gc(edit->window));
+}
+
+/** File / Open menu entry selected.
+ *
+ * @param mentry Menu entry
+ * @param arg Argument (edit_t *)
+ */
+static void edit_file_open(ui_menu_entry_t *mentry, void *arg)
+{
+	edit_t *edit = (edit_t *) arg;
+
+	(void)edit;
+	file_open();
+}
+
 /** File / Save menu entry selected.
  *
@@ -2465,4 +2619,63 @@
 	(void) arg;
 	caret_go_to_line_ask();
+}
+
+/** Open File dialog OK button press.
+ *
+ * @param dialog Open File dialog
+ * @param arg Argument (ui_demo_t *)
+ * @param fname File name
+ */
+static void open_dialog_bok(ui_file_dialog_t *dialog, void *arg,
+    const char *fname)
+{
+	edit_t *edit = (edit_t *)arg;
+	char *cname;
+	errno_t rc;
+
+	(void)edit;
+	ui_file_dialog_destroy(dialog);
+
+	cname = str_dup(fname);
+	if (cname == NULL) {
+		printf("Out of memory.\n");
+		return;
+	}
+
+	rc = file_open_file(fname);
+	if (rc != EOK)
+		return;
+
+	if (doc.file_name != NULL)
+		free(doc.file_name);
+	doc.file_name = cname;
+
+	(void) gfx_update(ui_window_get_gc(edit->window));
+}
+
+/** Open File dialog cancel button press.
+ *
+ * @param dialog File dialog
+ * @param arg Argument (ui_demo_t *)
+ */
+static void open_dialog_bcancel(ui_file_dialog_t *dialog, void *arg)
+{
+	edit_t *edit = (edit_t *)arg;
+
+	(void)edit;
+	ui_file_dialog_destroy(dialog);
+}
+
+/** Open File dialog close request.
+ *
+ * @param dialog File dialog
+ * @param arg Argument (ui_demo_t *)
+ */
+static void open_dialog_close(ui_file_dialog_t *dialog, void *arg)
+{
+	edit_t *edit = (edit_t *)arg;
+
+	(void)edit;
+	ui_file_dialog_destroy(dialog);
 }
 
Index: uspace/app/edit/sheet.c
===================================================================
--- uspace/app/edit/sheet.c	(revision ec50d65ee29a48534ce00b21e79ef5e2e5b04274)
+++ uspace/app/edit/sheet.c	(revision 14b2ac73258ca846c38ced9ac0a0e118f18e7c8f)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * All rights reserved.
  *
@@ -90,4 +90,11 @@
 }
 
+/** Destroy sheet. */
+void sheet_destroy(sheet_t *sh)
+{
+	free(sh->data);
+	free(sh);
+}
+
 /** Insert text into sheet.
  *
Index: uspace/app/edit/sheet.h
===================================================================
--- uspace/app/edit/sheet.h	(revision ec50d65ee29a48534ce00b21e79ef5e2e5b04274)
+++ uspace/app/edit/sheet.h	(revision 14b2ac73258ca846c38ced9ac0a0e118f18e7c8f)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * All rights reserved.
  *
@@ -91,4 +91,5 @@
 
 extern errno_t sheet_create(sheet_t **);
+extern void sheet_destroy(sheet_t *);
 extern errno_t sheet_insert(sheet_t *, spt_t *, enum dir_spec, char *);
 extern errno_t sheet_delete(sheet_t *, spt_t *, spt_t *);
