expanded console buffer from 16k to 128k, and changed scroll amount to be dependent...
[xonotic/darkplaces.git] / keys.c
diff --git a/keys.c b/keys.c
index c3a8a75497eef4f8d7bfa3bf24df205bcb2412fc..199d311f99a902e41d3c70662967b2b23c705af5 100644 (file)
--- a/keys.c
+++ b/keys.c
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -26,30 +26,32 @@ key up events are sent even if in console mode
 */
 
 
-#define                MAXCMDLINE      256
-char   key_lines[32][MAXCMDLINE];
-int            key_linepos;
-int            shift_down=false;
-int            key_lastpress;
+#define MAXCMDLINE 256
+char key_lines[32][MAXCMDLINE];
+int key_linepos;
+int shift_down = false;
+int key_lastpress;
+int key_insert;        // insert key toggle (for editing)
 
-int            edit_line=0;
-int            history_line=0;
+int edit_line = 0;
+int history_line = 0;
 
-keydest_t      key_dest;
+int key_consoleactive;
+keydest_t key_dest;
 
-int            key_count;                      // incremented every key event
+int key_count;                 // incremented every key event
 
-char   *keybindings[256];
-qboolean       consolekeys[256];       // if true, can't be rebound while in console
-qboolean       menubound[256]; // if true, can't be rebound while in menu
-int            keyshift[256];          // key to map to if shift held down in console
-int            key_repeats[256];       // if > 1, it is autorepeating
-qboolean       keydown[256];
+char *keybindings[256];
+qboolean consolekeys[256];     // if true, can't be rebound while in console
+qboolean menubound[256];       // if true, can't be rebound while in menu
+int keyshift[256];             // key to map to if shift held down in console
+int key_repeats[256];  // if > 1, it is autorepeating
+qboolean keydown[256];
 
 typedef struct
 {
-       char    *name;
-       int             keynum;
+       char *name;
+       int keynum;
 } keyname_t;
 
 keyname_t keynames[] =
@@ -67,7 +69,7 @@ keyname_t keynames[] =
        {"ALT", K_ALT},
        {"CTRL", K_CTRL},
        {"SHIFT", K_SHIFT},
-       
+
        {"F1", K_F1},
        {"F2", K_F2},
        {"F3", K_F3},
@@ -158,46 +160,90 @@ Interactive line editing and console scrollback
 */
 void Key_Console (int key)
 {
-       char    *cmd;
-       
        if (key == K_ENTER)
        {
-               Cbuf_AddText (key_lines[edit_line]+1);  // skip the >
+               Cbuf_AddText (key_lines[edit_line]+1);  // skip the ]
                Cbuf_AddText ("\n");
                Con_Printf ("%s\n",key_lines[edit_line]);
                edit_line = (edit_line + 1) & 31;
                history_line = edit_line;
                key_lines[edit_line][0] = ']';
+               key_lines[edit_line][1] = 0;    // EvilTypeGuy: null terminate
                key_linepos = 1;
+               // force an update, because the command may take some time
                if (cls.state == ca_disconnected)
-                       SCR_UpdateScreen ();    // force an update, because the command
-                                                                       // may take some time
+               {
+                       CL_UpdateScreen ();
+                       CL_UpdateScreen ();
+               }
                return;
        }
 
        if (key == K_TAB)
-       {       // command completion
-               cmd = Cmd_CompleteCommand (key_lines[edit_line]+1);
-               if (!cmd)
-                       cmd = Cvar_CompleteVariable (key_lines[edit_line]+1);
-               if (cmd)
+       {
+               // Enhanced command completion
+               // by EvilTypeGuy eviltypeguy@qeradiant.com
+               // Thanks to Fett, Taniwha
+               Con_CompleteCommandLine();
+       }
+
+       // Advanced Console Editing by Radix radix@planetquake.com
+       // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
+
+       // left arrow will just move left one without erasing, backspace will
+       // actually erase charcter
+       if (key == K_LEFTARROW)
+       {
+               if (key_linepos > 1)
+                       key_linepos--;
+               return;
+       }
+
+       if (key == K_BACKSPACE) // delete char before cursor
+       {
+               if (key_linepos > 1)
                {
-                       strcpy (key_lines[edit_line]+1, cmd);
-                       key_linepos = strlen(cmd)+1;
-                       key_lines[edit_line][key_linepos] = ' ';
+                       strcpy(key_lines[edit_line] + key_linepos - 1, key_lines[edit_line] + key_linepos);
+                       key_linepos--;
+               }
+               return;
+       }
+
+       if (key == K_DEL)               // delete char on cursor
+       {
+               if (key_linepos < strlen(key_lines[edit_line]))
+                       strcpy(key_lines[edit_line] + key_linepos, key_lines[edit_line] + key_linepos + 1);
+               return;
+       }
+
+
+       // if we're at the end, get one character from previous line,
+       // otherwise just go right one
+       if (key == K_RIGHTARROW)
+       {
+               if (strlen(key_lines[edit_line]) == key_linepos)
+               {
+                       if (strlen(key_lines[(edit_line + 31) & 31]) <= key_linepos)
+                               return; // no character to get
+
+                       key_lines[edit_line][key_linepos] = key_lines[(edit_line + 31) & 31][key_linepos];
                        key_linepos++;
                        key_lines[edit_line][key_linepos] = 0;
-                       return;
                }
+               else
+                       key_linepos++;
+
+               return;
        }
-       
-       if (key == K_BACKSPACE || key == K_LEFTARROW)
+
+       if (key == K_INS) // toggle insert mode
        {
-               if (key_linepos > 1)
-                       key_linepos--;
+               key_insert ^= 1;
                return;
        }
 
+       // End Advanced Console Editing
+
        if (key == K_UPARROW)
        {
                do
@@ -236,15 +282,15 @@ void Key_Console (int key)
 
        if (key == K_PGUP || key==K_MWHEELUP)
        {
-               con_backscroll += 2;
-               if (con_backscroll > con_totallines - (vid.height>>3) - 1)
-                       con_backscroll = con_totallines - (vid.height>>3) - 1;
+               con_backscroll += ((int) scr_conlines >> 4);
+               if (con_backscroll > con_totallines - (vid.conheight>>3) - 1)
+                       con_backscroll = con_totallines - (vid.conheight>>3) - 1;
                return;
        }
 
        if (key == K_PGDN || key==K_MWHEELDOWN)
        {
-               con_backscroll -= 2;
+               con_backscroll -= ((int) scr_conlines >> 4);
                if (con_backscroll < 0)
                        con_backscroll = 0;
                return;
@@ -252,7 +298,7 @@ void Key_Console (int key)
 
        if (key == K_HOME)
        {
-               con_backscroll = con_totallines - (vid.height>>3) - 1;
+               con_backscroll = con_totallines - (vid.conheight>>3) - 1;
                return;
        }
 
@@ -261,17 +307,36 @@ void Key_Console (int key)
                con_backscroll = 0;
                return;
        }
-       
+
        if (key < 32 || key > 127)
                return; // non printable
-               
+
+
+
        if (key_linepos < MAXCMDLINE-1)
        {
+               int i;
+
+               if (key_insert) // check insert mode
+               {
+                       // can't do strcpy to move string to right
+                       i = strlen(key_lines[edit_line]) - 1;
+
+                       if (i == 254)
+                               i--;
+
+                       for (; i >= key_linepos; i--)
+                               key_lines[edit_line][i + 1] = key_lines[edit_line][i];
+               }
+
+               // only null terminate if at the end
+               i = key_lines[edit_line][key_linepos];
                key_lines[edit_line][key_linepos] = key;
                key_linepos++;
-               key_lines[edit_line][key_linepos] = 0;
-       }
 
+               if (!i)
+                       key_lines[edit_line][key_linepos] = 0;
+       }
 }
 
 //============================================================================
@@ -343,7 +408,7 @@ the K_* names are matched up.
 int Key_StringToKeynum (char *str)
 {
        keyname_t       *kn;
-       
+
        if (!str || !str[0])
                return -1;
        if (!str[1])
@@ -368,9 +433,9 @@ FIXME: handle quote special (general escape sequence?)
 */
 char *Key_KeynumToString (int keynum)
 {
-       keyname_t       *kn;    
+       keyname_t       *kn;
        static  char    tinystr[2];
-       
+
        if (keynum == -1)
                return "<KEY NOT FOUND>";
        if (keynum > 32 && keynum < 127)
@@ -430,7 +495,7 @@ void Key_Unbind_f (void)
                Con_Printf ("unbind <key> : remove commands from a key\n");
                return;
        }
-       
+
        b = Key_StringToKeynum (Cmd_Argv(1));
        if (b==-1)
        {
@@ -444,7 +509,7 @@ void Key_Unbind_f (void)
 void Key_Unbindall_f (void)
 {
        int             i;
-       
+
        for (i=0 ; i<256 ; i++)
                if (keybindings[i])
                        Key_SetBinding (i, "");
@@ -460,7 +525,7 @@ void Key_Bind_f (void)
 {
        int                     i, c, b;
        char            cmd[1024];
-       
+
        c = Cmd_Argc();
 
        if (c != 2 && c != 3)
@@ -483,7 +548,7 @@ void Key_Bind_f (void)
                        Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) );
                return;
        }
-       
+
 // copy the rest of the command line
        cmd[0] = 0;             // start out with a null string
        for (i=2 ; i< c ; i++)
@@ -503,14 +568,14 @@ Key_WriteBindings
 Writes lines containing "bind key value"
 ============
 */
-void Key_WriteBindings (FILE *f)
+void Key_WriteBindings (QFile *f)
 {
        int             i;
 
        for (i=0 ; i<256 ; i++)
                if (keybindings[i])
                        if (*keybindings[i])
-                               fprintf (f, "bind \"%s\" \"%s\"\n", Key_KeynumToString(i), keybindings[i]);
+                               Qprintf (f, "bind \"%s\" \"%s\"\n", Key_KeynumToString(i), keybindings[i]);
 }
 
 
@@ -523,13 +588,17 @@ void Key_Init (void)
 {
        int             i;
 
+       // LordHavoc: clear keybindings array so bounds checking won't freak
+       for (i = 0;i < 256;i++)
+               keybindings[i] = NULL;
+
        for (i=0 ; i<32 ; i++)
        {
                key_lines[i][0] = ']';
                key_lines[i][1] = 0;
        }
        key_linepos = 1;
-       
+
 //
 // init ascii characters in console mode
 //
@@ -542,6 +611,8 @@ void Key_Init (void)
        consolekeys[K_UPARROW] = true;
        consolekeys[K_DOWNARROW] = true;
        consolekeys[K_BACKSPACE] = true;
+       consolekeys[K_DEL] = true;
+       consolekeys[K_INS] = true;
        consolekeys[K_PGUP] = true;
        consolekeys[K_PGDN] = true;
        consolekeys[K_SHIFT] = true;
@@ -586,8 +657,6 @@ void Key_Init (void)
        Cmd_AddCommand ("bind",Key_Bind_f);
        Cmd_AddCommand ("unbind",Key_Unbind_f);
        Cmd_AddCommand ("unbindall",Key_Unbindall_f);
-
-
 }
 
 /*
@@ -619,7 +688,7 @@ void Key_Event (int key, qboolean down)
                key_repeats[key]++;
                if (key != K_BACKSPACE && key != K_PAUSE && key_repeats[key] > 1)
                        return; // ignore most autorepeats
-                       
+
                if (key >= 200 && !keybindings[key])
                        Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) );
        }
@@ -643,7 +712,6 @@ void Key_Event (int key, qboolean down)
                        M_Keydown (key);
                        break;
                case key_game:
-               case key_console:
                        M_ToggleMenu_f ();
                        break;
                default:
@@ -652,89 +720,116 @@ void Key_Event (int key, qboolean down)
                return;
        }
 
-//
-// key up events only generate commands if the game key binding is
-// a button command (leading + sign).  These will occur even in console mode,
-// to keep the character from continuing an action started before a console
-// switch.  Button commands include the keynum as a parameter, so multiple
-// downs can be matched with ups
-//
-       if (!down)
+       // LordHavoc: hack to make toggleconsole always work
+       if (down)
        {
                kb = keybindings[key];
-               if (kb && kb[0] == '+')
+               if (kb && !strncmp(kb, "toggleconsole", strlen("toggleconsole")))
                {
-                       sprintf (cmd, "-%s %i\n", kb+1, key);
-                       Cbuf_AddText (cmd);
+                       Cbuf_AddText (kb);
+                       Cbuf_AddText ("\n");
+                       return;
                }
-               if (keyshift[key] != key)
+       }
+
+       if (key_consoleactive && consolekeys[key])
+       {
+               // console only wants key down events
+               if (!down)
+                       return;
+
+               // FIXME: this does not support non-QWERTY keyboards
+               if (shift_down)
+                       key = keyshift[key];
+
+               Key_Console (key);
+       }
+       else
+       {
+               //
+               // key up events only generate commands if the game key binding is
+               // a button command (leading + sign).  These will occur even in console mode,
+               // to keep the character from continuing an action started before a console
+               // switch.  Button commands include the keynum as a parameter, so multiple
+               // downs can be matched with ups
+               //
+               if (!down)
                {
-                       kb = keybindings[keyshift[key]];
+                       kb = keybindings[key];
                        if (kb && kb[0] == '+')
                        {
                                sprintf (cmd, "-%s %i\n", kb+1, key);
                                Cbuf_AddText (cmd);
                        }
+                       if (keyshift[key] != key)
+                       {
+                               kb = keybindings[keyshift[key]];
+                               if (kb && kb[0] == '+')
+                               {
+                                       sprintf (cmd, "-%s %i\n", kb+1, key);
+                                       Cbuf_AddText (cmd);
+                               }
+                       }
+                       return;
                }
-               return;
-       }
 
-//
-// during demo playback, most keys bring up the main menu
-//
-       if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game)
-       {
-               M_ToggleMenu_f ();
-               return;
-       }
+               //
+               // during demo playback, most keys bring up the main menu
+               //
+               if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game)
+               {
+                       M_ToggleMenu_f ();
+                       return;
+               }
 
-//
-// if not a consolekey, send to the interpreter no matter what mode is
-//
-       if ( (key_dest == key_menu && menubound[key])
-       || (key_dest == key_console && !consolekeys[key])
-       || (key_dest == key_game && ( !con_forcedup || !consolekeys[key] ) ) )
-       {
-               kb = keybindings[key];
-               if (kb)
+               //
+               // if not a consolekey, send to the interpreter no matter what mode is
+               //
+               //if ((key_dest == key_console && !consolekeys[key])
+               if ((key_consoleactive && !consolekeys[key])
+                || (key_dest == key_menu && menubound[key])
+                || key_dest == key_game)
                {
-                       if (kb[0] == '+')
-                       {       // button commands add keynum as a parm
-                               sprintf (cmd, "%s %i\n", kb, key);
-                               Cbuf_AddText (cmd);
-                       }
-                       else
+                       kb = keybindings[key];
+                       if (kb)
                        {
-                               Cbuf_AddText (kb);
-                               Cbuf_AddText ("\n");
+                               if (kb[0] == '+')
+                               {       // button commands add keynum as a parm
+                                       sprintf (cmd, "%s %i\n", kb, key);
+                                       Cbuf_AddText (cmd);
+                               }
+                               else
+                               {
+                                       Cbuf_AddText (kb);
+                                       Cbuf_AddText ("\n");
+                               }
                        }
+                       return;
                }
-               return;
-       }
 
-       if (!down)
-               return;         // other systems only care about key down events
+               if (!down)
+                       return;         // other systems only care about key down events
 
-       if (shift_down)
-       {
-               key = keyshift[key];
-       }
+               // FIXME: this does not support non-QWERTY keyboards
+               if (shift_down)
+                       key = keyshift[key];
 
-       switch (key_dest)
-       {
-       case key_message:
-               Key_Message (key);
-               break;
-       case key_menu:
-               M_Keydown (key);
-               break;
+               switch (key_dest)
+               {
+               case key_message:
+                       Key_Message (key);
+                       break;
+               case key_menu:
+                       M_Keydown (key);
+                       break;
 
-       case key_game:
-       case key_console:
-               Key_Console (key);
-               break;
-       default:
-               Sys_Error ("Bad key_dest");
+               case key_game:
+               //case key_console:
+                       Key_Console (key);
+                       break;
+               default:
+                       Sys_Error ("Bad key_dest");
+               }
        }
 }
 
@@ -746,9 +841,9 @@ Key_ClearStates
 */
 void Key_ClearStates (void)
 {
-       int             i;
+       int i;
 
-       for (i=0 ; i<256 ; i++)
+       for (i = 0;i < 256;i++)
        {
                keydown[i] = false;
                key_repeats[i] = 0;