static BOOL ReadCommand( PCONSOLE_STATE State, LPSTR str, INT maxlen) { 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; CHAR ch; BOOL bReturn = FALSE; BOOL bCharInput; #ifdef FEATURE_HISTORY //BOOL bContinue=FALSE;/*is TRUE the second case will not be executed*/ CHAR PreviousChar; #endif CONSOLE_GetCursorXY(&orgx, &orgy); curx = orgx; cury = orgy; memset(str, 0, maxlen * sizeof(CHAR)); CONSOLE_SetCursorType(State->bInsert, TRUE); do { bReturn = FALSE; CONSOLE_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 = strlen (str); ConOutPrintf("%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] = L'\0'; if (CONSOLE_GetCursorX () != 0) { CONSOLE_ConOutPrintf("\b \b"); curx--; } else { CONSOLE_SetCursorXY((SHORT)(State->maxx - 1), (SHORT)(CONSOLE_GetCursorY () - 1)); CONSOLE_ConOutChar(' '); CONSOLE_SetCursorXY((SHORT)(State->maxx - 1), (SHORT)(CONSOLE_GetCursorY () - 1)); cury--; curx = State->maxx - 1; } } else { for (count = current - 1; count < charcount; count++) str[count] = str[count + 1]; if (CONSOLE_GetCursorX () != 0) { CONSOLE_SetCursorXY ((SHORT)(CONSOLE_GetCursorX () - 1), CONSOLE_GetCursorY ()); curx--; } else { CONSOLE_SetCursorXY ((SHORT)(State->maxx - 1), (SHORT)(CONSOLE_GetCursorY () - 1)); cury--; curx = State->maxx - 1; } CONSOLE_GetCursorXY(&curx, &cury); CONSOLE_ConOutPrintf("%s ", &str[current - 1]); CONSOLE_SetCursorXY(curx, cury); } charcount--; current--; } break; case VK_INSERT: /* toggle insert/overstrike mode */ State->bInsert ^= TRUE; CONSOLE_SetCursorType(State->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--; CONSOLE_GetCursorXY(&curx, &cury); CONSOLE_ConOutPrintf("%s ", &str[current]); CONSOLE_SetCursorXY(curx, cury); } break; case VK_HOME: /* goto beginning of string */ if (current != 0) { CONSOLE_SetCursorXY(orgx, orgy); curx = orgx; cury = orgy; current = 0; } break; case VK_END: /* goto end of string */ if (current != charcount) { CONSOLE_SetCursorXY(orgx, orgy); CONSOLE_ConOutPrintf("%s", str); CONSOLE_GetCursorXY(&curx, &cury); current = charcount; } break; case 'M': case '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] = '\0'; CONSOLE_ConOutChar('\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 = strlen (str); if (((charcount + orgx) / maxx) + orgy > maxy - 1) orgy += maxy - ((charcount + orgx) / maxx + orgy + 1); CONSOLE_ConOutPrintf("%s", str); CONSOLE_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 = strlen (str); if (((charcount + orgx) / maxx) + orgy > maxy - 1) orgy += maxy - ((charcount + orgx) / maxx + orgy + 1); CONSOLE_ConOutPrintf("%s", str); CONSOLE_GetCursorXY(&curx, &cury); #endif break; case VK_LEFT: /* move cursor left */ if (current > 0) { current--; if (CONSOLE_GetCursorX() == 0) { CONSOLE_SetCursorXY((SHORT)(State->maxx - 1), (SHORT)(CONSOLE_GetCursorY () - 1)); curx = State->maxx - 1; cury--; } else { CONSOLE_SetCursorXY((SHORT)(CONSOLE_GetCursorX () - 1), CONSOLE_GetCursorY ()); curx--; } } break; case VK_RIGHT: /* move cursor right */ if (current != charcount) { current++; if (CONSOLE_GetCursorX() == State->maxx - 1) { CONSOLE_SetCursorXY(0, (SHORT)(CONSOLE_GetCursorY () + 1)); curx = 0; cury++; } else { CONSOLE_SetCursorXY((SHORT)(CONSOLE_GetCursorX () + 1), CONSOLE_GetCursorY ()); curx++; } } #ifdef FEATURE_HISTORY else { LPCSTR last = PeekHistory(-1); if (last && charcount < (INT)strlen (last)) { PreviousChar = last[current]; CONSOLE_ConOutChar(PreviousChar); CONSOLE_GetCursorXY(&curx, &cury); str[current++] = PreviousChar; charcount++; } } #endif break; default: /* This input is just a normal char */ bCharInput = TRUE; } ch = ir.Event.KeyEvent.uChar.UnicodeChar; if (ch >= 32 && (charcount != (maxlen - 2)) && bCharInput) { /* insert character into string... */ if (State->bInsert && current != charcount) { /* If this character insertion will cause screen scrolling, * adjust the saved origin of the command prompt. */ tempscreen = strlen(str + current) + curx; if ((tempscreen % State->maxx) == (State->maxx - 1) && (tempscreen / State->maxx) + cury == (State->maxy - 1)) { orgy--; cury--; } for (count = charcount; count > current; count--) str[count] = str[count - 1]; str[current++] = ch; if (curx == State->maxx - 1) curx = 0, cury++; else curx++; CONSOLE_ConOutPrintf("%s", &str[current - 1]); CONSOLE_SetCursorXY(curx, cury); charcount++; } else { if (current == charcount) charcount++; str[current++] = ch; if (CONSOLE_GetCursorX () == State->maxx - 1 && CONSOLE_GetCursorY () == State->maxy - 1) orgy--, cury--; if (CONSOLE_GetCursorX () == State->maxx - 1) curx = 0, cury++; else curx++; CONSOLE_ConOutChar(ch); } } } while (!bReturn); CONSOLE_SetCursorType(State->bInsert, TRUE); return TRUE; }
void C4Application::ParseCommandLine(int argc, char * argv[]) { StdStrBuf CmdLine("Command line:"); for(int i = 0; i < argc; ++i) { CmdLine.Append(" "); CmdLine.Append(argv[i]); } Log(CmdLine.getData()); ClearCommandLine(); Game.NetworkActive = false; isEditor = 2; int c; while (1) { static struct option long_options[] = { // option, w/ argument?, set directly, set to... {"editor", no_argument, &isEditor, 1}, {"fullscreen", no_argument, &isEditor, 0}, {"debugwait", no_argument, &Game.DebugWait, 1}, {"update", no_argument, &CheckForUpdates, 1}, {"noruntimejoin", no_argument, &Config.Network.NoRuntimeJoin, 1}, {"runtimejoin", no_argument, &Config.Network.NoRuntimeJoin, 0}, {"noleague", no_argument, &Config.Network.LeagueServerSignUp, 0}, {"league", no_argument, &Config.Network.LeagueServerSignUp, 1}, {"nosignup", no_argument, &Config.Network.MasterServerSignUp, 0}, {"signup", no_argument, &Config.Network.MasterServerSignUp, 1}, {"debugrecread", required_argument, 0, 'K'}, {"debugrecwrite", required_argument, 0, 'w'}, {"client", required_argument, 0, 'c'}, {"host", no_argument, 0, 'h'}, {"debughost", required_argument, 0, 'H'}, {"debugpass", required_argument, 0, 'P'}, {"debug", required_argument, 0, 'D'}, {"data", required_argument, 0, 'd'}, {"startup", required_argument, 0, 's'}, {"stream", required_argument, 0, 'e'}, {"recdump", required_argument, 0, 'R'}, {"comment", required_argument, 0, 'm'}, {"pass", required_argument, 0, 'p'}, {"udpport", required_argument, 0, 'u'}, {"tcpport", required_argument, 0, 't'}, {"join", required_argument, 0, 'j'}, {"language", required_argument, 0, 'L'}, {"scenpar", required_argument, 0, 'S'}, {"observe", no_argument, 0, 'o'}, {"nonetwork", no_argument, 0, 'N'}, {"network", no_argument, 0, 'n'}, {"record", no_argument, 0, 'r'}, {"lobby", required_argument, 0, 'l'}, {"debug-opengl", no_argument, &Config.Graphics.DebugOpenGL, 1}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long (argc, argv, "abc:d:f:", long_options, &option_index); // no more options if (c == -1) break; switch (c) { case 0: // Signup if (SEqualNoCase(long_options[option_index].name, "signup")) { Game.NetworkActive = true; } // League if (SEqualNoCase(long_options[option_index].name, "league")) { Game.NetworkActive = true; Config.Network.MasterServerSignUp = true; } break; // Lobby case 'l': Game.fLobby = true; // lobby timeout specified? (e.g. --lobby=120) if (optarg) { Game.iLobbyTimeout = atoi(optarg); if (Game.iLobbyTimeout < 0) Game.iLobbyTimeout = 0; } break; case 'o': Game.fObserve = true; break; // Direct join case 'j': Game.NetworkActive = true; SCopy(optarg, Game.DirectJoinAddress, _MAX_PATH); break; case 'K': if (optarg && optarg[0]) { LogF("Reading from DebugRec file '%s'", optarg); SCopy(optarg, Config.General.DebugRecExternalFile, _MAX_PATH); } else Log("Reading DebugRec from CtrlRec file in scenario record"); Config.General.DebugRec = 1; Config.General.DebugRecWrite = 0; break; case 'w': if (optarg && optarg[0]) { LogF("Writing to DebugRec file '%s'", optarg); SCopy(optarg, Config.General.DebugRecExternalFile, _MAX_PATH); } else Log("Writing DebugRec to CtrlRec file in scenario record"); Config.General.DebugRec = 1; Config.General.DebugRecWrite = 1; break; case 'r': Game.Record = true; break; case 'n': Game.NetworkActive = true; break; case 'N': Game.NetworkActive = false; break; // Language override by parameter case 'L': SCopy(optarg, Config.General.LanguageEx, CFG_MaxString); // port overrides case 't': Config.Network.PortTCP = atoi(optarg); break; case 'u': Config.Network.PortUDP = atoi(optarg); break; // network game password case 'p': Network.SetPassword(optarg); break; // network game comment case 'm': Config.Network.Comment.CopyValidated(optarg); break; // record dump case 'R': Game.RecordDumpFile.Copy(optarg); break; // record stream case 'e': Game.RecordStream.Copy(optarg); break; // startup start screen case 's': C4Startup::SetStartScreen(optarg); break; // additional read-only data path case 'd': Reloc.AddPath(optarg); break; // debug options case 'D': Game.DebugPort = atoi(optarg); break; case 'P': Game.DebugPassword = optarg; break; case 'H': Game.DebugHost = optarg; break; // set custom scenario parameter by command line case 'S': { StdStrBuf sopt, soptval; sopt.Copy(optarg); int32_t val=1; if (sopt.SplitAtChar('=', &soptval)) val=atoi(soptval.getData()); Game.StartupScenarioParameters.SetValue(sopt.getData(), val, false); } break; // debug configs case 'h': Game.NetworkActive = true; Game.fLobby = true; Config.Network.PortTCP = 11112; Config.Network.PortUDP = 11113; Config.Network.MasterServerSignUp = Config.Network.LeagueServerSignUp = false; break; case 'c': Game.NetworkActive = true; SCopy("localhost", Game.DirectJoinAddress, _MAX_PATH); Game.fLobby = true; Config.Network.PortTCP = 11112 + 2*(atoi(optarg)+1); Config.Network.PortUDP = 11113 + 2*(atoi(optarg)+1); break; case '?': /* getopt_long already printed an error message. */ break; default: assert(!"unexpected getopt_long return value"); } } if (!Config.Network.MasterServerSignUp) Config.Network.LeagueServerSignUp = false; if (Game.fObserve || Game.fLobby) Game.NetworkActive = true; while (optind < argc) { char * szParameter = argv[optind++]; { // Strip trailing / that result from tab-completing unpacked c4groups int iLen = SLen(szParameter); if (iLen > 5 && szParameter[iLen-1] == '/' && szParameter[iLen-5] == '.' && szParameter[iLen-4] == 'o' && szParameter[iLen-3] == 'c') { szParameter[iLen-1] = '\0'; } } // Scenario file if (SEqualNoCase(GetExtension(szParameter),"ocs")) { if(IsGlobalPath(szParameter)) Game.SetScenarioFilename(szParameter); else Game.SetScenarioFilename((std::string(GetWorkingDirectory()) + DirSep + szParameter).c_str()); continue; } if (SEqualNoCase(GetFilename(szParameter),"scenario.txt")) { Game.SetScenarioFilename(szParameter); continue; } // Player file if (SEqualNoCase(GetExtension(szParameter),"ocp")) { if(IsGlobalPath(szParameter)) SAddModule(Game.PlayerFilenames, szParameter); else SAddModule(Game.PlayerFilenames, (std::string(GetWorkingDirectory()) + DirSep + szParameter).c_str()); continue; } // Definition file if (SEqualNoCase(GetExtension(szParameter),"ocd")) { SAddModule(Game.DefinitionFilenames,szParameter); continue; } // Key file if (SEqualNoCase(GetExtension(szParameter),"c4k")) { Application.IncomingKeyfile.Copy(szParameter); continue; } // Update file if (SEqualNoCase(GetExtension(szParameter),"ocu")) { Application.IncomingUpdate.Copy(szParameter); continue; } // record stream if (SEqualNoCase(GetExtension(szParameter),"c4r")) { Game.RecordStream.Copy(szParameter); } // Direct join by URL if (SEqual2NoCase(szParameter, "clonk:")) { // Store address SCopy(szParameter + 6, Game.DirectJoinAddress, _MAX_PATH); SClearFrontBack(Game.DirectJoinAddress, '/'); // Special case: if the target address is "update" then this is used for update initiation by url if (SEqualNoCase(Game.DirectJoinAddress, "update")) { Application.CheckForUpdates = true; Game.DirectJoinAddress[0] = 0; continue; } // Self-enable network Game.NetworkActive = true; continue; } } #ifdef _WIN32 // Clean up some forward/backward slach confusion since many internal OC file functions cannot handle both SReplaceChar(Game.ScenarioFilename, AltDirectorySeparator, DirectorySeparator); SReplaceChar(Game.PlayerFilenames, AltDirectorySeparator, DirectorySeparator); SReplaceChar(Game.DefinitionFilenames, AltDirectorySeparator, DirectorySeparator); Application.IncomingKeyfile.ReplaceChar(AltDirectorySeparator, DirectorySeparator); Application.IncomingUpdate.ReplaceChar(AltDirectorySeparator, DirectorySeparator); Game.RecordStream.ReplaceChar(AltDirectorySeparator, DirectorySeparator); #endif // Default to editor if scenario given, player mode otherwise if (isEditor == 2) isEditor = !!*Game.ScenarioFilename && !Config.General.OpenScenarioInGameMode; // record? Game.Record = Game.Record || (Config.Network.LeagueServerSignUp && Game.NetworkActive); // startup dialog required? QuitAfterGame = !isEditor && Game.HasScenario(); }
/* 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; }