Add 'relativenumber' patch from Markus Heidelberg.
diff --git a/src/edit.c b/src/edit.c
index 33e580f..88943cd 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -6272,7 +6272,7 @@
 		    )
 	    textwidth -= 1;
 #endif
-	if (curwin->w_p_nu)
+	if (curwin->w_p_nu || curwin->w_p_rnu)
 	    textwidth -= 8;
     }
     if (textwidth < 0)
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 2296c33..1f9a7f2 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -3488,6 +3488,7 @@
 	curbuf->b_p_ma = FALSE;		/* not modifiable */
 	curbuf->b_p_bin = FALSE;	/* reset 'bin' before reading file */
 	curwin->w_p_nu = 0;		/* no line numbers */
+	curwin->w_p_rnu = 0;		/* no relative line numbers */
 #ifdef FEAT_SCROLLBIND
 	curwin->w_p_scb = FALSE;	/* no scroll binding */
 #endif
diff --git a/src/gui.c b/src/gui.c
index 2c307fa..5b1a2ae 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -4412,7 +4412,7 @@
 	max += W_WIDTH(curwin) - 1;
 #endif
 	/* The line number isn't scrolled, thus there is less space when
-	 * 'number' is set (also for 'foldcolumn'). */
+	 * 'number' or 'relativenumber' is set (also for 'foldcolumn'). */
 	size -= curwin_col_off();
 #ifndef SCROLL_PAST_END
 	max -= curwin_col_off();
diff --git a/src/misc1.c b/src/misc1.c
index d476f31..69bfe7d 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -1742,7 +1742,7 @@
 	col += 1;
 
     /*
-     * Add column offset for 'number' and 'foldcolumn'.
+     * Add column offset for 'number', 'relativenumber' and 'foldcolumn'.
      */
     width = W_WIDTH(wp) - win_col_off(wp);
     if (width <= 0)
@@ -1803,7 +1803,7 @@
 	col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL) - 1;
 
     /*
-     * Add column offset for 'number', 'foldcolumn', etc.
+     * Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
      */
     width = W_WIDTH(wp) - win_col_off(wp);
     if (width <= 0)
diff --git a/src/misc2.c b/src/misc2.c
index 949d7e2..8cd5683 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -469,6 +469,57 @@
 }
 
 /*
+ * Get the line number relative to the current cursor position, i.e. the
+ * difference between line number and cursor position. Only look for lines that
+ * can be visible, folded lines don't count.
+ */
+    linenr_T
+get_cursor_rel_lnum(wp, lnum)
+    win_T	*wp;
+    linenr_T	lnum;		    /* line number to get the result for */
+{
+    linenr_T	cursor = wp->w_cursor.lnum;
+    linenr_T	retval = 0;
+
+#ifdef FEAT_FOLDING
+    if (hasAnyFolding(wp))
+    {
+	if (lnum > cursor)
+	{
+	    while (lnum > cursor)
+	    {
+		(void)hasFolding(lnum, &lnum, NULL);
+		/* if lnum and cursor are in the same fold,
+		 * now lnum <= cursor */
+		if (lnum > cursor)
+		    retval++;
+		lnum--;
+	    }
+	}
+	else if (lnum < cursor)
+	{
+	    while (lnum < cursor)
+	    {
+		(void)hasFolding(lnum, NULL, &lnum);
+		/* if lnum and cursor are in the same fold,
+		 * now lnum >= cursor */
+		if (lnum < cursor)
+		    retval--;
+		lnum++;
+	    }
+	}
+	/* else if (lnum == cursor)
+	 *     retval = 0;
+	 */
+    }
+    else
+#endif
+	retval = lnum - cursor;
+
+    return retval;
+}
+
+/*
  * Make sure curwin->w_cursor.lnum is valid.
  */
     void
diff --git a/src/move.c b/src/move.c
index de1a9e4..4bdb694 100644
--- a/src/move.c
+++ b/src/move.c
@@ -916,14 +916,14 @@
 }
 
 /*
- * Compute offset of a window, occupied by line number, fold column and sign
- * column (these don't move when scrolling horizontally).
+ * Compute offset of a window, occupied by absolute or relative line number,
+ * fold column and sign column (these don't move when scrolling horizontally).
  */
     int
 win_col_off(wp)
     win_T	*wp;
 {
-    return ((wp->w_p_nu ? number_width(wp) + 1 : 0)
+    return (((wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) + 1 : 0)
 #ifdef FEAT_CMDWIN
 	    + (cmdwin_type == 0 || wp != curwin ? 0 : 1)
 #endif
@@ -949,13 +949,14 @@
 
 /*
  * Return the difference in column offset for the second screen line of a
- * wrapped line.  It's 8 if 'number' is on and 'n' is in 'cpoptions'.
+ * wrapped line.  It's 8 if 'number' or 'relativenumber' is on and 'n' is in
+ * 'cpoptions'.
  */
     int
 win_col_off2(wp)
     win_T	*wp;
 {
-    if (wp->w_p_nu && vim_strchr(p_cpo, CPO_NUMCOL) != NULL)
+    if ((wp->w_p_nu || wp->w_p_rnu) && vim_strchr(p_cpo, CPO_NUMCOL) != NULL)
 	return number_width(wp) + 1;
     return 0;
 }
@@ -1218,17 +1219,22 @@
     if (prev_skipcol != curwin->w_skipcol)
 	redraw_later(NOT_VALID);
 
+    /* Redraw when w_row changes and 'relativenumber' is set */
+    if (((curwin->w_valid & VALID_WROW) == 0 && (curwin->w_p_rnu
 #ifdef FEAT_SYN_HL
-    /* Redraw when w_virtcol changes and 'cursorcolumn' is set, or when w_row
-     * changes and 'cursorline' is set. */
-    if (((curwin->w_p_cuc && (curwin->w_valid & VALID_VIRTCOL) == 0)
-		|| (curwin->w_p_cul && (curwin->w_valid & VALID_WROW) == 0))
-# ifdef FEAT_INS_EXPAND
-	    && !pum_visible()
-# endif
-	    )
-	redraw_later(SOME_VALID);
+	/* or when w_row changes and 'cursorline' is set. */
+						|| curwin->w_p_cul
 #endif
+	))
+#ifdef FEAT_SYN_HL
+	/* or when w_virtcol changes and 'cursorcolumn' is set */
+	|| (curwin->w_p_cuc && (curwin->w_valid & VALID_VIRTCOL) == 0)
+#endif
+	)
+# ifdef FEAT_INS_EXPAND
+	    if (!pum_visible())
+# endif
+		redraw_later(SOME_VALID);
 
     curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
 }
diff --git a/src/netbeans.c b/src/netbeans.c
index 94c1aaa..93a9aea 100644
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -3143,7 +3143,8 @@
 
     if (bufno >= 0 && curwin != NULL && curwin->w_buffer == curbuf)
     {
-	int col = mouse_col - W_WINCOL(curwin) - (curwin->w_p_nu ? 9 : 1);
+	int col = mouse_col - W_WINCOL(curwin)
+		  - ((curwin->w_p_nu || curwin->w_p_rnu) ? 9 : 1);
 	long off = pos2off(curbuf, &curwin->w_cursor);
 
 	/* sync the cursor position */
diff --git a/src/normal.c b/src/normal.c
index a19771b..e02c817 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -7845,8 +7845,9 @@
 	}
 	else
 	    i = curwin->w_leftcol;
-	/* Go to the middle of the screen line.  When 'number' is on and lines
-	 * are wrapping the middle can be more to the left. */
+	/* Go to the middle of the screen line.  When 'number' or
+	 * 'relativenumber' is on and lines are wrapping the middle can be more
+	 * to the left. */
 	if (cap->nchar == 'm')
 	    i += (W_WIDTH(curwin) - curwin_col_off()
 		    + ((curwin->w_p_wrap && i > 0)
diff --git a/src/option.c b/src/option.c
index f93d839..c9cad32 100644
--- a/src/option.c
+++ b/src/option.c
@@ -207,6 +207,7 @@
 # define PV_LBR		OPT_WIN(WV_LBR)
 #endif
 #define PV_NU		OPT_WIN(WV_NU)
+#define PV_RNU		OPT_WIN(WV_RNU)
 #ifdef FEAT_LINEBREAK
 # define PV_NUW		OPT_WIN(WV_NUW)
 #endif
@@ -2015,6 +2016,9 @@
 			    (char_u *)NULL, PV_NONE,
 #endif
 			    {(char_u *)2000L, (char_u *)0L} SCRIPTID_INIT},
+    {"relativenumber", "rnu", P_BOOL|P_VI_DEF|P_RWIN,
+			    (char_u *)VAR_WIN, PV_RNU,
+			    {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
     {"remap",	    NULL,   P_BOOL|P_VI_DEF,
 			    (char_u *)&p_remap, PV_NONE,
 			    {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT},
@@ -7230,10 +7234,18 @@
 
     /* 'list', 'number' */
     else if ((int *)varp == &curwin->w_p_list
-	  || (int *)varp == &curwin->w_p_nu)
+	  || (int *)varp == &curwin->w_p_nu
+	  || (int *)varp == &curwin->w_p_rnu)
     {
 	if (curwin->w_curswant != MAXCOL)
 	    curwin->w_set_curswant = TRUE;
+
+	/* If 'number' is set, reset 'relativenumber'. */
+	/* If 'relativenumber' is set, reset 'number'. */
+	if ((int *)varp == &curwin->w_p_nu && curwin->w_p_nu)
+	    curwin->w_p_rnu = FALSE;
+	if ((int *)varp == &curwin->w_p_rnu && curwin->w_p_rnu)
+	    curwin->w_p_nu = FALSE;
     }
 
     else if ((int *)varp == &curbuf->b_p_ro)
@@ -9232,6 +9244,7 @@
 	case PV_FMR:	return (char_u *)&(curwin->w_p_fmr);
 #endif
 	case PV_NU:	return (char_u *)&(curwin->w_p_nu);
+	case PV_RNU:	return (char_u *)&(curwin->w_p_rnu);
 #ifdef FEAT_LINEBREAK
 	case PV_NUW:	return (char_u *)&(curwin->w_p_nuw);
 #endif
@@ -9417,6 +9430,7 @@
 #endif
     to->wo_list = from->wo_list;
     to->wo_nu = from->wo_nu;
+    to->wo_rnu = from->wo_rnu;
 #ifdef FEAT_LINEBREAK
     to->wo_nuw = from->wo_nuw;
 #endif
diff --git a/src/option.h b/src/option.h
index cfa7692..b635db1 100644
--- a/src/option.h
+++ b/src/option.h
@@ -1039,6 +1039,7 @@
     , WV_LBR
 #endif
     , WV_NU
+    , WV_RNU
 #ifdef FEAT_LINEBREAK
     , WV_NUW
 #endif
diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro
index 261ec82..5c4cc42 100644
--- a/src/proto/misc2.pro
+++ b/src/proto/misc2.pro
@@ -11,6 +11,7 @@
 int dec_cursor __ARGS((void));
 int dec __ARGS((pos_T *lp));
 int decl __ARGS((pos_T *lp));
+linenr_T get_cursor_rel_lnum __ARGS((win_T *wp, linenr_T lnum));
 void check_cursor_lnum __ARGS((void));
 void check_cursor_col __ARGS((void));
 void check_cursor __ARGS((void));
diff --git a/src/screen.c b/src/screen.c
index 7f929ac..72a93da 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -423,9 +423,11 @@
 	check_for_delay(FALSE);
 
 #ifdef FEAT_LINEBREAK
-    /* Force redraw when width of 'number' column changes. */
+    /* Force redraw when width of 'number' or 'relativenumber' column
+     * changes. */
     if (curwin->w_redr_type < NOT_VALID
-	   && curwin->w_nrwidth != (curwin->w_p_nu ? number_width(curwin) : 0))
+	   && curwin->w_nrwidth != ((curwin->w_p_nu || curwin->w_p_rnu)
+				    ? number_width(curwin) : 0))
 	curwin->w_redr_type = NOT_VALID;
 #endif
 
@@ -871,8 +873,9 @@
 #endif
 
 #ifdef FEAT_LINEBREAK
-    /* Force redraw when width of 'number' column changes. */
-    i = wp->w_p_nu ? number_width(wp) : 0;
+    /* Force redraw when width of 'number' or 'relativenumber' column
+     * changes. */
+    i = (wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) : 0;
     if (wp->w_nrwidth != i)
     {
 	type = NOT_VALID;
@@ -2118,7 +2121,7 @@
     /* Build the fold line:
      * 1. Add the cmdwin_type for the command-line window
      * 2. Add the 'foldcolumn'
-     * 3. Add the 'number' column
+     * 3. Add the 'number' or 'relativenumber' column
      * 4. Compose the text
      * 5. Add the text
      * 6. set highlighting for the Visual area an other text
@@ -2180,7 +2183,8 @@
 				 ScreenAttrs[off + (p) + ri] = v
 #endif
 
-    /* Set all attributes of the 'number' column and the text */
+    /* Set all attributes of the 'number' or 'relativenumber' column and the
+     * text */
     RL_MEMSET(col, hl_attr(HLF_FL), W_WIDTH(wp) - col);
 
 #ifdef FEAT_SIGNS
@@ -2206,18 +2210,27 @@
 #endif
 
     /*
-     * 3. Add the 'number' column
+     * 3. Add the 'number' or 'relativenumber' column
      */
-    if (wp->w_p_nu)
+    if (wp->w_p_nu || wp->w_p_rnu)
     {
 	len = W_WIDTH(wp) - col;
 	if (len > 0)
 	{
 	    int	    w = number_width(wp);
+	    long num;
 
 	    if (len > w + 1)
 		len = w + 1;
-	    sprintf((char *)buf, "%*ld ", w, (long)lnum);
+
+	    if (wp->w_p_nu)
+		/* 'number' */
+		num = (long)lnum;
+	    else
+		/* 'relativenumber', don't use negative numbers */
+		num = (long)abs((int)get_cursor_rel_lnum(wp, lnum));
+
+	    sprintf((char *)buf, "%*ld ", w, num);
 #ifdef FEAT_RIGHTLEFT
 	    if (wp->w_p_rl)
 		/* the line number isn't reversed */
@@ -3327,9 +3340,9 @@
 	    if (draw_state == WL_NR - 1 && n_extra == 0)
 	    {
 		draw_state = WL_NR;
-		/* Display the line number.  After the first fill with blanks
-		 * when the 'n' flag isn't in 'cpo' */
-		if (wp->w_p_nu
+		/* Display the absolute or relative line number. After the
+		 * first fill with blanks when the 'n' flag isn't in 'cpo' */
+		if ((wp->w_p_nu || wp->w_p_rnu)
 			&& (row == startrow
 #ifdef FEAT_DIFF
 			    + filler_lines
@@ -3343,8 +3356,18 @@
 #endif
 			    )
 		    {
+			long num;
+
+			if (wp->w_p_nu)
+			    /* 'number' */
+			    num = (long)lnum;
+			else
+			    /* 'relativenumber', don't use negative numbers */
+			    num = (long)abs((int)get_cursor_rel_lnum(wp,
+								    lnum));
+
 			sprintf((char *)extra, "%*ld ",
-						number_width(wp), (long)lnum);
+						number_width(wp), num);
 			if (wp->w_skipcol > 0)
 			    for (p_extra = extra; *p_extra == ' '; ++p_extra)
 				*p_extra = '-';
@@ -4707,7 +4730,8 @@
 	else
 	    --n_skip;
 
-	/* Only advance the "vcol" when after the 'number' column. */
+	/* Only advance the "vcol" when after the 'number' or 'relativenumber'
+	 * column. */
 	if (draw_state > WL_NR
 #ifdef FEAT_DIFF
 		&& filler_todo <= 0
@@ -9770,8 +9794,8 @@
 
 #if defined(FEAT_LINEBREAK) || defined(PROTO)
 /*
- * Return the width of the 'number' column.
- * Caller may need to check if 'number' is set.
+ * Return the width of the 'number' and 'relativenumber' column.
+ * Caller may need to check if 'number' or 'relativenumber' is set.
  * Otherwise it depends on 'numberwidth' and the line count.
  */
     int
@@ -9781,7 +9805,13 @@
     int		n;
     linenr_T	lnum;
 
-    lnum = wp->w_buffer->b_ml.ml_line_count;
+    if (wp->w_p_nu)
+	/* 'number' */
+	lnum = wp->w_buffer->b_ml.ml_line_count;
+    else
+	/* 'relativenumber' */
+	lnum = wp->w_height;
+
     if (lnum == wp->w_nrwidth_line_count)
 	return wp->w_nrwidth_width;
     wp->w_nrwidth_line_count = lnum;
diff --git a/src/structs.h b/src/structs.h
index d434bfe..72bd96c 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -169,6 +169,8 @@
 #define w_p_list w_onebuf_opt.wo_list	/* 'list' */
     int		wo_nu;
 #define w_p_nu w_onebuf_opt.wo_nu	/* 'number' */
+    int		wo_rnu;
+#define w_p_rnu w_onebuf_opt.wo_rnu	/* 'relativenumber' */
 #ifdef FEAT_LINEBREAK
     long	wo_nuw;
 # define w_p_nuw w_onebuf_opt.wo_nuw	/* 'numberwidth' */
@@ -1907,7 +1909,8 @@
 				       recomputed */
 #endif
 #ifdef FEAT_LINEBREAK
-    int		w_nrwidth;	    /* width of 'number' column being used */
+    int		w_nrwidth;	    /* width of 'number' and 'relativenumber'
+				       column being used */
 #endif
 
     /*