diff --git a/ChangeLog b/ChangeLog
index e122cf65ac42b7ffde321ce43f7b1fe22eb317c0..54fbc76cd1e41a06d9c8fe51963569046766b46d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -60,6 +60,11 @@ CVS code -
 	  when NANO_TINY is defined.  New functions do_cut_text_void()
 	  and do_copy_text(); changes to do_cut_text(), shortcut_init(),
 	  and do_input(). (DLR, suggested by Ken Tyler)
+	- Add the ability to indent and unindent all marked lines of
+	  text, via Meta-[ (Meta-}) and Meta-] (Meta-}).  New functions
+	  do_indent_marked(), do_indent_marked_void(), and
+	  do_unindent_marked_void(); changes to shortcut_init(). (Chris
+	  and DLR)
 - files.c:
   open_file()
 	- Remove redundant wording in the error message when we try to
@@ -101,7 +106,7 @@ CVS code -
 	  (DLR and Benno Schulenberg, suggested by Benno Schulenberg)
 	- Tweak the descriptions of some shortcut keys to make them more
 	  uniform. (Benno Schulenberg, minor tweaks by DLR)
-	- Add Meta-} as an alias for Meta-]. (DLR)
+	- Change the shortcut to find the matching bracket to ^]. (DLR)
   toggle_init()
 	- In the global toggle list, move the "Constant cursor position
 	  display" toggle up to after the "Use more space for editing"
diff --git a/src/global.c b/src/global.c
index f6af80a7189b431e0c7449e0d8ee3e366ec61cbc..888aaca20310133c9a7ef0adcfb08701dda52149 100644
--- a/src/global.c
+++ b/src/global.c
@@ -338,6 +338,8 @@ void shortcut_init(bool unjustify)
     const char *nano_whereis_next_msg = N_("Repeat last search");
     const char *nano_copy_msg =
 	N_("Copy the current line and store it in the cutbuffer");
+    const char *nano_indentmarked_msg = N_("Indent marked text");
+    const char *nano_unindentmarked_msg = N_("Unindent marked text");
 #endif
     const char *nano_forward_msg = N_("Move forward one character");
     const char *nano_back_msg = N_("Move back one character");
@@ -564,8 +566,18 @@ void shortcut_init(bool unjustify)
 	NANO_WHEREIS_NEXT_FKEY, NANO_NO_KEY, VIEW, do_research);
 
     sc_init_one(&main_list, NANO_NO_KEY, N_("Copy Text"),
-	IFHELP(nano_copy_msg, TRUE), NANO_COPY_KEY, NANO_NO_KEY,
+	IFHELP(nano_copy_msg, FALSE), NANO_COPY_KEY, NANO_NO_KEY,
 	NANO_COPY_ALTKEY, NOVIEW, do_copy_text);
+
+    sc_init_one(&main_list, NANO_NO_KEY, N_("Indent Text"),
+	IFHELP(nano_indentmarked_msg, FALSE), NANO_INDENTMARKED_KEY,
+	NANO_NO_KEY, NANO_INDENTMARKED_ALTKEY, NOVIEW,
+	do_indent_marked_void);
+
+    sc_init_one(&main_list, NANO_NO_KEY, N_("Unindent Text"),
+	IFHELP(nano_unindentmarked_msg, TRUE), NANO_UNINDENTMARKED_KEY,
+	NANO_NO_KEY, NANO_UNINDENTMARKED_ALTKEY, NOVIEW,
+	do_unindent_marked_void);
 #endif
 
     sc_init_one(&main_list, NANO_FORWARD_KEY, N_("Forward"),
@@ -621,9 +633,9 @@ void shortcut_init(bool unjustify)
 	NANO_NO_KEY, NANO_LASTLINE_ALTKEY2, VIEW, do_last_line);
 
 #ifndef NANO_TINY
-    sc_init_one(&main_list, NANO_NO_KEY, N_("Find Other Bracket"),
-	IFHELP(nano_bracket_msg, FALSE), NANO_BRACKET_KEY, NANO_NO_KEY,
-	NANO_BRACKET_ALTKEY, VIEW, do_find_bracket);
+    sc_init_one(&main_list, NANO_BRACKET_KEY, N_("Find Other Bracket"),
+	IFHELP(nano_bracket_msg, FALSE), NANO_NO_KEY, NANO_NO_KEY,
+	NANO_NO_KEY, VIEW, do_find_bracket);
 
     sc_init_one(&main_list, NANO_NO_KEY, N_("Scroll Up"),
 	IFHELP(nano_scrollup_msg, FALSE), NANO_SCROLLUP_KEY,
diff --git a/src/nano.h b/src/nano.h
index 68f325503c67ba86345299c9e360ea405a058d1e..234fc74442ed0c41322bdd455ede8f2fd80a4dbb 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -427,6 +427,7 @@ typedef struct rcoption {
 #define NANO_ALT_EQUALS '='
 #define NANO_ALT_RCARET '>'
 #define NANO_ALT_QUESTION '?'
+#define NANO_ALT_LBRACKET '['
 #define NANO_ALT_BACKSLASH '\\'
 #define NANO_ALT_RBRACKET ']'
 #define NANO_ALT_CARET '^'
@@ -457,6 +458,7 @@ typedef struct rcoption {
 #define NANO_ALT_X 'x'
 #define NANO_ALT_Y 'y'
 #define NANO_ALT_Z 'z'
+#define NANO_ALT_LCURLYBRACKET '{'
 #define NANO_ALT_PIPE '|'
 #define NANO_ALT_RCURLYBRACKET '}'
 
@@ -540,6 +542,10 @@ typedef struct rcoption {
 #define NANO_DELETE_KEY			NANO_CONTROL_D
 #define NANO_BACKSPACE_KEY		NANO_CONTROL_H
 #define NANO_TAB_KEY			NANO_CONTROL_I
+#define NANO_INDENTMARKED_KEY		NANO_ALT_LBRACKET
+#define NANO_INDENTMARKED_ALTKEY	NANO_ALT_LCURLYBRACKET
+#define NANO_UNINDENTMARKED_KEY		NANO_ALT_RBRACKET
+#define NANO_UNINDENTMARKED_ALTKEY	NANO_ALT_RCURLYBRACKET
 #define NANO_SUSPEND_KEY		NANO_CONTROL_Z
 #define NANO_ENTER_KEY			NANO_CONTROL_M
 #define NANO_TOFILES_KEY		NANO_CONTROL_T
@@ -549,8 +555,7 @@ typedef struct rcoption {
 #define NANO_NEXTFILE_KEY		NANO_ALT_RCARET
 #define NANO_PREVFILE_ALTKEY		NANO_ALT_COMMA
 #define NANO_NEXTFILE_ALTKEY		NANO_ALT_PERIOD
-#define NANO_BRACKET_KEY		NANO_ALT_RBRACKET
-#define NANO_BRACKET_ALTKEY		NANO_ALT_RCURLYBRACKET
+#define NANO_BRACKET_KEY		NANO_CONTROL_5
 #define NANO_NEXTWORD_KEY		NANO_CONTROL_SPACE
 #define NANO_PREVWORD_KEY		NANO_ALT_SPACE
 #define NANO_WORDCOUNT_KEY		NANO_ALT_D
diff --git a/src/proto.h b/src/proto.h
index 2fa044eab96b56ac36dbb96e151fb20ad449a33f..642d599b3b630f36ae62127e666cf910556b4b74 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -602,6 +602,11 @@ void do_mark(void);
 void do_delete(void);
 void do_backspace(void);
 void do_tab(void);
+#ifndef NANO_TINY
+void do_indent_marked(ssize_t len);
+void do_indent_marked_void(void);
+void do_unindent_marked_void(void);
+#endif
 void do_enter(void);
 #ifndef NANO_TINY
 RETSIGTYPE cancel_command(int signal);
diff --git a/src/text.c b/src/text.c
index 3ab0f66b247a688c37620fdb6cb05d3d39dd81bd..495e985f467f94d909044cb62b1ee92e5b7eefeb 100644
--- a/src/text.c
+++ b/src/text.c
@@ -193,6 +193,146 @@ void do_tab(void)
 #endif
 }
 
+#ifndef NANO_TINY
+/* Indent or unindent all lines covered by the mark len characters,
+ * depending on whether len is positive or negative.  If the
+ * TABS_TO_SPACES flag is set, indent/unindent by len spaces.
+ * Otherwise, indent/unindent by (len / tabsize) tabs and (len %
+ * tabsize) spaces. */
+void do_indent_marked(ssize_t len)
+{
+    bool indent_changed = FALSE;
+	/* Whether any indenting or unindenting was done. */
+    bool unindent = FALSE;
+	/* Whether we're unindenting text. */
+    char *line_indent;
+	/* The text added to each line in order to indent it. */
+    size_t line_indent_len;
+	/* The length of the text added to each line in order to indent
+	 * it. */
+    filestruct *top, *bot, *f;
+    size_t top_x, bot_x;
+
+    assert(openfile->current != NULL && openfile->current->data != NULL);
+
+    check_statusblank();
+
+    /* If the mark isn't on, indicate it on the statusbar and get
+     * out. */
+    if (!openfile->mark_set) {
+	statusbar(_("No lines selected, nothing to do!"));
+	return;
+    }
+
+    /* If len is zero, get out. */
+    if (len == 0)
+	return;
+
+    /* If len is negative, make it positive and set unindent to TRUE. */
+    if (len < 0) {
+	len = -len;
+	unindent = TRUE;
+    /* Otherwise, we're indenting, in which case the file will always be
+     * modified, so set indent_changed to TRUE. */
+    } else
+	indent_changed = TRUE;
+
+    /* Get the coordinates of the marked text. */
+    mark_order((const filestruct **)&top, &top_x,
+	(const filestruct **)&bot, &bot_x, NULL);
+
+    /* Set up the text we'll be using as indentation. */
+    line_indent = charalloc(len + 1);
+
+    if (ISSET(TABS_TO_SPACES)) {
+	/* Set the indentation to len spaces. */
+	charset(line_indent, ' ', len);
+	line_indent_len = len;
+    } else {
+	/* Set the indentation to (len / tabsize) tabs and (len %
+	 * tabsize) spaces. */
+	size_t num_tabs = len / tabsize;
+	size_t num_spaces = len % tabsize;
+
+	charset(line_indent, '\t', num_tabs);
+	charset(line_indent + num_tabs, ' ', num_spaces);
+
+	line_indent_len = num_tabs + num_spaces;
+    }
+
+    line_indent[line_indent_len] = '\0';
+
+    /* Go through each line of the marked text. */
+    for (f = top; f != bot->next; f = f->next) {
+	size_t line_len = strlen(f->data);
+
+	if (unindent) {
+	    if (len <= strnlenpt(f->data, indent_length(f->data))) {
+		size_t indent_len = actual_x(f->data, len);
+
+		/* If we're unindenting, and there's at least len
+		 * columns' worth of indentation on this line, remove
+		 * it. */
+		charmove(f->data, &f->data[indent_len], line_len -
+			indent_len + 1);
+		null_at(&f->data, line_len - indent_len + 1);
+		openfile->totsize -= indent_len;
+
+		/* If this is the current line, adjust the x-coordinate
+		 * to compensate for the change in it. */
+		if (f == openfile->current)
+		    openfile->current_x -= indent_len;
+
+		/* We've unindented, so set indent_changed to TRUE. */
+		if (!indent_changed)
+		    indent_changed = TRUE;
+	    }
+	} else {
+	    /* If we're indenting, add the characters in line_indent to
+	     * the beginning of this line. */
+	    f->data = charealloc(f->data, line_len +
+		line_indent_len + 1);
+	    charmove(&f->data[line_indent_len], f->data, line_len + 1);
+	    strncpy(f->data, line_indent, line_indent_len);
+	    openfile->totsize += line_indent_len;
+
+	    /* If this is the current line, adjust the x-coordinate to
+	     * compensate for the change in it. */
+	    if (f == openfile->current)
+		openfile->current_x += line_indent_len;
+
+	    /* If the NO_NEWLINES flag isn't set, and this is the
+	     * magicline, add a new magicline. */
+	    if (!ISSET(NO_NEWLINES) && openfile->current ==
+		openfile->filebot)
+		new_magicline();
+	}
+    }
+
+    free(line_indent);
+
+    if (indent_changed) {
+	/* Mark the file as modified. */
+	set_modified();
+
+	/* Update the screen. */
+	edit_refresh();
+    }
+}
+
+/* Indent all lines covered by the mark tabsize characters. */
+void do_indent_marked_void(void)
+{
+    do_indent_marked(tabsize);
+}
+
+/* Unindent all lines covered by the mark tabsize characters. */
+void do_unindent_marked_void(void)
+{
+    do_indent_marked(-tabsize);
+}
+#endif /* !NANO_TINY */
+
 /* Someone hits Enter *gasp!* */
 void do_enter(void)
 {