diff --git a/4coder_custom.h b/4coder_custom.h
index 77b0686f..f422320c 100644
--- a/4coder_custom.h
+++ b/4coder_custom.h
@@ -31,6 +31,7 @@ typedef enum{
 	MDFR_CONTROL_INDEX,
 	MDFR_ALT_INDEX,
     MDFR_CAPS_INDEX,
+    MDFR_HOLD_INDEX,
 	// always last
 	MDFR_INDEX_COUNT
 } Key_Control;
diff --git a/4ed.cpp b/4ed.cpp
index 3df9fd5b..aca3a7fb 100644
--- a/4ed.cpp
+++ b/4ed.cpp
@@ -3559,9 +3559,36 @@ App_Step_Sig(app_step){
         }
     }
     
-    // NOTE(allen): Keyboard input to command coroutine.
+    // NOTE(allen): Pass keyboard events to debug
     Available_Input available_input = init_available_input(&key_summary, &input->mouse);
     
+#if FRED_INTERNAL
+    {
+        Debug_Data *debug = &models->debug;
+        Key_Summary key_data = get_key_data(&available_input);
+        
+        Debug_Input_Event *events = debug->input_events;
+        
+        i32 count = key_data.count;
+        i32 preserved_inputs = ArrayCount(debug->input_events) - count;
+        
+        memmove(events + count, events,
+                sizeof(Debug_Input_Event)*preserved_inputs);
+        
+        for (i32 i = 0; i < key_data.count; ++i){
+            Key_Event_Data key = get_single_key(&key_data,  i);
+            events[i].key = key.keycode;
+            
+            events[i].is_hold = key.modifiers[MDFR_HOLD_INDEX];
+            events[i].is_ctrl = key.modifiers[MDFR_CONTROL_INDEX];
+            events[i].is_alt = key.modifiers[MDFR_ALT_INDEX];
+            events[i].is_shift = key.modifiers[MDFR_SHIFT_INDEX];
+        }
+    }
+#endif
+    
+    // NOTE(allen): Keyboard input to command coroutine.
+    
     if (models->command_coroutine != 0){
         Coroutine *command_coroutine = models->command_coroutine;
         u32 get_flags = models->command_coroutine_flags[0];
diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp
index c313fa98..37343215 100644
--- a/4ed_file_view.cpp
+++ b/4ed_file_view.cpp
@@ -4466,6 +4466,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
                     }
                 }break;
                 
+#if FRED_INTERNAL
                 case VUI_Debug:
                 {
                     view->current_scroll = &view->gui_scroll;
@@ -4487,7 +4488,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
                         string.size = 0;
                         u64 time = system->now_time_stamp();
                         
-                        append(&string, "last event time stamp: ");
+                        append(&string, "last redraw: ");
                         append_u64_to_str(&string, time);
                         
                         gui_do_text_field(target, string, empty_str);
@@ -4547,20 +4548,35 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
                                 append(&string, "      ");
                             }
                             
-                            if (input_event->key >= ' ' && input_event->key <= '~'){
+                            if (input_event->key > ' ' && input_event->key <= '~'){
                                 append(&string, make_string(&input_event->key, 1));
                             }
+                            else if (input_event->key == ' '){
+                                append(&string, "space");
+                            }
+                            else if (input_event->key == '\n'){
+                                append(&string, "\\n");
+                            }
+                            else if (input_event->key == '\t'){
+                                append(&string, "\\t");
+                            }
                             else{
                                 String str;
                                 str.str = global_key_name(input_event->key, &str.size);
-                                str.memory_size = str.size + 1;
-                                append(&string, str);
+                                if (str.str){
+                                    str.memory_size = str.size + 1;
+                                    append(&string, str);
+                                }
+                                else{
+                                    append(&string, "unrecognized!");
+                                }
                             }
                             
                             gui_do_text_field(target, string, empty_str);
                         }
                     }
                 }break;
+#endif
             }
         }
     }
diff --git a/4ed_gui.cpp b/4ed_gui.cpp
index 63f5995e..938906d6 100644
--- a/4ed_gui.cpp
+++ b/4ed_gui.cpp
@@ -490,8 +490,10 @@ gui_begin_list(GUI_Target *target, GUI_id id, i32 list_i,
         }
     }
     
-    if (list_i < list_min || list_i >= list_max){
-        result = 1;
+    if (list_max > 0){
+        if (list_i < list_min || list_i >= list_max){
+            result = 1;
+        }
     }
     
     if (result){
@@ -500,7 +502,12 @@ gui_begin_list(GUI_Target *target, GUI_id id, i32 list_i,
             gui_update_adjustment(update, list_min);
         }
         else if (list_i >= list_max){
-            gui_update_adjustment(update, list_max - 1);
+            if (list_max > 0){
+                gui_update_adjustment(update, list_max - 1);
+            }
+            else{
+                gui_update_adjustment(update, 0);
+            }
         }
         if (target->has_list_index_position){
             gui_update_position(update, target->list_index_position);
diff --git a/win32_4ed.cpp b/win32_4ed.cpp
index cb920b01..1ff9e458 100644
--- a/win32_4ed.cpp
+++ b/win32_4ed.cpp
@@ -1420,7 +1420,7 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
     switch (uMsg){
         case WM_MENUCHAR:
         case WM_SYSCHAR:break;
-
+        
         case WM_SYSKEYDOWN:
         case WM_SYSKEYUP:
         case WM_KEYDOWN:
@@ -1436,59 +1436,59 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
                     b8 *control_keys = 0;
                     controls = &win32vars.input_chunk.pers.controls;
                     control_keys = win32vars.input_chunk.pers.control_keys;
-
+                    
                     b8 down = ((lParam & Bit_31)?(0):(1));
                     b8 is_right = ((lParam & Bit_24)?(1):(0));
-
+                    
                     if (wParam != 255){
                         switch (wParam){
                             case VK_SHIFT:
                             {
                                 control_keys[MDFR_SHIFT_INDEX] = down;
                             }break;
-
+                            
                             case VK_CONTROL:
                             {
                                 if (is_right) controls->r_ctrl = down;
                                 else controls->l_ctrl = down;
                             }break;
-
+                            
                             case VK_MENU:
                             {
                                 if (is_right) controls->r_alt = down;
                                 else controls->l_alt = down;
                             }break;
                         }
-
+                        
                         b8 ctrl, alt;
                         ctrl = (controls->r_ctrl || (controls->l_ctrl && !controls->r_alt));
                         alt = (controls->l_alt || (controls->r_alt && !controls->l_ctrl));
-
+                        
                         if (win32vars.lctrl_lalt_is_altgr){
                             if (controls->l_alt && controls->l_ctrl){
                                 ctrl = 0;
                                 alt = 0;
                             }
                         }
-
+                        
                         control_keys[MDFR_CONTROL_INDEX] = ctrl;
                         control_keys[MDFR_ALT_INDEX] = alt;
                     }
                 }break;
-
+                
                 default:
                 b8 previous_state, current_state;
                 previous_state = ((lParam & Bit_30)?(1):(0));
                 current_state = ((lParam & Bit_31)?(0):(1));
-
+                
                 if (current_state){
                     u8 key = keycode_lookup_table[(u8)wParam];
-
+                    
                     i32 *count = 0;
                     Key_Event_Data *data = 0;
                     b8 *control_keys = 0;
                     i32 control_keys_size = 0;
-
+                    
                     if (!previous_state){
                         count = &win32vars.input_chunk.trans.key_data.press_count;
                         data = win32vars.input_chunk.trans.key_data.press;
@@ -1532,12 +1532,13 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
                                 result2 = 0;
                             }
                             
-                            // TODO(allen): This is becoming a really major issue.  Apparently
-                            // control + i outputs a '\t' which is VALID ascii according to this system.
-                            // So it reports the key as '\t'.  This wasn't an issue before because we were
-                            // ignoring control when computing character_no_caps_lock which is what
-                            // is used for commands.  But that is incorrect for some keyboard layouts where
-                            // control+alt is used to signal AltGr for important keys.
+                            // TODO(allen): This is becoming a really major issue.
+                            // Apparently control + i outputs a '\t' which is VALID ascii
+                            // according to this system. So it reports the key as '\t'.
+                            // This wasn't an issue before because we were ignoring control
+                            // when computing character_no_caps_lock which is what is used
+                            // for commands. But that is incorrect for some keyboard layouts
+                            // where control+alt is used to signal AltGr for important keys.
                             if (result1 && result2){
                                 char c1 = char_to_upper((char)x1);
                                 char cParam = char_to_upper((char)wParam);
@@ -1549,7 +1550,7 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
                                     result1 = 0;
                                 }
                             }
-
+                            
                             if (result1){
                                 x = x1;
                                 state[VK_CONTROL] = control_state;
@@ -1595,6 +1596,7 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
                             data[*count].keycode = key;
                         }
                         memcpy(data[*count].modifiers, control_keys, control_keys_size);
+                        data[*count].modifiers[MDFR_HOLD_INDEX] = previous_state;
                         ++(*count);
                     }
                 }
@@ -1607,16 +1609,16 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
         {
             i32 new_x = LOWORD(lParam);
             i32 new_y = HIWORD(lParam);
-
+            
             if (new_x != win32vars.input_chunk.pers.mouse_x
-                    || new_y != win32vars.input_chunk.pers.mouse_y){
+                || new_y != win32vars.input_chunk.pers.mouse_y){
                 win32vars.input_chunk.pers.mouse_x = new_x;
                 win32vars.input_chunk.pers.mouse_y = new_y;
-
+                
                 win32vars.got_useful_event = 1;
             }
         }break;
-
+        
         case WM_MOUSEWHEEL:
         {
             win32vars.got_useful_event = 1;
@@ -1628,58 +1630,58 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
                 win32vars.input_chunk.trans.mouse_wheel = -1;
             }
         }break;
-
+        
         case WM_LBUTTONDOWN:
         {
             win32vars.got_useful_event = 1;
             win32vars.input_chunk.trans.mouse_l_press = 1;
             win32vars.input_chunk.pers.mouse_l = 1;
         }break;
-
+        
         case WM_RBUTTONDOWN:
         {
             win32vars.got_useful_event = 1;
             win32vars.input_chunk.trans.mouse_r_press = 1;
             win32vars.input_chunk.pers.mouse_r = 1;
         }break;
-
+        
         case WM_LBUTTONUP:
         {
             win32vars.got_useful_event = 1;
             win32vars.input_chunk.trans.mouse_l_release = 1;
             win32vars.input_chunk.pers.mouse_l = 0;
         }break;
-
+        
         case WM_RBUTTONUP:
         {
             win32vars.got_useful_event = 1;
             win32vars.input_chunk.trans.mouse_r_release = 1;
             win32vars.input_chunk.pers.mouse_r = 0;
         }break;
-
+        
         case WM_KILLFOCUS:
         case WM_SETFOCUS:
         {
             win32vars.got_useful_event = 1;
             win32vars.input_chunk.pers.mouse_l = 0;
             win32vars.input_chunk.pers.mouse_r = 0;
-
+            
             b8 *control_keys = win32vars.input_chunk.pers.control_keys;
             for (int i = 0; i < MDFR_INDEX_COUNT; ++i) control_keys[i] = 0;
             win32vars.input_chunk.pers.controls = control_keys_zero();
         }break;
-
+        
         case WM_SIZE:
         {
             win32vars.got_useful_event = 1;
             if (win32vars.target.handle){
                 i32 new_width = LOWORD(lParam);
                 i32 new_height = HIWORD(lParam);
-
+                
                 Win32Resize(new_width, new_height);
             }
         }break;
-
+        
         case WM_PAINT:
         {
             win32vars.got_useful_event = 1;
@@ -1688,14 +1690,14 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
             Win32RedrawScreen(hdc);
             EndPaint(hwnd, &ps);
         }break;
-
+        
         case WM_CLOSE:
         case WM_DESTROY:
         {
             win32vars.got_useful_event = 1;
             win32vars.input_chunk.trans.trying_to_kill = 1;
         }break;
-
+        
         case WM_4coder_ANIMATE:
         win32vars.got_useful_event = 1;
         break;