diff --git a/src/console.c b/src/console.c
index 025bc1c19f2068812cf14ade4740eaeeaa3587c7..44819fb4f10b8dcc839818fdd830b0d4eb5f7fc4 100644
--- a/src/console.c
+++ b/src/console.c
@@ -91,11 +91,13 @@ static char inputlines[32][CON_MAXPROMPTCHARS]; // hold last 32 prompt lines
 static INT32 inputline;    // current input line number
 static INT32 inputhist;    // line number of history input line to restore
 static size_t input_cx;  // position in current input line
+static INT32 input_selection; // selection border in current input line, -1 if no selection
 
 // protos.
 static void CON_InputInit(void);
 static void CON_RecalcSize(void);
 
+static void CON_DeleteSelectedText(void);
 static void CONS_hudlines_Change(void);
 static void CON_DrawBackpic(patch_t *pic, INT32 startx, INT32 destwidth);
 //static void CON_DrawBackpic2(pic_t *pic, INT32 startx, INT32 destwidth);
@@ -394,6 +396,7 @@ static void CON_InputInit(void)
 		inputlines[i][0] = CON_PROMPTCHAR;
 	inputline = 0;
 	input_cx = 1;
+	input_selection = -1;
 }
 
 //======================================================================
@@ -618,6 +621,25 @@ void CON_Ticker(void)
 	}
 }
 
+// Deletes selected text, assuming there is, and resets selection.
+// Also sets the cursor to the correct position.
+//
+static void CON_DeleteSelectedText(void)
+{
+	UINT32 i, j;
+	char *line = inputlines[inputline];
+	size_t selstart = min(input_cx, input_selection);
+	size_t selend = max(input_cx, input_selection);
+
+	for (i = selstart, j = selend; line[j]; ++i, ++j)
+		line[i] = line[j];
+	while (line[i])
+		line[i++] = 0;
+
+	input_cx = selstart;
+	input_selection = -1;
+}
+
 // Handles console key input
 //
 boolean CON_Responder(event_t *ev)
@@ -704,6 +726,9 @@ boolean CON_Responder(event_t *ev)
 	// command completion forward (tab) and backward (shift-tab)
 	if (key == KEY_TAB)
 	{
+		input_cx = strlen(inputlines[inputline]); // make sure the cursor is at the end of the string, in case we were inserting
+		input_selection = -1; // make sure there is no text selected, it would look odd
+
 		// show all cvars/commands that match what we have inputted
 		if (ctrldown)
 		{
@@ -839,21 +864,51 @@ boolean CON_Responder(event_t *ev)
 		return true;
 	}
 
-	if (key == KEY_HOME) // oldest text in buffer
+	if (key == KEY_HOME)
 	{
-		con_scrollup = (con_totallines-((con_curlines-16)>>3));
+		if (shiftdown)
+		{
+			if (input_selection == -1)
+				input_selection = input_cx;
+		}
+		else
+			input_selection = -1;
+
+		if (ctrldown)
+			con_scrollup = (con_totallines-((con_curlines-16)>>3)); // oldest text in buffer
+		else
+			input_cx = 1;
+
+		if (input_cx == input_selection)
+			input_selection = -1;
+
 		return true;
 	}
-	else if (key == KEY_END) // most recent text in buffer
+	else if (key == KEY_END)
 	{
-		con_scrollup = 0;
+		if (shiftdown)
+		{
+			if (input_selection == -1)
+				input_selection = input_cx;
+		}
+		else
+			input_selection = -1;
+
+		if (ctrldown)
+			con_scrollup = 0; // most recent text in buffer
+		else
+			input_cx = strlen(inputlines[inputline]);
+
+		if (input_cx == input_selection)
+			input_selection = -1;
+
 		return true;
 	}
 
 	// command enter
 	if (key == KEY_ENTER)
 	{
-		if (input_cx < 2)
+		if (strlen(inputlines[inputline]) < 2)
 			return true;
 
 		// push the command
@@ -868,18 +923,107 @@ boolean CON_Responder(event_t *ev)
 		memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS);
 		inputlines[inputline][0] = CON_PROMPTCHAR;
 		input_cx = 1;
+		input_selection = -1;
 
 		return true;
 	}
 
-	// backspace command prompt
+	// backspace command prompt or delete selected text
 	if (key == KEY_BACKSPACE)
 	{
-		if (input_cx > 1)
+		if (input_selection == -1)
+		{
+			if (input_cx > 1)
+			{
+				UINT32 i, j;
+				char *line = inputlines[inputline];
+
+				for (i = input_cx - 1, j = input_cx; line[j]; ++i, ++j)
+					line[i] = line[j];
+				line[i] = 0;
+				input_cx--;
+			}
+		}
+		else
+			CON_DeleteSelectedText();
+		return true;
+	}
+
+	// delete character under cursor or selected text
+	if (key == KEY_DEL)
+	{
+		if (input_selection == -1)
 		{
+			UINT32 i, j;
+			char *line = inputlines[inputline];
+
+			for (i = input_cx, j = input_cx + 1; line[j]; ++i, ++j)
+				line[i] = line[j];
+			line[i] = 0;
+		}
+		else
+			CON_DeleteSelectedText();
+
+		return true;
+	}
+
+	if (key == KEY_LEFTARROW)
+	{
+		if (shiftdown)
+		{
+			if (input_selection == -1)
+				input_selection = input_cx;
+		}
+		else
+			input_selection = -1;
+
+		// move cursor to previous word
+		if (ctrldown)
+		{
+			char *line = inputlines[inputline];
+
+			while (input_cx > 1 && line[input_cx - 1] == ' ')
+				input_cx--;
+			while (input_cx > 1 && line[input_cx - 1] != ' ')
+				input_cx--;
+		}
+		// move cursor left
+		else if (input_cx > 1)
 			input_cx--;
-			inputlines[inputline][input_cx] = 0;
+
+		if (input_cx == input_selection)
+			input_selection = -1;
+
+		return true;
+	}
+
+	if (key == KEY_RIGHTARROW)
+	{
+		if (shiftdown)
+		{
+			if (input_selection == -1)
+				input_selection = input_cx;
+		}
+		else
+			input_selection = -1;
+
+		// move cursor to next word
+		if (ctrldown)
+		{
+			char *line = inputlines[inputline];
+
+			while (line[input_cx] && line[input_cx] != ' ')
+				input_cx++;
+			while (line[input_cx] && line[input_cx] == ' ')
+				input_cx++;
 		}
+		// move cursor right
+		else if (inputlines[inputline][input_cx])
+			input_cx++;
+
+		if (input_cx == input_selection)
+			input_selection = -1;
+
 		return true;
 	}
 
@@ -950,13 +1094,21 @@ boolean CON_Responder(event_t *ev)
 		return false;
 
 	// add key to cmd line here
-	if (input_cx < CON_MAXPROMPTCHARS)
+	if (strlen(inputlines[inputline]) < CON_MAXPROMPTCHARS - 1)
 	{
+		INT32 i, j;
+		char *line = inputlines[inputline];
+
 		if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers
 			key = key + 'a' - 'A';
 
-		inputlines[inputline][input_cx] = (char)key;
-		inputlines[inputline][input_cx + 1] = 0;
+		if (input_selection != -1)
+			CON_DeleteSelectedText();
+
+		for (i = strlen(line), j = i + 1; j > (INT32)input_cx; --i, --j)
+			line[j] = line[i];
+
+		line[input_cx] = (char)key;
 		input_cx++;
 	}
 
@@ -1246,6 +1398,7 @@ static void CON_DrawInput(void)
 	size_t c;
 	INT32 x, y;
 	INT32 charwidth = (INT32)con_scalefactor << 3;
+	INT32 f = cv_constextsize.value | V_NOSCALESTART;
 
 	// input line scrolls left if it gets too long
 	p = inputlines[inputline];
@@ -1254,14 +1407,44 @@ static void CON_DrawInput(void)
 
 	y = con_curlines - 12 * con_scalefactor;
 
-	for (c = 0, x = charwidth; c < con_width-11; c++, x += charwidth)
-		V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
+	if (input_selection == -1)
+	{
+		for (c = 0, x = charwidth; c < con_width-11; c++, x += charwidth)
+			V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value);
+	}
+	else
+	{
+		size_t selstart = min(input_cx, input_selection);
+		size_t selend = max(input_cx, input_selection);
+
+		for (c = 0, x = charwidth; c < selstart && c < con_width-11; c++, x += charwidth)
+			V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value);
+
+		f |= V_YELLOWMAP;
+		for (; c < selend && c < con_width-11; c++, x += charwidth)
+			V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value);
+		f &= ~V_YELLOWMAP;
+
+		for (; c < con_width-11; c++, x += charwidth)
+			V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value);
+	}
+	//for (c = 0, x = charwidth; c < con_width-11; c++, x += charwidth)
+		//V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
 
 	// draw the blinking cursor
 	//
 	x = ((input_cx >= con_width-11) ? (INT32)(con_width-11) : (INT32)((input_cx + 1)) * charwidth);
 	if (con_tick < 4)
-		V_DrawCharacter(x, y, '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
+	{
+		if (inputlines[inputline][input_cx])
+			//V_DrawCharacter(x - 2 * con_scalefactor, y, '|' | f, !cv_allcaps.value);
+			V_DrawCharacter(x, y + 2 * con_scalefactor, '_' | f, !cv_allcaps.value);
+		else
+			V_DrawCharacter(x, y, '_' | f, !cv_allcaps.value);
+	}
+	/*x = ((input_cx >= con_width-11) ? (INT32)(con_width-11) : (INT32)((input_cx + 1)) * charwidth);
+	if (con_tick < 4)
+		V_DrawCharacter(x, y, '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);*/
 }
 
 // draw the last lines of console text to the top of the screen
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index ec747305ea5b1cac5201ef425bd0d2f520b8c0c0..9f1cea13fe185ee7cbfb6ab35868dbffbdafcce6 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -73,6 +73,9 @@ patch_t *cred_font[CRED_FONTSIZE];
 static player_t *plr;
 boolean chat_on; // entering a chat message?
 static char w_chat[HU_MAXMSGLEN];
+static size_t chat_pos; // position of the cursor in the chat
+static INT32 chat_selection; // selection border in current input line, -1 if no selection
+static boolean teamtalk = false;
 static boolean headsupactive = false;
 boolean hu_showscores; // draw rankings
 static char hu_tick;
@@ -106,6 +109,7 @@ static patch_t *crosshair[HU_CROSSHAIRS]; // 3 precached crosshair graphics
 static void HU_DrawRankings(void);
 static void HU_DrawCoopOverlay(void);
 static void HU_DrawNetplayCoopOverlay(void);
+static void HU_DeleteSelectedText(void);
 
 //======================================================================
 //                 KEYBOARD LAYOUTS FOR ENTERING TEXT
@@ -621,93 +625,47 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
 }
 #endif
 
-// Handles key input and string input
+// Deletes selected text, assuming there is, and resets selection.
+// Also sets the cursor to the correct position.
 //
-static inline boolean HU_keyInChatString(char *s, char ch)
-{
-	size_t l;
-
-	if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART])
-	  || ch == ' ') // Allow spaces, of course
-	{
-		l = strlen(s);
-		if (l < HU_MAXMSGLEN - 1)
-		{
-			s[l++] = ch;
-			s[l]=0;
-			return true;
-		}
-		return false;
-	}
-	else if (ch == KEY_BACKSPACE)
-	{
-		l = strlen(s);
-		if (l)
-			s[--l] = 0;
-		else
-			return false;
-	}
-	else if (ch != KEY_ENTER)
-		return false; // did not eat key
-
-	return true; // ate the key
-}
-
-//
-//
-void HU_Ticker(void)
+static void HU_DeleteSelectedText(void)
 {
-	if (dedicated)
-		return;
+	UINT32 i, j;
+	size_t selstart = min(chat_pos, chat_selection);
+	size_t selend = max(chat_pos, chat_selection);
 
-	hu_tick++;
-	hu_tick &= 7; // currently only to blink chat input cursor
+	for (i = selstart, j = selend; w_chat[j]; ++i, ++j)
+		w_chat[i] = w_chat[j];
+	while (w_chat[i])
+		w_chat[i++] = 0;
 
-	if (PLAYER1INPUTDOWN(gc_scores))
-		hu_showscores = !chat_on;
-	else
-		hu_showscores = false;
+	chat_pos = selstart;
+	chat_selection = -1;
 }
 
-#define QUEUESIZE 256
-
-static boolean teamtalk = false;
-static char chatchars[QUEUESIZE];
-static INT32 head = 0, tail = 0;
-
-//
-// HU_dequeueChatChar
+// Handles key input and string input
 //
-char HU_dequeueChatChar(void)
+static inline void HU_keyInChatString(char *s, UINT32 key, boolean shiftdown, boolean ctrldown)
 {
-	char c;
-
-	if (head != tail)
+	switch (key)
 	{
-		c = chatchars[tail];
-		tail = (tail + 1) & (QUEUESIZE-1);
-	}
-	else
-		c = 0;
-
-	return c;
-}
-
-//
-//
-static void HU_queueChatChar(char c)
-{
-	// send automaticly the message (no more chat char)
-	if (c == KEY_ENTER)
+	case KEY_ESCAPE:
+		chat_on = false;
+		break;
+	case KEY_ENTER:
 	{
+		// send automatically the message (no more chat char)
 		char buf[2+256];
 		size_t ci = 2;
+		char *cp = w_chat;
 
-		do {
-			c = HU_dequeueChatChar();
-			if (!c || (c >= ' ' && !(c & 0x80))) // copy printable characters and terminating '\0' only.
-				buf[ci++]=c;
-		} while (c);
+		while (*cp)
+		{
+			if (*cp >= ' ' && !(*cp & 0x80))
+				buf[ci++] = *cp;
+			cp++;
+		}
+		buf[ci] = 0;
 
 		// last minute mute check
 		if (cv_mute.value && !(server || adminplayer == consoleplayer))
@@ -716,7 +674,7 @@ static void HU_queueChatChar(char c)
 			return;
 		}
 
-		if (ci > 3) // don't send target+flags+empty message.
+		if (ci > 2) // don't send target+flags+empty message.
 		{
 			if (teamtalk)
 				buf[0] = -1; // target
@@ -725,30 +683,146 @@ static void HU_queueChatChar(char c)
 			buf[1] = 0; // flags
 			SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1);
 		}
-		return;
+
+		chat_on = false;
+		break;
 	}
+	// cursor moving
+	case KEY_LEFTARROW:
+	case KEY_RIGHTARROW:
+	case KEY_HOME:
+	case KEY_END:
+		if (shiftdown)
+		{
+			if (chat_selection == -1)
+				chat_selection = chat_pos;
+		}
+		else
+			chat_selection = -1;
 
-	if (((head + 1) & (QUEUESIZE-1)) == tail)
-		CONS_Printf(M_GetText("[Message unsent]\n")); // message not sent
-	else
-	{
-		if (c == KEY_BACKSPACE)
+		switch (key)
+		{
+		case KEY_LEFTARROW:
+			// move cursor to previous word
+			if (ctrldown)
+			{
+				while (chat_pos > 0 && w_chat[chat_pos - 1] == ' ')
+					chat_pos--;
+				while (chat_pos > 0 && w_chat[chat_pos - 1] != ' ')
+					chat_pos--;
+			}
+			// move cursor left
+			else if (chat_pos > 0)
+				chat_pos--;
+			break;
+		case KEY_RIGHTARROW:
+			// move cursor to next word
+			if (ctrldown)
+			{
+				while (w_chat[chat_pos] && w_chat[chat_pos] != ' ')
+					chat_pos++;
+				while (w_chat[chat_pos] && w_chat[chat_pos] == ' ')
+					chat_pos++;
+			}
+			// move cursor right
+			else if (w_chat[chat_pos])
+				chat_pos++;
+			break;
+		case KEY_HOME:
+			chat_pos = 0;
+			break;
+		case KEY_END:
+			chat_pos = strlen(w_chat);
+		}
+
+		if (chat_pos == chat_selection)
+			chat_selection = -1;
+		break;
+	// backspace or delete selected text
+	case KEY_BACKSPACE:
+		if (chat_selection == -1)
 		{
-			if (tail != head)
-				head = (head - 1) & (QUEUESIZE-1);
+			if (chat_pos > 0)
+			{
+				UINT32 i, j;
+				for (i = chat_pos - 1, j = chat_pos; w_chat[j]; ++i, ++j)
+					w_chat[i] = w_chat[j];
+				w_chat[i] = 0;
+				chat_pos--;
+			}
 		}
 		else
+			HU_DeleteSelectedText();
+		break;
+	// delete character under cursor
+	case KEY_DEL:
+		if (chat_selection == -1)
 		{
-			chatchars[head] = c;
-			head = (head + 1) & (QUEUESIZE-1);
+			UINT32 i, j;
+
+			for (i = chat_pos, j = chat_pos + 1; w_chat[j]; ++i, ++j)
+				w_chat[i] = w_chat[j];
+			w_chat[i] = 0;
+		}
+		else
+			HU_DeleteSelectedText();
+		break;
+	default:
+		// allow people to use keypad in chat
+		if (key >= KEY_KEYPAD7 && key <= KEY_KPADDEL)
+		{
+			XBOXSTATIC char keypad_translation[] = {'7','8','9','-',
+													'4','5','6','+',
+													'1','2','3',
+													'0','.'};
+
+			key = keypad_translation[key - KEY_KEYPAD7];
+		}
+		else if (key == KEY_KPADSLASH)
+			key = '/';
+
+		// use console translations
+		if (shiftdown)
+			key = shiftxform[key];
+
+		if ((key >= HU_FONTSTART && key <= HU_FONTEND && hu_font[key-HU_FONTSTART])
+		  || key == ' ') // Allow spaces, of course
+		{
+			if (strlen(w_chat) < HU_MAXMSGLEN - 1)
+			{
+				UINT32 i, j;
+
+				if (chat_selection != -1)
+					HU_DeleteSelectedText();
+
+				for (i = strlen(w_chat), j = i + 1; j > chat_pos; --i, --j)
+					w_chat[j] = w_chat[i];
+				w_chat[chat_pos] = (char)key;
+				chat_pos++;
+			}
 		}
 	}
 }
 
+//
+//
+void HU_Ticker(void)
+{
+	if (dedicated)
+		return;
+
+	hu_tick++;
+	hu_tick &= 7; // currently only to blink chat input cursor
+
+	if (PLAYER1INPUTDOWN(gc_scores))
+		hu_showscores = !chat_on;
+	else
+		hu_showscores = false;
+}
+
+// REMOVE? Now this has become pretty useless IMO
 void HU_clearChatChars(void)
 {
-	while (tail != head)
-		HU_queueChatChar(KEY_BACKSPACE);
 	chat_on = false;
 }
 
@@ -758,13 +832,19 @@ void HU_clearChatChars(void)
 boolean HU_Responder(event_t *ev)
 {
 	static boolean shiftdown = false;
-	UINT8 c;
+	static boolean ctrldown = false;
+	INT32 key = ev->data1; // only valid if ev->type is a key event
 
-	if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT)
+	if (key == KEY_LSHIFT || key == KEY_RSHIFT)
 	{
 		shiftdown = (ev->type == ev_keydown);
 		return chat_on;
 	}
+	else if (key == KEY_LCTRL || key == KEY_RCTRL)
+	{
+		ctrldown = (ev->type == ev_keydown);
+		return chat_on;
+	}
 
 	if (ev->type != ev_keydown)
 		return false;
@@ -774,42 +854,36 @@ boolean HU_Responder(event_t *ev)
 	if (!chat_on)
 	{
 		// enter chat mode
-		if ((ev->data1 == gamecontrol[gc_talkkey][0] || ev->data1 == gamecontrol[gc_talkkey][1])
+		if ((key == gamecontrol[gc_talkkey][0] || key == gamecontrol[gc_talkkey][1])
 			&& netgame && (!cv_mute.value || server || (adminplayer == consoleplayer)))
 		{
-			if (cv_mute.value && !(server || adminplayer == consoleplayer))
-				return false;
+			// we already checked for this two lines before...
+			//if (cv_mute.value && !(server || adminplayer == consoleplayer))
+				//return false;
 			chat_on = true;
 			w_chat[0] = 0;
+			chat_pos = 0;
+			chat_selection = -1;
 			teamtalk = false;
 			return true;
 		}
-		if ((ev->data1 == gamecontrol[gc_teamkey][0] || ev->data1 == gamecontrol[gc_teamkey][1])
+		if ((key == gamecontrol[gc_teamkey][0] || key == gamecontrol[gc_teamkey][1])
 			&& netgame && (!cv_mute.value || server || (adminplayer == consoleplayer)))
 		{
-			if (cv_mute.value && !(server || adminplayer == consoleplayer))
-				return false;
+			// we already checked for this two lines before...
+			//if (cv_mute.value && !(server || adminplayer == consoleplayer))
+				//return false;
 			chat_on = true;
 			w_chat[0] = 0;
+			chat_pos = 0;
+			chat_selection = -1;
 			teamtalk = true;
 			return true;
 		}
 	}
 	else // if chat_on
 	{
-		c = (UINT8)ev->data1;
-
-		// use console translations
-		if (shiftdown)
-			c = shiftxform[c];
-
-		if (HU_keyInChatString(w_chat,c))
-			HU_queueChatChar(c);
-		if (c == KEY_ENTER)
-			chat_on = false;
-		else if (c == KEY_ESCAPE)
-			chat_on = false;
-
+		HU_keyInChatString(w_chat, key, shiftdown, ctrldown);
 		return true;
 	}
 	return false;
@@ -826,7 +900,7 @@ boolean HU_Responder(event_t *ev)
 //
 static void HU_DrawChat(void)
 {
-	INT32 t = 0, c = 0, y = HU_INPUTY;
+	INT32 t = 0, f = 0, c = 0, y = HU_INPUTY;
 	size_t i = 0;
 	const char *ntalk = "Say: ", *ttalk = "Say-Team: ";
 	const char *talk = ntalk;
@@ -844,6 +918,8 @@ static void HU_DrawChat(void)
 #endif
 	}
 
+	f = cv_constextsize.value | V_NOSCALESTART;
+
 	while (talk[i])
 	{
 		if (talk[i] < HU_FONTSTART)
@@ -854,36 +930,123 @@ static void HU_DrawChat(void)
 		else
 		{
 			//charwidth = SHORT(hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor;
-			V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
+			V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | f, !cv_allcaps.value);
 		}
 		c += charwidth;
 	}
 
+	f |= t;
 	i = 0;
-	while (w_chat[i])
+	if (chat_selection == -1)
 	{
-		//Hurdler: isn't it better like that?
-		if (w_chat[i] < HU_FONTSTART)
+		while (w_chat[i])
 		{
-			++i;
-			//charwidth = 4 * con_scalefactor;
+			//Hurdler: isn't it better like that?
+			if (w_chat[i] < HU_FONTSTART)
+			{
+				++i;
+				//charwidth = 4 * con_scalefactor;
+			}
+			else
+			{
+				//charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
+				V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value);
+			}
+
+			c += charwidth;
+			if (c >= vid.width)
+			{
+				c = 0;
+				y += charheight;
+			}
 		}
-		else
+	}
+	else
+	{
+		size_t selstart = min(chat_pos, chat_selection);
+		size_t selend = max(chat_pos, chat_selection);
+
+		while (i < selstart)
 		{
-			//charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
-			V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, !cv_allcaps.value);
+			//Hurdler: isn't it better like that?
+			if (w_chat[i] < HU_FONTSTART)
+			{
+				++i;
+				//charwidth = 4 * con_scalefactor;
+			}
+			else
+			{
+				//charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
+				V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value);
+			}
+
+			c += charwidth;
+			if (c >= vid.width)
+			{
+				c = 0;
+				y += charheight;
+			}
 		}
 
-		c += charwidth;
-		if (c >= vid.width)
+		f &= ~t;
+		f |= V_YELLOWMAP;
+		while (i < selend)
+		{
+			//Hurdler: isn't it better like that?
+			if (w_chat[i] < HU_FONTSTART)
+			{
+				++i;
+				//charwidth = 4 * con_scalefactor;
+			}
+			else
+			{
+				//charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
+				V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value);
+			}
+
+			c += charwidth;
+			if (c >= vid.width)
+			{
+				c = 0;
+				y += charheight;
+			}
+		}
+		f &= ~V_YELLOWMAP;
+		f |= t;
+
+		while (w_chat[i])
 		{
-			c = 0;
-			y += charheight;
+			//Hurdler: isn't it better like that?
+			if (w_chat[i] < HU_FONTSTART)
+			{
+				++i;
+				//charwidth = 4 * con_scalefactor;
+			}
+			else
+			{
+				//charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
+				V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value);
+			}
+
+			c += charwidth;
+			if (c >= vid.width)
+			{
+				c = 0;
+				y += charheight;
+			}
 		}
 	}
 
 	if (hu_tick < 4)
-		V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, !cv_allcaps.value);
+	{
+		if (w_chat[chat_pos])
+		{
+			i = (strlen(talk) + chat_pos) * charwidth;
+			c = i % vid.width;
+			y = HU_INPUTY + i / vid.width * charheight + 2 * con_scalefactor;
+		}
+		V_DrawCharacter(HU_INPUTX + c, y, '_' | f, !cv_allcaps.value);
+	}
 }
 
 
diff --git a/src/hu_stuff.h b/src/hu_stuff.h
index 7b22f33f189b5a602ca043862b21ca2e8cc0d678..5dca10981735ce70d4518f1fee2e62f091782054 100644
--- a/src/hu_stuff.h
+++ b/src/hu_stuff.h
@@ -93,7 +93,6 @@ boolean HU_Responder(event_t *ev);
 
 void HU_Ticker(void);
 void HU_Drawer(void);
-char HU_dequeueChatChar(void);
 void HU_Erase(void);
 void HU_clearChatChars(void);
 void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer);