static VOID WaitForKey (VOID) { DWORD dwWritten; WriteFile (hStdErr, szCont , szContLength, &dwWritten, NULL); ConInKey(); WriteFile (hStdErr, _T("\n"), 1, &dwWritten, NULL); // FlushConsoleInputBuffer (hConsoleIn); }
INT CommandChoice (LPTSTR param) { LPTSTR lpOptions; TCHAR Options[6]; LPTSTR lpText = NULL; BOOL bNoPrompt = FALSE; BOOL bCaseSensitive = FALSE; BOOL bTimeout = FALSE; INT nTimeout = 0; TCHAR cDefault = _T('\0'); INPUT_RECORD ir; LPTSTR p, np; LPTSTR *arg; INT argc; INT i; INT val; INT GCret; TCHAR Ch; DWORD amount,clk; LoadString(CMD_ModuleHandle, STRING_CHOICE_OPTION, Options, 4); lpOptions = Options; if (_tcsncmp (param, _T("/?"), 2) == 0) { ConOutResPaging(TRUE,STRING_CHOICE_HELP); return 0; } /* retrieve text */ p = param; while (TRUE) { if (*p == _T('\0')) break; if (*p != _T('/')) { lpText = p; break; } np = _tcschr (p, _T(' ')); if (!np) break; p = np + 1; } /* build parameter array */ arg = split (param, &argc, FALSE); /* evaluate arguments */ if (argc > 0) { for (i = 0; i < argc; i++) { if (_tcsnicmp (arg[i], _T("/c"), 2) == 0) { if (arg[i][2] == _T(':')) lpOptions = &arg[i][3]; else lpOptions = &arg[i][2]; if (_tcslen (lpOptions) == 0) { ConErrResPuts(STRING_CHOICE_ERROR); freep (arg); return 1; } } else if (_tcsnicmp (arg[i], _T("/n"), 2) == 0) { bNoPrompt = TRUE; } else if (_tcsnicmp (arg[i], _T("/s"), 2) == 0) { bCaseSensitive = TRUE; } else if (_tcsnicmp (arg[i], _T("/t"), 2) == 0) { LPTSTR s; if (arg[i][2] == _T(':')) { cDefault = arg[i][3]; s = &arg[i][4]; } else { cDefault = arg[i][2]; s = &arg[i][3]; } if (*s != _T(',')) { ConErrResPuts(STRING_CHOICE_ERROR_TXT); freep (arg); return 1; } s++; nTimeout = _ttoi(s); bTimeout = TRUE; } else if (arg[i][0] == _T('/')) { ConErrResPrintf(STRING_CHOICE_ERROR_OPTION, arg[i]); freep (arg); return 1; } } } /* print text */ if (lpText) ConOutPrintf (_T("%s"), lpText); /* print options */ if (bNoPrompt == FALSE) { ConOutPrintf (_T("[%c"), lpOptions[0]); for (i = 1; (unsigned)i < _tcslen (lpOptions); i++) ConOutPrintf (_T(",%c"), lpOptions[i]); ConOutPrintf (_T("]?")); } ConInFlush (); if(!bTimeout) { while (TRUE) { ConInKey (&ir); val = IsKeyInString (lpOptions, #ifdef _UNICODE ir.Event.KeyEvent.uChar.UnicodeChar, #else ir.Event.KeyEvent.uChar.AsciiChar, #endif bCaseSensitive); if (val >= 0) { ConOutPrintf (_T("%c\n"), lpOptions[val]); nErrorLevel = val + 1; break; } Beep (440, 50); } freep (arg); TRACE ("ErrorLevel: %d\n", nErrorLevel); return 0; } clk = GetTickCount (); amount = nTimeout*1000; loop: GCret = GetCharacterTimeout (&Ch, amount - (GetTickCount () - clk)); switch (GCret) { case GC_TIMEOUT: TRACE ("GC_TIMEOUT\n"); TRACE ("elapsed %d msecs\n", GetTickCount () - clk); break; case GC_NOKEY: TRACE ("GC_NOKEY\n"); TRACE ("elapsed %d msecs\n", GetTickCount () - clk); goto loop; case GC_KEYREAD: TRACE ("GC_KEYREAD\n"); TRACE ("elapsed %d msecs\n", GetTickCount () - clk); TRACE ("read %c", Ch); if ((val=IsKeyInString(lpOptions,Ch,bCaseSensitive))==-1) { Beep (440, 50); goto loop; } cDefault=Ch; break; } TRACE ("exiting wait loop after %d msecs\n", GetTickCount () - clk); val = IsKeyInString (lpOptions, cDefault, bCaseSensitive); ConOutPrintf (_T("%c\n"), lpOptions[val]); nErrorLevel = val + 1; freep (arg); TRACE ("ErrorLevel: %d\n", nErrorLevel); return 0; }
/* read in a command line */ BOOL ReadCommand(LPTSTR str, INT maxlen) { CONSOLE_SCREEN_BUFFER_INFO csbi; SHORT orgx; /* origin x/y */ SHORT orgy; SHORT curx; /*current x/y cursor position*/ SHORT cury; SHORT tempscreen; INT count; /*used in some for loops*/ INT current = 0; /*the position of the cursor in the string (str)*/ INT charcount = 0;/*chars in the string (str)*/ INPUT_RECORD ir; #ifdef FEATURE_UNIX_FILENAME_COMPLETION WORD wLastKey = 0; #endif TCHAR ch; BOOL bReturn = FALSE; BOOL bCharInput; #ifdef FEATURE_4NT_FILENAME_COMPLETION TCHAR szPath[MAX_PATH]; #endif #ifdef FEATURE_HISTORY //BOOL bContinue=FALSE;/*is TRUE the second case will not be executed*/ TCHAR PreviousChar; #endif if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { /* No console */ HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); DWORD dwRead; CHAR chr; do { if (!ReadFile(hStdin, &chr, 1, &dwRead, NULL) || !dwRead) return FALSE; #ifdef _UNICODE MultiByteToWideChar(InputCodePage, 0, &chr, 1, &str[charcount++], 1); #endif } while (chr != '\n' && charcount < maxlen); str[charcount] = _T('\0'); return TRUE; } /* get screen size */ maxx = csbi.dwSize.X; maxy = csbi.dwSize.Y; curx = orgx = csbi.dwCursorPosition.X; cury = orgy = csbi.dwCursorPosition.Y; memset (str, 0, maxlen * sizeof (TCHAR)); SetCursorType (bInsert, TRUE); do { bReturn = FALSE; ConInKey (&ir); if (ir.Event.KeyEvent.dwControlKeyState & (RIGHT_ALT_PRESSED |LEFT_ALT_PRESSED| RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED) ) { switch (ir.Event.KeyEvent.wVirtualKeyCode) { #ifdef FEATURE_HISTORY case 'K': /*add the current command line to the history*/ if (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) { if (str[0]) History(0,str); ClearCommandLine (str, maxlen, orgx, orgy); current = charcount = 0; curx = orgx; cury = orgy; //bContinue=TRUE; break; } case 'D': /*delete current history entry*/ if (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) { ClearCommandLine (str, maxlen, orgx, orgy); History_del_current_entry(str); current = charcount = _tcslen (str); ConOutPrintf (_T("%s"), str); GetCursorXY (&curx, &cury); //bContinue=TRUE; break; } #endif /*FEATURE_HISTORY*/ } } bCharInput = FALSE; switch (ir.Event.KeyEvent.wVirtualKeyCode) { case VK_BACK: /* <BACKSPACE> - delete character to left of cursor */ if (current > 0 && charcount > 0) { if (current == charcount) { /* if at end of line */ str[current - 1] = _T('\0'); if (GetCursorX () != 0) { ConOutPrintf (_T("\b \b")); curx--; } else { SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1)); ConOutChar (_T(' ')); SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1)); cury--; curx = maxx - 1; } } else { for (count = current - 1; count < charcount; count++) str[count] = str[count + 1]; if (GetCursorX () != 0) { SetCursorXY ((SHORT)(GetCursorX () - 1), GetCursorY ()); curx--; } else { SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1)); cury--; curx = maxx - 1; } GetCursorXY (&curx, &cury); ConOutPrintf (_T("%s "), &str[current - 1]); SetCursorXY (curx, cury); } charcount--; current--; } break; case VK_INSERT: /* toggle insert/overstrike mode */ bInsert ^= TRUE; SetCursorType (bInsert, TRUE); break; case VK_DELETE: /* delete character under cursor */ if (current != charcount && charcount > 0) { for (count = current; count < charcount; count++) str[count] = str[count + 1]; charcount--; GetCursorXY (&curx, &cury); ConOutPrintf (_T("%s "), &str[current]); SetCursorXY (curx, cury); } break; case VK_HOME: /* goto beginning of string */ if (current != 0) { SetCursorXY (orgx, orgy); curx = orgx; cury = orgy; current = 0; } break; case VK_END: /* goto end of string */ if (current != charcount) { SetCursorXY (orgx, orgy); ConOutPrintf (_T("%s"), str); GetCursorXY (&curx, &cury); current = charcount; } break; case VK_TAB: #ifdef FEATURE_UNIX_FILENAME_COMPLETION /* expand current file name */ if ((current == charcount) || (current == charcount - 1 && str[current] == _T('"'))) /* only works at end of line*/ { if (wLastKey != VK_TAB) { /* if first TAB, complete filename*/ tempscreen = charcount; CompleteFilename (str, charcount); charcount = _tcslen (str); current = charcount; SetCursorXY (orgx, orgy); ConOutPrintf (_T("%s"), str); if (tempscreen > charcount) { GetCursorXY (&curx, &cury); for (count = tempscreen - charcount; count--; ) ConOutChar (_T(' ')); SetCursorXY (curx, cury); } else { if (((charcount + orgx) / maxx) + orgy > maxy - 1) orgy += maxy - ((charcount + orgx) / maxx + orgy + 1); } /* set cursor position */ SetCursorXY ((orgx + current) % maxx, orgy + (orgx + current) / maxx); GetCursorXY (&curx, &cury); } else { /*if second TAB, list matches*/ if (ShowCompletionMatches (str, charcount)) { PrintPrompt(); GetCursorXY(&orgx, &orgy); ConOutPrintf(_T("%s"), str); /* set cursor position */ SetCursorXY((orgx + current) % maxx, orgy + (orgx + current) / maxx); GetCursorXY(&curx, &cury); } } } else { MessageBeep(-1); } #endif #ifdef FEATURE_4NT_FILENAME_COMPLETION /* used to later see if we went down to the next line */ tempscreen = charcount; szPath[0]=_T('\0'); /* str is the whole things that is on the current line that is and and out. arg 2 is weather it goes back one file or forward one file */ CompleteFilename(str, !(ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED), szPath, current); /* Attempt to clear the line */ ClearCommandLine (str, maxlen, orgx, orgy); curx = orgx; cury = orgy; current = charcount = 0; /* Everything is deleted, lets add it back in */ _tcscpy(str,szPath); /* Figure out where cusor is going to be after we print it */ charcount = _tcslen(str); current = charcount; SetCursorXY(orgx, orgy); /* Print out what we have now */ ConOutPrintf(_T("%s"), str); /* Move cursor accordingly */ if (tempscreen > charcount) { GetCursorXY(&curx, &cury); for(count = tempscreen - charcount; count--; ) ConOutChar(_T(' ')); SetCursorXY(curx, cury); } else { if (((charcount + orgx) / maxx) + orgy > maxy - 1) orgy += maxy - ((charcount + orgx) / maxx + orgy + 1); } SetCursorXY((short)(((int)orgx + current) % maxx), (short)((int)orgy + ((int)orgx + current) / maxx)); GetCursorXY(&curx, &cury); #endif break; case _T('M'): case _T('C'): /* ^M does the same as return */ bCharInput = TRUE; if (!(ir.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED))) { break; } case VK_RETURN: /* end input, return to main */ #ifdef FEATURE_HISTORY /* add to the history */ if (str[0]) History (0, str); #endif str[charcount++] = _T('\n'); str[charcount] = _T('\0'); ConOutChar(_T('\n')); bReturn = TRUE; break; case VK_ESCAPE: /* clear str Make this callable! */ ClearCommandLine (str, maxlen, orgx, orgy); curx = orgx; cury = orgy; current = charcount = 0; break; #ifdef FEATURE_HISTORY case VK_F3: History_move_to_bottom(); #endif case VK_UP: #ifdef FEATURE_HISTORY /* get previous command from buffer */ ClearCommandLine (str, maxlen, orgx, orgy); History (-1, str); current = charcount = _tcslen (str); if (((charcount + orgx) / maxx) + orgy > maxy - 1) orgy += maxy - ((charcount + orgx) / maxx + orgy + 1); ConOutPrintf (_T("%s"), str); GetCursorXY (&curx, &cury); #endif break; case VK_DOWN: #ifdef FEATURE_HISTORY /* get next command from buffer */ ClearCommandLine (str, maxlen, orgx, orgy); History (1, str); current = charcount = _tcslen (str); if (((charcount + orgx) / maxx) + orgy > maxy - 1) orgy += maxy - ((charcount + orgx) / maxx + orgy + 1); ConOutPrintf (_T("%s"), str); GetCursorXY (&curx, &cury); #endif break; case VK_LEFT: /* move cursor left */ if (current > 0) { current--; if (GetCursorX () == 0) { SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1)); curx = maxx - 1; cury--; } else { SetCursorXY ((SHORT)(GetCursorX () - 1), GetCursorY ()); curx--; } } else { MessageBeep (-1); } break; case VK_RIGHT: /* move cursor right */ if (current != charcount) { current++; if (GetCursorX () == maxx - 1) { SetCursorXY (0, (SHORT)(GetCursorY () + 1)); curx = 0; cury++; } else { SetCursorXY ((SHORT)(GetCursorX () + 1), GetCursorY ()); curx++; } } #ifdef FEATURE_HISTORY else { LPCTSTR last = PeekHistory(-1); if (last && charcount < (INT)_tcslen (last)) { PreviousChar = last[current]; ConOutChar(PreviousChar); GetCursorXY(&curx, &cury); str[current++] = PreviousChar; charcount++; } } #endif break; default: /* This input is just a normal char */ bCharInput = TRUE; } #ifdef _UNICODE ch = ir.Event.KeyEvent.uChar.UnicodeChar; if (ch >= 32 && (charcount != (maxlen - 2)) && bCharInput) #else ch = ir.Event.KeyEvent.uChar.AsciiChar; if ((UCHAR)ch >= 32 && (charcount != (maxlen - 2)) && bCharInput) #endif /* _UNICODE */ { /* insert character into string... */ if (bInsert && current != charcount) { /* If this character insertion will cause screen scrolling, * adjust the saved origin of the command prompt. */ tempscreen = _tcslen(str + current) + curx; if ((tempscreen % maxx) == (maxx - 1) && (tempscreen / maxx) + cury == (maxy - 1)) { orgy--; cury--; } for (count = charcount; count > current; count--) str[count] = str[count - 1]; str[current++] = ch; if (curx == maxx - 1) curx = 0, cury++; else curx++; ConOutPrintf (_T("%s"), &str[current - 1]); SetCursorXY (curx, cury); charcount++; } else { if (current == charcount) charcount++; str[current++] = ch; if (GetCursorX () == maxx - 1 && GetCursorY () == maxy - 1) orgy--, cury--; if (GetCursorX () == maxx - 1) curx = 0, cury++; else curx++; ConOutChar (ch); } } //wLastKey = ir.Event.KeyEvent.wVirtualKeyCode; } while (!bReturn); SetCursorType (bInsert, TRUE); #ifdef FEATURE_ALIASES /* expand all aliases */ ExpandAlias (str, maxlen); #endif /* FEATURE_ALIAS */ return TRUE; }
void DisplayHelp( const char * unrecognized_option ) { static const char *valid_help_requests[] = { "-help", "--help", "help", "-h", "/h", "/?", "-?", "?", "/help" }; static const char *helpheader[] = { "distributed.net v" CLIENT_VERSIONSTRING " client for " CLIENT_OS_NAME_EXTENDED, "Visit http://faq.distributed.net/ for in-depth command line help", "-------------------------------------------------------------------------" }; int headerlines, bodylines, footerlines; int startline, maxscreenlines, maxpagesize; int i, key, nopaging = (!ConIsScreen()); char linebuffer[128]; if (ConGetSize(NULL,&maxscreenlines) == -1) maxscreenlines = 25; headerlines = (sizeof(helpheader) / sizeof(char *)); bodylines = (sizeof(helpbody) / sizeof(char *)); footerlines = 2; startline = 0; maxpagesize = maxscreenlines - (headerlines + footerlines); #if defined(NO_INTERNAL_PAGING) nopaging = 1; #endif /* -------------------------------------------------- */ if (unrecognized_option && *unrecognized_option) { int goodopt = 0; for (i = 0; ((goodopt == 0) && (i < (int) (sizeof(valid_help_requests)/sizeof(char *)))); i++) { int n=0; for (;((valid_help_requests[i][n])!=0 && unrecognized_option[n]!=0);n++) { if (tolower(valid_help_requests[i][n])!=tolower(unrecognized_option[n])) break; } goodopt = ((valid_help_requests[i][n])==0 && unrecognized_option[n]==0); } if (!goodopt) { if (strlen(unrecognized_option) > 25) LogScreenRaw( "\nUnrecognized option '%25.25s...'\n\n", unrecognized_option); else LogScreenRaw( "\nUnrecognized option '%s'\n\n", unrecognized_option); LogScreenRaw( "The following list of command line switches may be obtained\n" "at any time by running the client with the '-help' option.\n\n"); if (!nopaging) { LogScreenRaw("Press enter to continue... "); key = ConInKey(-1); /* -1 == wait forever. returns zero if break. */ LogScreenRaw( "\r \r" ); if (CheckExitRequestTriggerNoIO()) return; if (key != '\n' && key != '\r' && key != ' ') return; } } } /* -------------------------------------------------- */ if (nopaging || (maxscreenlines > (headerlines+bodylines))) { for (i = 0; i < headerlines; i++) LogScreenRaw( "%s\n", helpheader[i] ); for (i = 0; i < bodylines; i++) LogScreenRaw( "%s\n", helpbody[i] ); return; } /* -------------------------------------------------- */ key = 0; do { if (key == 0) /* refresh required */ { ConClear(); for (i = 0; i < headerlines; i++) LogScreenRaw( "%s\n", helpheader[i] ); for (i = startline; i < (startline+maxpagesize); i++) LogScreenRaw( "%s\n", helpbody[i] ); LogScreenRaw("\n"); } if (startline == 0) strcpy( linebuffer, "Press '+' for the next page,"); else if (startline >= ((bodylines-maxpagesize)-1)) strcpy( linebuffer, "Press '-' for the previous page,"); else strcpy( linebuffer, "Press '+' or '-' for the next/previous page,"); strcat( linebuffer, " 'Esc' or 'Q' to quit... "); LogScreenRaw( linebuffer ); key = ConInKey(-1); linebuffer[i=strlen(linebuffer)]='\r'; linebuffer[i+1]=0; for (--i; i > 0; i--) linebuffer[i]=' '; linebuffer[0]='\r'; LogScreenRaw( linebuffer ); if (CheckExitRequestTriggerNoIO()) break; if (key == '+' || key == '=' || key == ' ' || key == 'f' || key == '\r' || key == '\n') { if (startline <= ((bodylines-maxpagesize) - 1)) { startline += maxpagesize; if ( startline >= (bodylines-maxpagesize)) startline = (bodylines-maxpagesize); key = 0; //refresh required } else if (key == ' ' || key == '\r' || key == '\n') { key = -1; // quit if space or enter pressed on last page } } else if (key == '-' || key == 'b') { if (startline > 0) { startline -= maxpagesize; if ( startline < 0 ) startline = 0; key = 0; //refresh required } } else { key = -1; //unknown keystroke, so quit } } while (key >= 0); return; }