diff --git a/cmd-display-message.c b/cmd-display-message.c
index baf6fb9d..dfa8312f 100644
--- a/cmd-display-message.c
+++ b/cmd-display-message.c
@@ -30,8 +30,8 @@ int	cmd_display_message_exec(struct cmd *, struct cmd_ctx *);
 
 const struct cmd_entry cmd_display_message_entry = {
 	"display-message", "display",
-	"pt:", 0, 1,
-	"[-p] " CMD_TARGET_CLIENT_USAGE " [message]",
+	"c:pt:", 0, 1,
+	"[-p] [-c target-client] [-t target-pane] [message]",
 	0,
 	NULL,
 	NULL,
@@ -43,18 +43,31 @@ cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
 	struct args		*args = self->args;
 	struct client		*c;
+	struct session		*s;
+	struct winlink		*wl;
+	struct window_pane	*wp;
 	const char		*template;
 	char			*msg;
 
-	if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
+	if ((c = cmd_find_client(ctx, args_get(args, 'c'))) == NULL)
 		return (-1);
 
+	if (args_has(args, 't') != NULL) {
+		wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp);
+		if (wl == NULL)
+			return (-1);
+	} else {
+		s = NULL;
+		wl = NULL;
+		wp = NULL;
+	}
+
 	if (args->argc == 0)
 		template = "[#S] #I:#W, current pane #P - (%H:%M %d-%b-%y)";
 	else
 		template = args->argv[0];
 
-	msg = status_replace(c, NULL, template, time(NULL), 0);
+	msg = status_replace(c, s, wl, wp, template, time(NULL), 0);
 	if (args_has(self->args, 'p'))
 		ctx->print(ctx, "%s", msg);
 	else
diff --git a/cmd-pipe-pane.c b/cmd-pipe-pane.c
index d0e47541..1f27e6d9 100644
--- a/cmd-pipe-pane.c
+++ b/cmd-pipe-pane.c
@@ -113,7 +113,8 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
 
 		closefrom(STDERR_FILENO + 1);
 
-		command = status_replace(c, NULL, args->argv[0], time(NULL), 0);
+		command = status_replace(
+		    c, NULL, NULL, NULL, args->argv[0], time(NULL), 0);
 		execl(_PATH_BSHELL, "sh", "-c", command, (char *) NULL);
 		_exit(1);
 	default:
diff --git a/server-client.c b/server-client.c
index 2b67ef5d..66e5caf0 100644
--- a/server-client.c
+++ b/server-client.c
@@ -614,7 +614,7 @@ server_client_set_title(struct client *c)
 
 	template = options_get_string(&s->options, "set-titles-string");
 
-	title = status_replace(c, NULL, template, time(NULL), 1);
+	title = status_replace(c, NULL, NULL, NULL, template, time(NULL), 1);
 	if (c->title == NULL || strcmp(title, c->title) != 0) {
 		if (c->title != NULL)
 			xfree(c->title);
diff --git a/status.c b/status.c
index 60442fce..0a777ce8 100644
--- a/status.c
+++ b/status.c
@@ -38,8 +38,8 @@ void	status_job_free(void *);
 void	status_job_callback(struct job *);
 char   *status_print(
 	    struct client *, struct winlink *, time_t, struct grid_cell *);
-void	status_replace1(struct client *,
-	    struct winlink *, char **, char **, char *, size_t, int);
+void	status_replace1(struct client *, struct session *, struct winlink *,
+	    struct window_pane *, char **, char **, char *, size_t, int);
 void	status_message_callback(int, short, void *);
 
 const char *status_prompt_up_history(u_int *);
@@ -80,8 +80,8 @@ status_redraw_get_left(struct client *c,
 	if (attr != 0)
 		gc->attr = attr;
 
-	left = status_replace(
-	    c, NULL, options_get_string(&s->options, "status-left"), t, 1);
+	left = status_replace(c, NULL,
+	    NULL, NULL, options_get_string(&s->options, "status-left"), t, 1);
 
 	*size = options_get_number(&s->options, "status-left-length");
 	leftlen = screen_write_cstrlen(utf8flag, "%s", left);
@@ -110,8 +110,8 @@ status_redraw_get_right(struct client *c,
 	if (attr != 0)
 		gc->attr = attr;
 
-	right = status_replace(
-	    c, NULL, options_get_string(&s->options, "status-right"), t, 1);
+	right = status_replace(c, NULL,
+	    NULL, NULL, options_get_string(&s->options, "status-right"), t, 1);
 
 	*size = options_get_number(&s->options, "status-right-length");
 	rightlen = screen_write_cstrlen(utf8flag, "%s", right);
@@ -347,16 +347,20 @@ out:
 
 /* Replace a single special sequence (prefixed by #). */
 void
-status_replace1(struct client *c,struct winlink *wl,
-    char **iptr, char **optr, char *out, size_t outsize, int jobsflag)
+status_replace1(struct client *c, struct session *s, struct winlink *wl,
+    struct window_pane *wp, char **iptr, char **optr, char *out,
+    size_t outsize, int jobsflag)
 {
-	struct session *s = c->session;
-	char		ch, tmp[256], *ptr, *endptr, *freeptr;
-	size_t		ptrlen;
-	long		limit;
+	char	ch, tmp[256], *ptr, *endptr, *freeptr;
+	size_t	ptrlen;
+	long	limit;
 
+	if (s == NULL)
+		s = c->session;
 	if (wl == NULL)
 		wl = s->curw;
+	if (wp == NULL)
+		wp = wl->window->active;
 
 	errno = 0;
 	limit = strtol(*iptr, &endptr, 10);
@@ -379,6 +383,10 @@ status_replace1(struct client *c,struct winlink *wl,
 		if ((ptr = status_find_job(c, iptr)) == NULL)
 			return;
 		goto do_replace;
+	case 'D':
+		xsnprintf(tmp, sizeof tmp, "%%%u", wp->id);
+		ptr = tmp;
+		goto do_replace;
 	case 'H':
 		if (gethostname(tmp, sizeof tmp) != 0)
 			fatal("gethostname failed");
@@ -389,15 +397,15 @@ status_replace1(struct client *c,struct winlink *wl,
 		ptr = tmp;
 		goto do_replace;
 	case 'P':
-		xsnprintf(tmp, sizeof tmp, "%u",
-		    window_pane_index(wl->window, wl->window->active));
+		xsnprintf(
+		    tmp, sizeof tmp, "%u", window_pane_index(wl->window, wp));
 		ptr = tmp;
 		goto do_replace;
 	case 'S':
 		ptr = s->name;
 		goto do_replace;
 	case 'T':
-		ptr = wl->window->active->base.title;
+		ptr = wp->base.title;
 		goto do_replace;
 	case 'W':
 		ptr = wl->window->name;
@@ -449,8 +457,8 @@ skip_to:
 
 /* Replace special sequences in fmt. */
 char *
-status_replace(struct client *c,
-    struct winlink *wl, const char *fmt, time_t t, int jobsflag)
+status_replace(struct client *c, struct session *s, struct winlink *wl,
+    struct window_pane *wp, const char *fmt, time_t t, int jobsflag)
 {
 	static char	out[BUFSIZ];
 	char		in[BUFSIZ], ch, *iptr, *optr;
@@ -470,7 +478,8 @@ status_replace(struct client *c,
 			*optr++ = ch;
 			continue;
 		}
-		status_replace1(c, wl, &iptr, &optr, out, sizeof out, jobsflag);
+		status_replace1(
+		    c, s, wl, wp, &iptr, &optr, out, sizeof out, jobsflag);
 	}
 	*optr = '\0';
 
@@ -657,7 +666,7 @@ status_print(
 			gc->attr = attr;
 	}
 
-	text = status_replace(c, wl, fmt, t, 1);
+	text = status_replace(c, NULL, wl, NULL, fmt, t, 1);
 	return (text);
 }
 
diff --git a/tmux.1 b/tmux.1
index 939a4333..d2842374 100644
--- a/tmux.1
+++ b/tmux.1
@@ -2611,7 +2611,8 @@ This command works only from inside
 .Nm .
 .It Xo Ic display-message
 .Op Fl p
-.Op Fl t Ar target-client
+.Op Fl c Ar target-client
+.Op Fl t Ar target-pane
 .Op Ar message
 .Xc
 .D1 (alias: Ic display )
@@ -2625,7 +2626,12 @@ The format of
 .Ar message
 is as for
 .Ic status-left ,
-with the exception that #() are not handled.
+with the exception that #() are not handled; information is taken from
+.Ar target-pane
+if
+.Fl t
+is given, otherwise the active pane for the session attached to
+.Ar target-client .
 .El
 .Sh BUFFERS
 .Nm
diff --git a/tmux.h b/tmux.h
index 5d271a57..b3e9868f 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1666,8 +1666,8 @@ RB_PROTOTYPE(status_out_tree, status_out, entry, status_out_cmp);
 void	 status_free_jobs(struct status_out_tree *);
 void	 status_update_jobs(struct client *);
 int	 status_redraw(struct client *);
-char	*status_replace(
-	     struct client *, struct winlink *, const char *, time_t, int);
+char	*status_replace(struct client *, struct session *,
+	     struct winlink *, struct window_pane *, const char *, time_t, int);
 void printflike2 status_message_set(struct client *, const char *, ...);
 void	 status_message_clear(struct client *);
 int	 status_message_redraw(struct client *);