From 7b32d5909adfa1d4dda4d20d2355eb40f2a4a58b Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Fri, 18 Dec 2009 21:56:51 +0000 Subject: [PATCH] FSCORE-516 git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16000 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/switch_console.c | 461 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 418 insertions(+), 43 deletions(-) diff --git a/src/switch_console.c b/src/switch_console.c index af24b44a6c..def9a1e690 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -33,7 +33,7 @@ #include #include #include -#define CMD_BUFLEN 1024; +#define CMD_BUFLEN 1024 #ifdef SWITCH_HAVE_LIBEDIT #include @@ -43,6 +43,34 @@ static History *myhistory; static HistEvent ev; static char *hfile = NULL; +#else + +#define CC_NORM 0 +#define CC_NEWLINE 1 +#define CC_EOF 2 +#define CC_ARGHACK 3 +#define CC_REFRESH 4 +#define CC_CURSOR 5 +#define CC_ERROR 6 +#define CC_FATAL 7 +#define CC_REDISPLAY 8 +#define CC_REFRESH_BEEP 9 + +#ifdef _MSC_VER +#define HISTLEN 10 +#define KEY_UP 1 +#define KEY_DOWN 2 +#define KEY_TAB 3 +#define CLEAR_OP 4 +#define DELETE_REFRESH_OP 5 +#define KEY_LEFT 6 +#define KEY_RIGHT 7 +#define KEY_INSERT 8 +#define PROMPT_OP 9 + +static int console_bufferInput (char* buf, int len, char *cmd, int key); +#endif +#endif /* * store a strdup() of the string configured in XML @@ -91,20 +119,6 @@ static switch_status_t console_xml_config(void) return SWITCH_STATUS_SUCCESS; } -#else - -#define CC_NORM 0 -#define CC_NEWLINE 1 -#define CC_EOF 2 -#define CC_ARGHACK 3 -#define CC_REFRESH 4 -#define CC_CURSOR 5 -#define CC_ERROR 6 -#define CC_FATAL 7 -#define CC_REDISPLAY 8 -#define CC_REFRESH_BEEP 9 - -#endif SWITCH_DECLARE_NONSTD(switch_status_t) switch_console_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen) { @@ -467,7 +481,11 @@ static int comp_callback(void *pArg, int argc, char **argv, char **columnNames) } if (!zstr(target)) { +#ifdef _MSC_VER + if ((h->hits % 3) == 0) { +#else if ((h->hits % 4) == 0) { +#endif if (h->out) { fprintf(h->out, "\n"); } @@ -543,9 +561,11 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch int sc = 0; #ifndef SWITCH_HAVE_LIBEDIT +#ifndef _MSC_VER if (!stream) { return CC_ERROR; } +#endif #endif switch_core_db_handle(&db); @@ -734,6 +754,21 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch el_insertstr(el, h.partial); } } +#else +#ifdef _MSC_VER + if (h.out) { + if (h.hits == 1 && !zstr(h.last)) { + console_bufferInput(0, h.len, (char*)line, DELETE_REFRESH_OP); + console_bufferInput(h.last, (int)strlen(h.last), (char*)line, 0); + console_bufferInput(" ", 1, (char*)line, 0); + } else if (h.hits > 1 && !zstr(h.partial)) { + console_bufferInput(0, h.len, (char*)line, DELETE_REFRESH_OP); + console_bufferInput(h.partial, (int)strlen(h.partial), (char*)line, 0); + } else { + console_bufferInput(0, 0, (char*)line, DELETE_REFRESH_OP); + } + } +#endif #endif end: @@ -752,10 +787,6 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch - -#ifdef SWITCH_HAVE_LIBEDIT -static char prompt_str[512] = ""; - /* * If a fnkey is configured then process the command */ @@ -782,6 +813,9 @@ static unsigned char console_fnkey_pressed(int i) return CC_REDISPLAY; } +#ifdef SWITCH_HAVE_LIBEDIT +static char prompt_str[512] = ""; + static unsigned char console_f1key(EditLine * el, int ch) { return console_fnkey_pressed(1); @@ -993,23 +1027,376 @@ SWITCH_DECLARE(void) switch_console_loop(void) #else +#ifdef _MSC_VER +char history[HISTLEN][CMD_BUFLEN+1]; +int iHistory = 0; +int iHistorySel = 0; + +static int console_history (char *cmd, int direction) +{ + int i; + static int first; + + if (direction == 0) { + first = 1; + if (iHistory < HISTLEN) { + if (iHistory && strcmp(history[iHistory-1], cmd)) { + iHistorySel = iHistory; + strcpy(history[iHistory++], cmd); + } + else if (iHistory == 0) { + iHistorySel = iHistory; + strcpy(history[iHistory++], cmd); + } + } + else { + iHistory = HISTLEN-1; + for (i = 0; i < HISTLEN-1; i++) + { + strcpy(history[i], history[i+1]); + } + iHistorySel = iHistory; + strcpy(history[iHistory++], cmd); + } + } + else { + if (!first) { + iHistorySel += direction; + } + first = 0; + if (iHistorySel < 0) { + iHistorySel = 0; + } + if (iHistory && iHistorySel >= iHistory) { + iHistorySel = iHistory-1; + } + strcpy(cmd, history[iHistorySel]); + } + return (SWITCH_STATUS_SUCCESS); +} + +static int console_bufferInput (char* addchars, int len, char *cmd, int key) +{ + static int iCmdBuffer = 0; + static int iCmdCursor = 0; + static int ignoreNext = 0; + static int insertMode = 1; + static COORD orgPosition; + static char prompt [80]; + int iBuf; + int i; + + HANDLE hOut; + CONSOLE_SCREEN_BUFFER_INFO info; + COORD position; + hOut = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(hOut, &info); + position = info.dwCursorPosition; + if (iCmdCursor == 0) { + orgPosition = position; + } + + if (key == PROMPT_OP) { + if (strlen(cmd) < sizeof(prompt)) { + strcpy(prompt, cmd); + } + return 0; + } + + if (key == KEY_TAB) { + switch_console_complete(cmd, cmd+iCmdBuffer, switch_core_get_console(), NULL, NULL); + return 0; + } + if (key == KEY_UP || key == KEY_DOWN || key == CLEAR_OP) { + SetConsoleCursorPosition(hOut, orgPosition); + for (i = 0; i < (int)strlen(cmd); i++) { + printf(" "); + } + SetConsoleCursorPosition(hOut, orgPosition); + iCmdBuffer = 0; + iCmdCursor = 0; + memset(cmd, 0, CMD_BUFLEN); + } + if (key == DELETE_REFRESH_OP) { + int l = len < (int)strlen(cmd) ? len : (int)strlen(cmd); + for (i = 0; i < l; i++) { + cmd[--iCmdBuffer] = 0; + } + iCmdCursor = (int)strlen(cmd); + printf("%s%s", prompt, cmd); + return 0; + } + + if (key == KEY_LEFT) { + if (iCmdCursor) { + if (position.X == 0) { + position.Y -= 1; + position.X = info.dwSize.X-1; + } + else { + position.X -= 1; + } + + SetConsoleCursorPosition(hOut, position); + iCmdCursor--; + } + } + if (key == KEY_RIGHT) { + if (iCmdCursor < (int)strlen(cmd)) { + if (position.X == info.dwSize.X-1) { + position.Y += 1; + position.X = 0; + } + else { + position.X += 1; + } + + SetConsoleCursorPosition(hOut, position); + iCmdCursor++; + } + } + if (key == KEY_INSERT) { + insertMode = !insertMode; + } + for (iBuf = 0; iBuf < len; iBuf++) { + switch (addchars[iBuf]) { + case '\r': + case '\n': + if (ignoreNext) { + ignoreNext = 0; + } + else { + int ret = iCmdBuffer; + if (iCmdBuffer == 0) { + strcpy(cmd, "Empty"); + ret = (int)strlen(cmd); + } + else { + console_history(cmd, 0); + cmd[iCmdBuffer] = 0; + } + iCmdBuffer = 0; + iCmdCursor = 0; + printf("\n"); + return (ret); + } + break; + case '\b': + if (iCmdCursor) { + if (position.X == 0) { + position.Y -= 1; + position.X = info.dwSize.X-1; + SetConsoleCursorPosition(hOut, position); + } + else { + position.X -= 1; + SetConsoleCursorPosition(hOut, position); + } + printf(" "); + if (iCmdCursor < iCmdBuffer) { + int pos; + iCmdCursor--; + for (pos = iCmdCursor; pos < iCmdBuffer; pos++) { + cmd[pos] = cmd[pos+1]; + } + cmd[pos] = 0; + iCmdBuffer--; + + SetConsoleCursorPosition(hOut, position); + for (pos = iCmdCursor; pos < iCmdBuffer; pos++) { + printf("%c", cmd[pos]); + } + printf(" "); + SetConsoleCursorPosition(hOut, position); + } + else { + SetConsoleCursorPosition(hOut, position); + iCmdBuffer--; + iCmdCursor--; + cmd[iCmdBuffer] = 0; + } + } + break; + default: + if (!ignoreNext) { + if (iCmdCursor < iCmdBuffer) { + int pos; + + if (position.X == info.dwSize.X-1) { + position.Y += 1; + position.X = 0; + } + else { + position.X += 1; + } + + if (insertMode) { + for (pos = iCmdBuffer-1; pos >= iCmdCursor; pos--) { + cmd[pos+1] = cmd[pos]; + } + } + iCmdBuffer++; + cmd[iCmdCursor++] = addchars[iBuf]; + printf("%c", addchars[iBuf]); + for (pos = iCmdCursor; pos < iCmdBuffer; pos++) { + GetConsoleScreenBufferInfo(hOut, &info); + if (info.dwCursorPosition.X == info.dwSize.X-1 && info.dwCursorPosition.Y == info.dwSize.Y-1) { + orgPosition.Y -= 1; + position.Y -= 1; + } + printf("%c", cmd[pos]); + } + SetConsoleCursorPosition(hOut, position); + } + else { + if (position.X == info.dwSize.X-1 && position.Y == info.dwSize.Y-1) { + orgPosition.Y -= 1; + } + cmd[iCmdBuffer++] = addchars[iBuf]; + iCmdCursor++; + printf("%c", addchars[iBuf]); + } + } + } + if (iCmdBuffer == CMD_BUFLEN) { + printf("Read Console... BUFFER OVERRUN\n"); + iCmdBuffer = 0; + ignoreNext = 1; + } + } + return (SWITCH_STATUS_SUCCESS); +} + + +static BOOL console_readConsole(HANDLE conIn, char* buf, int len, int* pRed, int *key) +{ + DWORD recordIndex, bufferIndex, toRead, red; + PINPUT_RECORD pInput; + + GetNumberOfConsoleInputEvents(conIn, &toRead); + if (len < (int)toRead) { + toRead = len; + } + if (toRead == 0) { + return(FALSE); + } + + if ((pInput = (PINPUT_RECORD) malloc(toRead * sizeof(INPUT_RECORD))) == NULL) { + return (FALSE); + } + *key = 0; + ReadConsoleInput(conIn, pInput, toRead, &red); + + for (recordIndex = bufferIndex = 0; recordIndex < red; recordIndex++) { + KEY_EVENT_RECORD keyEvent = pInput[recordIndex].Event.KeyEvent; + if (pInput[recordIndex].EventType == KEY_EVENT && keyEvent.bKeyDown) { + if (keyEvent.wVirtualKeyCode == 38 && keyEvent.wVirtualScanCode == 72) { + buf[0] = 0; + console_history(buf, -1); + *key = KEY_UP; + bufferIndex += (DWORD)strlen(buf); + } + if (keyEvent.wVirtualKeyCode == 40 && keyEvent.wVirtualScanCode == 80) { + buf[0] = 0; + console_history(buf, 1); + *key = KEY_DOWN; + bufferIndex += (DWORD)strlen(buf); + } + if (keyEvent.wVirtualKeyCode == 112 && keyEvent.wVirtualScanCode == 59) { + console_fnkey_pressed(1); + } + if (keyEvent.wVirtualKeyCode == 113 && keyEvent.wVirtualScanCode == 60) { + console_fnkey_pressed(2); + } + if (keyEvent.wVirtualKeyCode == 114 && keyEvent.wVirtualScanCode == 61) { + console_fnkey_pressed(3); + } + if (keyEvent.wVirtualKeyCode == 115 && keyEvent.wVirtualScanCode == 62) { + console_fnkey_pressed(4); + } + if (keyEvent.wVirtualKeyCode == 116 && keyEvent.wVirtualScanCode == 63) { + console_fnkey_pressed(5); + } + if (keyEvent.wVirtualKeyCode == 117 && keyEvent.wVirtualScanCode == 64) { + console_fnkey_pressed(6); + } + if (keyEvent.wVirtualKeyCode == 118 && keyEvent.wVirtualScanCode == 65) { + console_fnkey_pressed(7); + } + if (keyEvent.wVirtualKeyCode == 119 && keyEvent.wVirtualScanCode == 66) { + console_fnkey_pressed(8); + } + if (keyEvent.wVirtualKeyCode == 120 && keyEvent.wVirtualScanCode == 67) { + console_fnkey_pressed(9); + } + if (keyEvent.wVirtualKeyCode == 121 && keyEvent.wVirtualScanCode == 68) { + console_fnkey_pressed(10); + } + if (keyEvent.wVirtualKeyCode == 122 && keyEvent.wVirtualScanCode == 87) { + console_fnkey_pressed(11); + } + if (keyEvent.wVirtualKeyCode == 123 && keyEvent.wVirtualScanCode == 88) { + console_fnkey_pressed(12); + } + if (keyEvent.uChar.AsciiChar == 9) { + *key = KEY_TAB; + break; + } + if (keyEvent.uChar.AsciiChar == 27) { + *key = CLEAR_OP; + break; + } + if (keyEvent.wVirtualKeyCode == 37 && keyEvent.wVirtualScanCode == 75) { + *key = KEY_LEFT; + } + if (keyEvent.wVirtualKeyCode == 39 && keyEvent.wVirtualScanCode == 77) { + *key = KEY_RIGHT; + } + if (keyEvent.wVirtualKeyCode == 45 && keyEvent.wVirtualScanCode == 82) { + *key = KEY_INSERT; + } + while (keyEvent.wRepeatCount && keyEvent.uChar.AsciiChar) { + buf[bufferIndex] = keyEvent.uChar.AsciiChar; + if (buf[bufferIndex] == '\r') { + buf[bufferIndex] = '\n'; + } + bufferIndex++; + keyEvent.wRepeatCount--; + } + } + } + + free(pInput); + *pRed = bufferIndex; + return (TRUE); +} +#endif + + SWITCH_DECLARE(void) switch_console_loop(void) { - - char cmd[2048] = ""; + char cmd[CMD_BUFLEN+1] = ""; int32_t activity = 1; #ifndef _MSC_VER int x = 0; +#else + char keys[80]; #endif + /* Load/Init the config first */ + console_xml_config(); gethostname(hostname, sizeof(hostname)); +#ifdef _MSC_VER + sprintf(cmd, "\nfreeswitch@%s> ", hostname); + console_bufferInput (0, 0, cmd, PROMPT_OP); + memset(cmd, 0, sizeof(cmd)); +#endif while (running) { int32_t arg; #ifdef _MSC_VER - DWORD read, i; + int read, key; HANDLE stdinHandle = GetStdHandle(STD_INPUT_HANDLE); - INPUT_RECORD in[128]; #else fd_set rfds, efds; struct timeval tv = { 0, 20000 }; @@ -1025,29 +1412,17 @@ SWITCH_DECLARE(void) switch_console_loop(void) } #ifdef _MSC_VER activity = 0; - PeekConsoleInput(stdinHandle, in, 128, &read); - for (i = 0; i < read; i++) { - if (in[i].EventType == KEY_EVENT && !in[i].Event.KeyEvent.bKeyDown) { + if (console_readConsole(stdinHandle, keys, (int)sizeof(keys), &read, &key)) { + if (console_bufferInput(keys, read, cmd, key)) { + if (!strcmp(cmd, "Empty")) { + cmd[0] = '\n'; + cmd[1] = 0; + } activity = 1; - break; + running = switch_console_process(cmd, 0); + memset(cmd, 0, sizeof(cmd)); } } - - if (activity) { - DWORD bytes = 0; - char *end; - ReadConsole(stdinHandle, cmd, sizeof(cmd), &bytes, NULL); - FlushConsoleInputBuffer(stdinHandle); - end = end_of_p(cmd); - while(*end == '\r' || *end == '\n') { - *end-- = '\0'; - } - } - - if (cmd[0]) { - running = switch_console_process(cmd, 0); - memset(cmd, 0, sizeof(cmd)); - } Sleep(20); #else FD_ZERO(&rfds);