static LONG WINAPI Sys_ConsoleEditProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CHAR: if (hWnd == sys_console.hWndInput) { switch (wParam) { case VK_RETURN: if (GetWindowText(sys_console.hWndInput, sys_console.cmdBuffer, sizeof(sys_console.cmdBuffer))) { SetWindowText(sys_console.hWndInput, ""); Com_Printf("]%s\n", sys_console.cmdBuffer); } /* Keep it from beeping */ return 0; case VK_TAB: /* command completion */ if (GetWindowText(sys_console.hWndInput, sys_console.cmdBuffer, sizeof(sys_console.cmdBuffer))) { uint32_t inputpos = 0; if (Com_ConsoleCompleteCommand(sys_console.cmdBuffer, sys_console.cmdBuffer, sizeof(sys_console.cmdBuffer), &inputpos, 0)) { SetWindowText(sys_console.hWndInput, sys_console.cmdBuffer); /* reset again - we don't want to execute yet */ sys_console.cmdBuffer[0] = '\0'; } } /* Keep it from beeping */ return 0; } } else if (hWnd == sys_console.hWndOutput) return 0; /* Read only */ break; case WM_VSCROLL: if (LOWORD(wParam) == SB_THUMBTRACK) return 0; break; } if (hWnd == sys_console.hWndOutput) return CallWindowProc(sys_console.defOutputProc, hWnd, uMsg, wParam, lParam); else if (hWnd == sys_console.hWndInput) return CallWindowProc(sys_console.defInputProc, hWnd, uMsg, wParam, lParam); return 0; }
/** * @brief Interactive line editing and console scrollback * @param[in] key key code, either K_ value or lowercase ascii * @param[in] unicode translated meaning of keypress in unicode */ static void Key_Console (int key, int unicode) { int i; if (keyDown[K_CTRL]) { switch (toupper(key)) { /* ctrl-L clears screen */ case 'L': Cbuf_AddText("clear\n"); return; /* jump to beginning of line */ case 'A': keyLinePos = 1; return; /* end of line */ case 'E': keyLinePos = strlen(keyLines[editLine]); return; } } if (key == K_ENTER || key == K_KP_ENTER) { /* backslash text are commands, else chat */ if (keyLines[editLine][1] == '\\' || keyLines[editLine][1] == '/') Cbuf_AddText(keyLines[editLine] + 2); /* skip the > */ /* no command - just enter */ else if (!keyLines[editLine][1]) return; else Cbuf_AddText(keyLines[editLine] + 1); /* valid command */ Cbuf_AddText("\n"); Com_Printf("%s\n", keyLines[editLine] + 1); editLine = (editLine + 1) & (MAXKEYLINES - 1); historyLine = editLine; keyLines[editLine][0] = CONSOLE_PROMPT_CHAR; /* maybe MAXKEYLINES was reached - we don't want to spawn 'random' strings * from history buffer in our console */ keyLines[editLine][1] = '\0'; keyLinePos = 1; return; } /* command completion */ if (key == K_TAB) { Com_ConsoleCompleteCommand(&keyLines[editLine][1], keyLines[editLine], MAXCMDLINE, &keyLinePos, 1); return; } if (key == K_BACKSPACE || (key == 'h' && keyDown[K_CTRL])) { if (keyLinePos > 1) { strcpy(keyLines[editLine] + keyLinePos - 1, keyLines[editLine] + keyLinePos); keyLinePos--; } return; } /* delete char on cursor */ if (key == K_DEL) { if (keyLinePos < strlen(keyLines[editLine])) strcpy(keyLines[editLine] + keyLinePos, keyLines[editLine] + keyLinePos + 1); return; } if (key == K_UPARROW || key == K_KP_UPARROW || (tolower(key) == 'p' && keyDown[K_CTRL])) { do { historyLine = (historyLine - 1) & (MAXKEYLINES - 1); } while (historyLine != editLine && !keyLines[historyLine][1]); if (historyLine == editLine) historyLine = (editLine + 1) & (MAXKEYLINES - 1); Q_strncpyz(keyLines[editLine], keyLines[historyLine], MAXCMDLINE); keyLinePos = strlen(keyLines[editLine]); return; } else if (key == K_DOWNARROW || key == K_KP_DOWNARROW || (tolower(key) == 'n' && keyDown[K_CTRL])) { if (historyLine == editLine) return; do { historyLine = (historyLine + 1) & (MAXKEYLINES - 1); } while (historyLine != editLine && !keyLines[historyLine][1]); if (historyLine == editLine) { keyLines[editLine][0] = CONSOLE_PROMPT_CHAR; /* fresh edit line */ keyLines[editLine][1] = '\0'; keyLinePos = 1; } else { Q_strncpyz(keyLines[editLine], keyLines[historyLine], MAXCMDLINE); keyLinePos = strlen(keyLines[editLine]); } return; } if (key == K_LEFTARROW) { /* move cursor left */ if (keyDown[K_CTRL]) { /* by a whole word */ while (keyLinePos > 1 && keyLines[editLine][keyLinePos - 1] == ' ') keyLinePos--; /* get off current word */ while (keyLinePos > 1 && keyLines[editLine][keyLinePos - 1] != ' ') keyLinePos--; /* and behind previous word */ return; } if (keyLinePos > 1) /* or just a char */ keyLinePos--; return; } else if (key == K_RIGHTARROW) { /* move cursor right */ if ((i = strlen(keyLines[editLine])) == keyLinePos) return; /* no character to get */ if (keyDown[K_CTRL]) { /* by a whole word */ while (keyLinePos < i && keyLines[editLine][keyLinePos + 1] == ' ') keyLinePos++; /* get off current word */ while (keyLinePos < i && keyLines[editLine][keyLinePos + 1] != ' ') keyLinePos++; /* and in front of next word */ if (keyLinePos < i) /* all the way in front */ keyLinePos++; return; } keyLinePos++; /* or just a char */ return; } /* toggle insert mode */ if (key == K_INS) { keyInsert ^= 1; return; } if (key == K_PGUP || key == K_KP_PGUP || key == K_MWHEELUP) { Con_Scroll(-2); return; } if (key == K_PGDN || key == K_KP_PGDN || key == K_MWHEELDOWN) { Con_Scroll(2); return; } if (key == K_HOME || key == K_KP_HOME) { keyLinePos = 1; return; } if (key == K_END || key == K_KP_END) { keyLinePos = strlen(keyLines[editLine]); return; } switch (key) { case K_KP_SLASH: key = '/'; break; case K_KP_MINUS: key = '-'; break; case K_KP_PLUS: key = '+'; break; case K_KP_HOME: key = '7'; break; case K_KP_UPARROW: key = '8'; break; case K_KP_PGUP: key = '9'; break; case K_KP_LEFTARROW: key = '4'; break; case K_KP_5: key = '5'; break; case K_KP_RIGHTARROW: key = '6'; break; case K_KP_END: key = '1'; break; case K_KP_DOWNARROW: key = '2'; break; case K_KP_PGDN: key = '3'; break; case K_KP_INS: key = '0'; break; case K_KP_DEL: key = '.'; break; default: key = unicode; break; } /** @todo use isprint here? */ if (key < 32 || key > 127) return; /* non printable */ if (keyLinePos < MAXCMDLINE - 1) { if (keyInsert) { /* can't do strcpy to move string to right */ i = strlen(keyLines[editLine]) - 1; if (i == MAXCMDLINE - 2) i--; for (; i >= keyLinePos; i--) keyLines[editLine][i + 1] = keyLines[editLine][i]; } i = keyLines[editLine][keyLinePos]; keyLines[editLine][keyLinePos] = key; keyLinePos++; if (!i) /* only null terminate if at the end */ keyLines[editLine][keyLinePos] = 0; } }