diff --git a/docs/rh-log.txt b/docs/rh-log.txt
index c03282fdd..d2ea6e2fd 100644
--- a/docs/rh-log.txt
+++ b/docs/rh-log.txt
@@ -1,4 +1,8 @@
-August 12, 2009  (Changes by Graf Zahl)
+August 28, 2009
+- Fixed: genStringEnter mode acted on key up events rather than key repeat
+  events.
+
+August 12, 2009  (Changes by Graf Zahl)
 - Fixed: paletted texture composition with part translucent patches
   did not work.
 - Fixed: A_SorcOffense2 depended on args being bytes and overflowing.
@@ -29,7 +33,8 @@ August 9, 2009  (Changes by Graf Zahl)
 
 August 8, 2009  (Changes by Graf Zahl)
 - replaced all code that changed a sector's light level with a setter function.
-- Fixed: The FeatureFlags array in the CPUInfo struct was not mapped to the flags properly.
+- Fixed: The FeatureFlags array in the CPUInfo struct was not mapped to the
+  flags properly.
 
 August 8, 2009
 - Changed the return value of SetActivatorToTarget to match the description
diff --git a/src/m_menu.cpp b/src/m_menu.cpp
index 97335382d..d16a964dd 100644
--- a/src/m_menu.cpp
+++ b/src/m_menu.cpp
@@ -2874,45 +2874,49 @@ bool M_Responder (event_t *ev)
 				}
 				return true;
 			}
-			if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyUp)
+			ch = ev->data1;
+			if ((ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) &&
+				ch == '\b')
 			{
-				ch = ev->data1;
-
-				if (genStringEnter)
+				if (saveCharIndex > 0)
 				{
-					switch (ch)
-					{
-					case '\b':
-						if (saveCharIndex > 0)
-						{
-							saveCharIndex--;
-							savegamestring[saveCharIndex] = 0;
-						}
-						break;
-
-					case GK_ESCAPE:
-						genStringEnter = 0;
-						genStringCancel ();	// [RH] Function to call when escape is pressed
-						break;
-
-					case '\r':
-						if (savegamestring[0])
-						{
-							genStringEnter = 0;
-							if (messageToPrint)
-								M_ClearMenus ();
-							genStringEnd (SelSaveGame);	// [RH] Function to call when enter is pressed
-						}
-						break;
-					}
-					return true;
+					saveCharIndex--;
+					savegamestring[saveCharIndex] = 0;
 				}
 			}
+			else if (ev->subtype == EV_GUI_KeyDown)
+			{
+				if (ch == GK_ESCAPE)
+				{
+					genStringEnter = 0;
+					genStringCancel();	// [RH] Function to call when escape is pressed
+				}
+				else if (ch == '\r')
+				{
+					if (savegamestring[0])
+					{
+						genStringEnter = 0;
+						if (messageToPrint)
+							M_ClearMenus ();
+						genStringEnd (SelSaveGame);	// [RH] Function to call when enter is pressed
+					}
+				}
+			}
+			if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat)
+			{
+				return true;
+			}
 		}
 		if (ev->subtype != EV_GUI_KeyDown && ev->subtype != EV_GUI_KeyUp)
 		{
 			return false;
 		}
+		if (ev->subtype == EV_GUI_KeyRepeat)
+		{
+			// We do our own key repeat handling but still want to eat the
+			// OS's repeated keys.
+			return true;
+		}
 		ch = ev->data1;
 		keyup = ev->subtype == EV_GUI_KeyUp;
 		if (messageToPrint && messageRoutine == NULL)