diff --git a/src/comm.c b/src/comm.c
index 0744ff0..05d8452 100644
--- a/src/comm.c
+++ b/src/comm.c
@@ -130,6 +130,7 @@ struct comm comms[RC_LAST + 1] =
   { "info",		CAN_QUERY|NEED_LAYER|ARGS_0,	{NULL} },
   { "kanji",		NEED_FORE|ARGS_12,		{NULL} },
   { "kill",		NEED_FORE|ARGS_0,		{NULL} },
+  { "labels",		ARGS_1,				{NULL} },
   { "lastmsg",		CAN_QUERY|NEED_DISPLAY|ARGS_0,	{NULL} },
   { "layout",           ARGS_1|ARGS_ORMORE,		{NULL} },
   { "license",		NEED_LAYER|ARGS_0,		{NULL} },
diff --git a/src/process.c b/src/process.c
index c20bbfd..aacd68f 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1054,6 +1055,24 @@ void DoAction(struct action *act, int key)
 		ParseSwitch(act, &b);
 		LogToggle(b);
 		break;
+	case RC_LABELS:
+		if (*args) {
+			if (args[0]) {
+				free(labelstring);
+				labelstring = SaveStr(args[0]);
+				num_labels = strlen(labelstring);
+				/* go through windows, update labels */
+				Window *window;
+				for (window = windows; window; window = window->w_next) {
+					if(window->w_label)
+						free(window->w_label);
+					window->w_label = GenerateLabel(window->w_number);
+				}
+			}
+			if (msgok)
+				OutputMsg(0, "labels: %s", labelstring);
+		}
+		break;
 	case RC_SUSPEND:
 		Detach(D_STOP);
 		break;
@@ -3417,6 +3436,9 @@ void DoAction(struct action *act, int key)
 				bzero(wtab, n * sizeof(Window *));
 			}
 			maxwin = n;
+			max_label_len = 0;
+			while(n /= 10)
+				max_label_len++;
 		}
 		break;
 	case RC_BACKTICK:
@@ -4148,12 +4170,18 @@ static Window *WindowByName(char *s)
 {
 	Window *window;
 
-	for (window = windows; window; window = window->w_next)
+	for (window = windows; window; window = window->w_next) {
+		if (!strcmp(window->w_label, s))
+			return window;
 		if (!strcmp(window->w_title, s))
 			return window;
-	for (window = windows; window; window = window->w_next)
+	}
+	for (window = windows; window; window = window->w_next) {
+		if (!strncmp(window->w_label, s, strlen(s)))
+			return window;
 		if (!strncmp(window->w_title, s, strlen(s)))
 			return window;
+	}
 	return 0;
 }
 
@@ -4515,7 +4543,7 @@ char *AddWindows(WinMsgBufContext *wmbc, int len, int flags, int where)
 		}
 		if (rend != -1)
 			AddWinMsgRend(wmbc->buf, s, rend);
-		sprintf(s, "%d", p->w_number);
+		sprintf(s, "%s", p->w_label);
 		s += strlen(s);
 		if (!(flags & 2)) {
 			s = AddWindowFlags(s, len, p);
diff --git a/src/screen.c b/src/screen.c
index bc2a538..28998a9 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -111,6 +112,8 @@ char *ActivityString;
 char *BufferFile;
 char *PowDetachString;
 char *hstatusstring;
+char *labelstring;
+int num_labels;
 char *captionstring;
 char *timestring;
 char *wliststr;
@@ -142,6 +145,7 @@ char *screenencodings;
 bool cjkwidth;
 
 uint16_t maxwin;
+int max_label_len;
 
 Layer *flayer;
 Window *fore;
@@ -244,6 +248,8 @@ int main(int argc, char **argv)
 	logtstamp_string = SaveStr("-- %n:%t -- time-stamp -- %M/%d/%y %c:%s --\n");
 	hstatusstring = SaveStr("%h");
 	captionstring = SaveStr("%4n %t");
+	labelstring = SaveStr("");
+	num_labels = strlen(labelstring);
 	timestring = SaveStr("%c:%s %M %d %H%? %l%?");
 	wlisttit = SaveStr(" Num Name%=Flags");
 	wliststr = SaveStr("%4n %t%=%f");
@@ -1792,4 +1798,3 @@ static int ParseEscape(char *p)
 	}
 	return 0;
 }
-
diff --git a/src/screen.h b/src/screen.h
index e3ff58b..0194286 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -246,6 +246,8 @@ extern char *captionstring;
 extern char *hardcopydir;
 extern char *home;
 extern char *hstatusstring;
+extern char *labelstring;
+extern int num_labels;
 extern char *logtstamp_string;
 extern char *multi;
 extern char *preselect;
@@ -285,6 +287,7 @@ extern int force_vt;
 extern int log_flush;
 extern int logtstamp_after;
 extern uint16_t maxwin;
+extern int max_label_len;
 extern unsigned int multi_uid;
 extern int multiattach;
 extern int nversion;
diff --git a/src/window.c b/src/window.c
index 072c098..935e861 100644
--- a/src/window.c
+++ b/src/window.c
@@ -452,6 +454,7 @@ int MakeWindow(struct NewWindow *newwin)
 		p->w_term = SaveStr(nwin.term);
 
 	p->w_number = n;
+	p->w_label = GenerateLabel(n);
 	p->w_group = 0;
 	if (fore && fore->w_type == W_TYPE_GROUP)
 		p->w_group = fore;
@@ -765,6 +768,8 @@ void FreeWindow(Window *window)
 		free(window->w_dir);
 	if (window->w_term)
 		free(window->w_term);
+	if (window->w_label)
+		free(window->w_label);
 	for (display = displays; display; display = display->d_next) {
 		if (display->d_other == window)
 			display->d_other = display->d_fore && display->d_fore->w_next != window ? display->d_fore->w_next : window->w_next;
@@ -1747,6 +1752,15 @@ int SwapWindows(int old, int dest)
 	wtab[old] = p;
 	if (p)
 		p->w_number = old;
+	/* if dest window exists, swap labels, otherwise generate a new label */
+	if(p) {
+		char *label_tmp = win_old->w_label;
+		win_old->w_label = p->w_label;
+		p->w_label = label_tmp;
+	} else {
+		free(win_old->w_label);
+		win_old->w_label = GenerateLabel(win_old->w_number);
+	}
 	/* exchange the acls for these windows. */
 #ifdef UTMPOK
 	/* exchange the utmp-slots for these windows */
@@ -1839,3 +1853,15 @@ void WindowDied(Window *p, int wstat, int wstat_valid)
 	CarefulUtmp();
 #endif
 }
+
+char *GenerateLabel(int n) {
+	char *label;
+	if(n >= num_labels) {
+		label = (char *) malloc(sizeof(char) * (max_label_len + 1));
+		snprintf(label, max_label_len, "%d", n);
+	} else {
+		label = (char *) malloc(sizeof(char) * 2);
+		snprintf(label, 2, "%c", labelstring[n]);
+	}
+	return label;
+}
diff --git a/src/window.h b/src/window.h
index 530c5d9..272e54e 100644
--- a/src/window.h
+++ b/src/window.h
@@ -143,6 +143,7 @@ struct Window {
 	Display *w_pdisplay;		/* display for printer relay */
 	Display *w_lastdisp;		/* where the last input was made */
 	uint16_t w_number;		/* window number */
+	char  *w_label;		/* label of the window */
 	Event w_readev;
 	Event w_writeev;
 	Event w_silenceev;		/* silence event */
@@ -325,6 +326,7 @@ int   ObtainAutoWritelock (Display *, Window *);
 void  CloseDevice (Window *);
 void  zmodem_abort(Window *, Display *);
 void  WindowDied (Window *, int, int);
+char *GenerateLabel(int);
 #ifndef HAVE_EXECVPE
 #include <unistd.h>
 #endif
diff --git a/src/winmsg.c b/src/winmsg.c
index 41dfea5..d659113 100644
--- a/src/winmsg.c
+++ b/src/winmsg.c
@@ -446,6 +446,15 @@ winmsg_esc_ex(WinTitle, Window *win)
 		wmc_set(cond);
 }
 
+winmsg_esc_ex(WinLabel, Window *win)
+{
+	if (!win)
+		return;
+
+	if (*wmbc_strcpy(wmbc, win->w_label))
+		wmc_set(cond);
+}
+
 winmsg_esc_ex(Cond, int *condrend)
 {
 	if (wmc_is_active(cond)) {
@@ -635,7 +644,7 @@ char *MakeWinMsgEv(WinMsgBuf *winmsg, char *str, Window *win,
 			WinMsgDoEscEx(WinSize, win);
 			break;
 		case WINESC_WIN_NUM:
-			WinMsgDoEscEx(WinNum, win);
+			WinMsgDoEscEx(WinLabel, win);
 			break;
 		case WINESC_WIN_LOGNAME:
 			WinMsgDoEscEx(WinLogName, win);
