diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h
index b8b5e33..4203125 100644
--- a/gtk/gtkenums.h
+++ b/gtk/gtkenums.h
@@ -177,6 +177,21 @@ typedef enum
   GTK_TEXT_DIR_RTL
 } GtkTextDirection;
 
+/* Type of newline */
+typedef enum
+{
+  GTK_TEXT_RETURN_NORMAL,
+  GTK_TEXT_RETURN_CONTROL
+} GtkTextReturnType;
+
+/* Type of tab */
+typedef enum
+{
+  GTK_TEXT_TAB_NORMAL,
+  GTK_TEXT_TAB_CONTROL,
+  GTK_TEXT_TAB_SHIFT
+} GtkTextTabType;
+
 /* justification for label and maybe other widgets (text?) */
 typedef enum
 {
diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c
index e223d92..4b4bad7 100644
--- a/gtk/gtktextbuffer.c
+++ b/gtk/gtktextbuffer.c
@@ -3915,6 +3915,96 @@ gtk_text_buffer_backspace (GtkTextBuffer *buffer,
   return retval;
 }
 
+/**
+ * gtk_text_buffer_newline:
+ * @buffer: a #GtkTextBuffer
+ * @iter: a position in @buffer
+ * @interactive: whether the deletion is caused by user interaction
+ * @default_editable: whether the buffer is editable by default
+ * 
+ * Performs the appropriate action as if the user hit the enter
+ * key with the cursor at the position specified by @iter.
+ * 
+ * Because the buffer is modified, all outstanding iterators become
+ * invalid after calling this function; however, the @iter will be
+ * re-initialized to point to the location where text was deleted.
+ *
+ * Since: 2.20
+ **/
+void
+gtk_text_buffer_newline (GtkTextBuffer *buffer,
+			 GtkTextIter   *iter,
+			 gboolean       interactive,
+			 gboolean       default_editable)
+{
+  GtkTextIter start;
+
+  g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+  g_return_if_fail (iter != NULL);
+
+  start = *iter;
+
+  if (interactive)
+    gtk_text_buffer_begin_user_action (buffer);
+
+  gtk_text_buffer_insert_interactive (buffer,
+                                      &start,
+                                      "\n",
+                                      1,
+                                      default_editable);
+
+  if (interactive)
+    gtk_text_buffer_end_user_action (buffer);
+
+  /* Revalidate the users iter */
+  *iter = start;
+}
+
+/**
+ * gtk_text_buffer_tab:
+ * @buffer: a #GtkTextBuffer
+ * @iter: a position in @buffer
+ * @interactive: whether the deletion is caused by user interaction
+ * @default_editable: whether the buffer is editable by default
+ * 
+ * Performs the appropriate action as if the user hit the tab
+ * key with the cursor at the position specified by @iter.
+ * 
+ * Because the buffer is modified, all outstanding iterators become
+ * invalid after calling this function; however, the @iter will be
+ * re-initialized to point to the location where text was deleted.
+ *
+ * Since: 2.20
+ **/
+void
+gtk_text_buffer_tab (GtkTextBuffer *buffer,
+		     GtkTextIter   *iter,
+		     gboolean       interactive,
+		     gboolean       default_editable)
+{
+  GtkTextIter start;
+
+  g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+  g_return_if_fail (iter != NULL);
+
+  start = *iter;
+
+  if (interactive)
+    gtk_text_buffer_begin_user_action (buffer);
+
+  gtk_text_buffer_insert_interactive (buffer,
+                                      &start,
+                                      "\t",
+                                      1,
+                                      default_editable);
+
+  if (interactive)
+    gtk_text_buffer_end_user_action (buffer);
+
+  /* Revalidate the users iter */
+  *iter = start;
+}
+
 static void
 cut_or_copy (GtkTextBuffer *buffer,
 	     GtkClipboard  *clipboard,
diff --git a/gtk/gtktextbuffer.h b/gtk/gtktextbuffer.h
index d160c49..c990986 100644
--- a/gtk/gtktextbuffer.h
+++ b/gtk/gtktextbuffer.h
@@ -227,6 +227,16 @@ gboolean gtk_text_buffer_backspace          (GtkTextBuffer *buffer,
 					     gboolean       interactive,
 					     gboolean       default_editable);
 
+void     gtk_text_buffer_newline            (GtkTextBuffer *buffer,
+					     GtkTextIter   *iter,
+					     gboolean       interactive,
+					     gboolean       default_editable);
+
+void     gtk_text_buffer_tab                (GtkTextBuffer *buffer,
+					     GtkTextIter   *iter,
+					     gboolean       interactive,
+					     gboolean       default_editable);
+
 /* Obtain strings from the buffer */
 gchar          *gtk_text_buffer_get_text            (GtkTextBuffer     *buffer,
                                                      const GtkTextIter *start,
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index 80d356d..15fdf7b 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -131,6 +131,8 @@ enum
   INSERT_AT_CURSOR,
   DELETE_FROM_CURSOR,
   BACKSPACE,
+  NEWLINE,
+  TAB,
   CUT_CLIPBOARD,
   COPY_CLIPBOARD,
   PASTE_CLIPBOARD,
@@ -277,6 +279,10 @@ static void gtk_text_view_delete_from_cursor (GtkTextView           *text_view,
                                               GtkDeleteType          type,
                                               gint                   count);
 static void gtk_text_view_backspace        (GtkTextView           *text_view);
+static void gtk_text_view_newline          (GtkTextView           *text_view,
+                                            GtkTextReturnType      type);
+static void gtk_text_view_tab              (GtkTextView           *text_view,
+                                            GtkTextTabType         type);
 static void gtk_text_view_cut_clipboard    (GtkTextView           *text_view);
 static void gtk_text_view_copy_clipboard   (GtkTextView           *text_view);
 static void gtk_text_view_paste_clipboard  (GtkTextView           *text_view);
@@ -529,6 +535,8 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
   klass->insert_at_cursor = gtk_text_view_insert_at_cursor;
   klass->delete_from_cursor = gtk_text_view_delete_from_cursor;
   klass->backspace = gtk_text_view_backspace;
+  klass->newline = gtk_text_view_newline;
+  klass->tab = gtk_text_view_tab;
   klass->cut_clipboard = gtk_text_view_cut_clipboard;
   klass->copy_clipboard = gtk_text_view_copy_clipboard;
   klass->paste_clipboard = gtk_text_view_paste_clipboard;
@@ -886,6 +894,48 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
 		  G_TYPE_NONE, 0);
 
   /**
+   * GtkTextView::newline:
+   * @text_view: the object which received the signal
+   *
+   * The ::newline signal is a 
+   * <link linkend="keybinding-signals">keybinding signal</link> 
+   * which gets emitted when the user asks for it.
+   * 
+   * The default bindings for this signal are
+   * GDK_Return and GDK_KP_Enter.
+   */
+  signals[NEWLINE] =
+    g_signal_new (I_("newline"),
+		  G_OBJECT_CLASS_TYPE (gobject_class),
+		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		  G_STRUCT_OFFSET (GtkTextViewClass, newline),
+		  NULL, NULL,
+		  _gtk_marshal_VOID__ENUM,
+		  G_TYPE_NONE, 1,
+		  GTK_TYPE_TEXT_RETURN_TYPE);
+
+  /**
+   * GtkTextView::tab:
+   * @text_view: the object which received the signal
+   *
+   * The ::tab signal is a 
+   * <link linkend="keybinding-signals">keybinding signal</link> 
+   * which gets emitted when the user asks for it.
+   * 
+   * The default bindings for this signal are
+   * Tab and Shift+Tab.
+   */
+  signals[TAB] =
+    g_signal_new (I_("tab"),
+		  G_OBJECT_CLASS_TYPE (gobject_class),
+		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		  G_STRUCT_OFFSET (GtkTextViewClass, tab),
+		  NULL, NULL,
+		  _gtk_marshal_VOID__ENUM,
+		  G_TYPE_NONE, 1,
+		  GTK_TYPE_TEXT_TAB_TYPE);
+
+  /**
    * GtkTextView::cut-clipboard:
    * @text_view: the object which received the signal
    *
@@ -1211,6 +1261,26 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
   gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_SHIFT_MASK,
 				"backspace", 0);
 
+  gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
+				"newline", 1,
+				G_TYPE_ENUM, GTK_TEXT_RETURN_NORMAL);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
+				"newline", 1,
+				G_TYPE_ENUM, GTK_TEXT_RETURN_CONTROL);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_Tab, 0,
+				"tab", 1,
+				G_TYPE_ENUM, GTK_TEXT_TAB_NORMAL);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, 0,
+				"tab", 1,
+				G_TYPE_ENUM, GTK_TEXT_TAB_CONTROL);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, 0,
+				"tab", 1,
+				G_TYPE_ENUM, GTK_TEXT_TAB_SHIFT);
+
   gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_CONTROL_MASK,
 				"delete-from-cursor", 2,
 				G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
@@ -5767,6 +5837,56 @@ gtk_text_view_backspace (GtkTextView *text_view)
 }
 
 static void
+gtk_text_view_newline (GtkTextView      *text_view,
+                       GtkTextReturnType type)
+{
+  GtkTextIter insert;
+
+  gtk_text_view_reset_im_context (text_view);
+
+  /* A newline added deletes the selection, if one exists */
+  gtk_text_buffer_delete_selection (get_buffer (text_view), TRUE,
+                                    text_view->editable);
+
+  gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
+                                    &insert,
+                                    gtk_text_buffer_get_insert (get_buffer (text_view)));
+
+  gtk_text_buffer_newline (get_buffer (text_view), &insert,
+                           TRUE, text_view->editable);
+
+  gtk_text_view_set_virtual_cursor_pos (text_view, -1, -1);
+  DV(g_print (G_STRLOC": scrolling onscreen\n"));
+  gtk_text_view_scroll_mark_onscreen (text_view,
+                                      gtk_text_buffer_get_insert (get_buffer (text_view)));
+}
+
+static void
+gtk_text_view_tab (GtkTextView   *text_view,
+                   GtkTextTabType type)
+{
+  GtkTextIter insert;
+
+  gtk_text_view_reset_im_context (text_view);
+
+  /* A newline added deletes the selection, if one exists */
+  gtk_text_buffer_delete_selection (get_buffer (text_view), TRUE,
+                                    text_view->editable);
+
+  gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
+                                    &insert,
+                                    gtk_text_buffer_get_insert (get_buffer (text_view)));
+
+  gtk_text_buffer_tab (get_buffer (text_view), &insert,
+                       TRUE, text_view->editable);
+
+  gtk_text_view_set_virtual_cursor_pos (text_view, -1, -1);
+  DV(g_print (G_STRLOC": scrolling onscreen\n"));
+  gtk_text_view_scroll_mark_onscreen (text_view,
+                                      gtk_text_buffer_get_insert (get_buffer (text_view)));
+}
+
+static void
 gtk_text_view_cut_clipboard (GtkTextView *text_view)
 {
   GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (text_view),
diff --git a/gtk/gtktextview.h b/gtk/gtktextview.h
index 2dfe23f..64aad15 100644
--- a/gtk/gtktextview.h
+++ b/gtk/gtktextview.h
@@ -189,6 +189,10 @@ struct _GtkTextViewClass
                                   GtkDeleteType type,
                                   gint          count);
   void (* backspace)             (GtkTextView *text_view);
+  void (* newline)               (GtkTextView      *text_view,
+                                  GtkTextReturnType type);
+  void (* tab)                   (GtkTextView   *text_view,
+                                  GtkTextTabType type);
 
   /* cut copy paste */
   void (* cut_clipboard)   (GtkTextView *text_view);
@@ -210,8 +214,6 @@ struct _GtkTextViewClass
   void (*_gtk_reserved3) (void);
   void (*_gtk_reserved4) (void);
   void (*_gtk_reserved5) (void);
-  void (*_gtk_reserved6) (void);
-  void (*_gtk_reserved7) (void);
 };
 
 GType          gtk_text_view_get_type              (void) G_GNUC_CONST;
