Added patches from Guillaume Serre and Justin. Changed copy to strip *.* from target
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1008
This commit is contained in:
parent
f64cceafdf
commit
27d7b02a31
4 changed files with 164 additions and 68 deletions
|
@ -50,14 +50,13 @@ void SHELL_AddAutoexec(char * line,...) {
|
|||
sprintf((autoexec_data+auto_len),"%s\r\n",buf);
|
||||
}
|
||||
|
||||
|
||||
DOS_Shell::DOS_Shell():Program(){
|
||||
input_handle=STDIN;
|
||||
echo=true;
|
||||
exit=false;
|
||||
bf=0;
|
||||
memset(&old.buffer,0,CMD_OLDSIZE);
|
||||
old.size=0;
|
||||
|
||||
completion_start = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,11 +64,14 @@ DOS_Shell::DOS_Shell():Program(){
|
|||
|
||||
Bit32u DOS_Shell::GetRedirection(char *s, char **ifn, char **ofn) {
|
||||
|
||||
char *output = strrchr(s, '>');
|
||||
if (output) {
|
||||
*output = 0;
|
||||
// while (!isalnum(*output)) output++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void DOS_Shell::ParseLine(char * line) {
|
||||
|
||||
|
@ -81,7 +83,7 @@ void DOS_Shell::ParseLine(char * line) {
|
|||
line=trim(line);
|
||||
Bit32u num=0; /* Number of commands in this line */
|
||||
|
||||
num = GetRedirection(line,&in, &out);
|
||||
num = GetRedirection(line, &in, &out);
|
||||
|
||||
/* TODO in and out redirection */
|
||||
|
||||
|
|
|
@ -24,31 +24,30 @@
|
|||
|
||||
|
||||
static SHELL_Cmd cmd_list[]={
|
||||
{ "CD", 0, &DOS_Shell::CMD_CHDIR, "SHELL_CMD_CHDIR_HELP"},
|
||||
{ "CHDIR", 0, &DOS_Shell::CMD_CHDIR, "SHELL_CMD_CHDIR_HELP"},
|
||||
{ "CD", 1, &DOS_Shell::CMD_CHDIR, "SHELL_CMD_CHDIR_HELP"},
|
||||
{ "CLS", 0, &DOS_Shell::CMD_CLS, "SHELL_CMD_CLS_HELP"},
|
||||
{ "COPY", 0, &DOS_Shell::CMD_COPY, "SHELL_CMD_COPY_HELP"},
|
||||
{ "DIR", 0, &DOS_Shell::CMD_DIR, "SHELL_CMD_DIR_HELP"},
|
||||
{ "DEL", 1, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"},
|
||||
{ "DELETE", 0, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"},
|
||||
{ "ERASE", 1, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"},
|
||||
{ "ECHO", 0, &DOS_Shell::CMD_ECHO, "SHELL_CMD_ECHO_HELP"},
|
||||
{ "ECHO.", 1, &DOS_Shell::CMD_EHCODOT, "SHELL_CMD_ECHO_HELP"},
|
||||
{ "EXIT", 0, &DOS_Shell::CMD_EXIT, "SHELL_CMD_EXIT_HELP"},
|
||||
{ "HELP", 0, &DOS_Shell::CMD_HELP, "SHELL_CMD_HELP_HELP"},
|
||||
{ "MD", 0, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP"},
|
||||
{ "RD", 0, &DOS_Shell::CMD_RMDIR, "SHELL_CMD_RMDIR_HELP"},
|
||||
{ "MKDIR", 0, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP"},
|
||||
{ "MD", 1, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP"},
|
||||
{ "RMDIR", 0, &DOS_Shell::CMD_RMDIR, "SHELL_CMD_RMDIR_HELP"},
|
||||
{ "RD", 1, &DOS_Shell::CMD_RMDIR, "SHELL_CMD_RMDIR_HELP"},
|
||||
{ "SET", 0, &DOS_Shell::CMD_SET, "SHELL_CMD_SET_HELP"},
|
||||
{ "IF", 0, &DOS_Shell::CMD_IF, "SHELL_CMD_IF_HELP"},
|
||||
{ "IF", 0, &DOS_Shell::CMD_IF, "SHELL_CMD_IF_HELP"},
|
||||
{ "GOTO", 0, &DOS_Shell::CMD_GOTO, "SHELL_CMD_GOTO_HELP"},
|
||||
{ "TYPE", 0, &DOS_Shell::CMD_TYPE, "SHELL_CMD_TYPE_HELP"},
|
||||
{ "REM", 0, &DOS_Shell::CMD_REM, "SHELL_CMD_REM_HELP"},
|
||||
{ "RENAME", 0, &DOS_Shell::CMD_RENAME, "SHELL_CMD_RENAME_HELP"},
|
||||
{ "REN", 1, &DOS_Shell::CMD_RENAME, "SHELL_CMD_RENAME_HELP"},
|
||||
{ "PAUSE", 0, &DOS_Shell::CMD_PAUSE, "SHELL_CMD_PAUSE_HELP"},
|
||||
/*
|
||||
"CHDIR", 0, &DOS_Shell::CMD_CHDIR, "Change Directory",
|
||||
"MKDIR", 0, &DOS_Shell::CMD_MKDIR, "Make Directory",
|
||||
"RMDIR", 0, &DOS_Shell::CMD_RMDIR, "Remove Directory",
|
||||
*/
|
||||
{ 0,0,0,0}
|
||||
};
|
||||
|
||||
|
@ -235,7 +234,7 @@ void DOS_Shell::CMD_DIR(char * args) {
|
|||
|
||||
/* Make a full path in the args */
|
||||
if (!DOS_Canonicalize(args,path)) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_ILLEGAL_PATH"));
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
return;
|
||||
}
|
||||
*(strrchr(path,'\\')+1)=0;
|
||||
|
@ -332,7 +331,7 @@ void DOS_Shell::CMD_COPY(char * args) {
|
|||
char pathTarget[DOS_PATHLENGTH];
|
||||
|
||||
if (!DOS_Canonicalize(source,pathSource)) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_ILLEGAL_PATH"));
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
return;
|
||||
}
|
||||
// cut search pattern
|
||||
|
@ -340,10 +339,13 @@ void DOS_Shell::CMD_COPY(char * args) {
|
|||
if (pos) *(pos+1) = 0;
|
||||
|
||||
if (!DOS_Canonicalize(target,pathTarget)) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_ILLEGAL_PATH"));
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
return;
|
||||
}
|
||||
// add '\\' if target is a directoy
|
||||
char* temp = strstr(pathTarget,"*.*");
|
||||
if(temp) *temp = 0;//strip off *.* from target
|
||||
|
||||
// add '\\' if target is a directoy
|
||||
if (pathTarget[strlen(pathTarget)-1]!='\\') {
|
||||
if (DOS_FindFirst(pathTarget,0xffff)) {
|
||||
dta.GetResult(name,size,date,time,attr);
|
||||
|
@ -520,8 +522,8 @@ void DOS_Shell::CMD_REM(char * args) {
|
|||
}
|
||||
|
||||
void DOS_Shell::CMD_PAUSE(char * args){
|
||||
WriteOut(MSG_Get("SHELL_CMD_PAUSE"));
|
||||
Bit8u c;Bit16u n=1;
|
||||
WriteOut(MSG_Get("SHELL_CMD_PAUSE"));
|
||||
Bit8u c;Bit16u n=1;
|
||||
DOS_ReadFile (STDIN,&c,&n);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#include "callback.h"
|
||||
#include "setup.h"
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#define CMD_MAXLINE 4096
|
||||
#define CMD_MAXCMDS 20
|
||||
#define CMD_OLDSIZE 4096
|
||||
|
@ -46,11 +49,19 @@ public:
|
|||
CommandLine * cmd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DOS_Shell : public Program {
|
||||
|
||||
private:
|
||||
|
||||
std::list<std::string> l_history, l_completion;
|
||||
|
||||
char *completion_start;
|
||||
Bit16u completion_index;
|
||||
|
||||
public:
|
||||
|
||||
DOS_Shell();
|
||||
|
||||
void Run(void);
|
||||
void RunInternal(void); //for command /C
|
||||
/* A load of subfunctions */
|
||||
|
@ -87,12 +98,6 @@ public:
|
|||
BatchFile * bf;
|
||||
bool echo;
|
||||
bool exit;
|
||||
struct {
|
||||
char buffer[CMD_OLDSIZE];
|
||||
Bitu index;
|
||||
Bitu size;
|
||||
} old;
|
||||
|
||||
};
|
||||
|
||||
struct SHELL_Cmd {
|
||||
|
|
|
@ -40,11 +40,14 @@ static void outs(char * str) {
|
|||
}
|
||||
|
||||
void DOS_Shell::InputCommand(char * line) {
|
||||
char * prev=old.buffer;
|
||||
char * reader;
|
||||
Bitu size=CMD_MAXLINE-1;
|
||||
Bit8u c;Bit16u n=1;
|
||||
Bitu str_len=0;Bitu str_index=0;
|
||||
Bit16u len;
|
||||
|
||||
line[0] = '\0';
|
||||
|
||||
std::list<std::string>::iterator it_history = l_history.begin(), it_completion = l_completion.begin();
|
||||
|
||||
while (size) {
|
||||
dos.echo=false;
|
||||
|
@ -58,41 +61,75 @@ void DOS_Shell::InputCommand(char * line) {
|
|||
{
|
||||
DOS_ReadFile(input_handle,&c,&n);
|
||||
switch (c) {
|
||||
|
||||
case 0x3d: /* F3 */
|
||||
if (strlen(old.buffer)>str_len) {
|
||||
reader=&old.buffer[str_len];
|
||||
while ((c=*reader++)) {
|
||||
line[str_index]=c;
|
||||
str_len++;
|
||||
str_index++;
|
||||
size--;
|
||||
if (!l_history.size()) break;
|
||||
it_history = l_history.begin();
|
||||
if (it_history != l_history.end() && it_history->length() > str_len) {
|
||||
const char *reader = &(it_history->c_str())[str_len];
|
||||
while ((c = *reader++)) {
|
||||
line[str_index ++] = c;
|
||||
DOS_WriteFile(STDOUT,&c,&n);
|
||||
}
|
||||
str_len = str_index = it_history->length();
|
||||
size = CMD_MAXLINE - str_index - 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
case 0x4B: /* LEFT */
|
||||
if (str_index) {
|
||||
outc(8);
|
||||
str_index --;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x4D: /* RIGHT */
|
||||
if (str_index < str_len) {
|
||||
outc(line[str_index++]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x48: /* UP */
|
||||
if (it_history == l_history.end()) break;
|
||||
|
||||
for (;str_index>0; str_index--) {
|
||||
// removes all characters
|
||||
outc(8); outc(' '); outc(8);
|
||||
}
|
||||
strcpy(line, it_history->c_str());
|
||||
len = it_history->length();
|
||||
str_len = str_index = len;
|
||||
size = CMD_MAXLINE - str_index - 1;
|
||||
DOS_WriteFile(STDOUT, (Bit8u *)line, &len);
|
||||
|
||||
it_history ++;
|
||||
if (it_history == l_history.end()) it_history = l_history.begin();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
break;
|
||||
case 0x08: /* BackSpace */
|
||||
if (str_index>0) {
|
||||
Bit32u str_remain=str_len-str_index;
|
||||
if (str_index) {
|
||||
outc(8);
|
||||
Bit32u str_remain=str_len - str_index;
|
||||
if (str_remain) {
|
||||
memcpy(&line[str_index-1],&line[str_index],str_remain);
|
||||
line[str_len]=0;
|
||||
memmove(&line[str_index-1],&line[str_index],str_remain);
|
||||
line[--str_len]=0;
|
||||
str_index --;
|
||||
/* Go back to redraw */
|
||||
for (;str_remain>0;str_remain--) {
|
||||
outc(8);
|
||||
}
|
||||
for (Bit16u i=str_index; i < str_len; i++)
|
||||
outc(line[i]);
|
||||
} else {
|
||||
line[--str_index] = '\0';
|
||||
str_len--;
|
||||
}
|
||||
str_index--;str_len--;
|
||||
outc(8);
|
||||
outc(' ');
|
||||
outc(8);
|
||||
|
||||
outc(' '); outc(8);
|
||||
// moves the cursor left
|
||||
while (str_remain--) outc(8);
|
||||
}
|
||||
break;
|
||||
case 0x0a: /* New Line not handled */
|
||||
|
@ -103,35 +140,85 @@ void DOS_Shell::InputCommand(char * line) {
|
|||
size=0; //Kill the while loop
|
||||
break;
|
||||
case'\t':
|
||||
{
|
||||
Bit8u c=' ';Bit16u n=1;
|
||||
for(Bitu i=0; i !=4 ;i++)
|
||||
{
|
||||
line[str_index]=c;
|
||||
str_len++;//This should depend on insert being active
|
||||
str_index++;
|
||||
size--;
|
||||
DOS_WriteFile(STDOUT,&c,&n);
|
||||
{
|
||||
if (l_completion.size()) {
|
||||
it_completion ++;
|
||||
if (it_completion == l_completion.end()) it_completion = l_completion.begin();
|
||||
} else {
|
||||
// build new completion list
|
||||
|
||||
// get completion mask
|
||||
char *completion_start = strrchr(line, ' ');
|
||||
|
||||
if (completion_start) {
|
||||
completion_start ++;
|
||||
completion_index = str_index - strlen(completion_start);
|
||||
} else {
|
||||
completion_start = line;
|
||||
completion_index = 0;
|
||||
}
|
||||
|
||||
// build the completion list
|
||||
char mask[DOS_PATHLENGTH];
|
||||
if (completion_start) {
|
||||
strcpy(mask, completion_start);
|
||||
// not perfect when line already contains wildcards, but works
|
||||
strcat(mask, "*.*");
|
||||
} else {
|
||||
strcpy(mask, "*.*");
|
||||
}
|
||||
|
||||
bool res = DOS_FindFirst(mask, 0xffff & ~DOS_ATTR_VOLUME);
|
||||
if (!res) break; // TODO: beep
|
||||
|
||||
DOS_DTA dta(dos.dta);
|
||||
char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr;
|
||||
|
||||
while (res) {
|
||||
dta.GetResult(name,size,date,time,attr);
|
||||
// add result to completion list
|
||||
|
||||
if (strcmp(name, ".") && strcmp(name, ".."))
|
||||
l_completion.push_back(name);
|
||||
|
||||
res=DOS_FindNext();
|
||||
}
|
||||
|
||||
it_completion = l_completion.begin();
|
||||
}
|
||||
|
||||
if (it_completion->length()) {
|
||||
for (;str_index > completion_index; str_index--) {
|
||||
// removes all characters
|
||||
outc(8); outc(' '); outc(8);
|
||||
}
|
||||
|
||||
strcpy(&line[completion_index], it_completion->c_str());
|
||||
len = it_completion->length();
|
||||
str_len = str_index = completion_index + len;
|
||||
size = CMD_MAXLINE - str_index - 1;
|
||||
DOS_WriteFile(STDOUT, (Bit8u *)it_completion->c_str(), &len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (l_completion.size()) l_completion.clear();
|
||||
line[str_index]=c;
|
||||
str_index ++;
|
||||
if (str_index > str_len) line[str_index] = '\0';
|
||||
str_len++;//This should depend on insert being active
|
||||
str_index++;
|
||||
size--;
|
||||
DOS_WriteFile(STDOUT,&c,&n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* String is inputted now save it in the buffer */
|
||||
line[str_len]=0;
|
||||
|
||||
if (!str_len) return;
|
||||
str_len++;
|
||||
//Not quite perfect last entries can get screwed :)
|
||||
size_t first_len=strlen(old.buffer)+1;
|
||||
memmove(&old.buffer[first_len],&old.buffer[0],CMD_OLDSIZE-first_len);
|
||||
strcpy(old.buffer,line);
|
||||
|
||||
// add command line to history
|
||||
l_history.push_front(line); it_history = l_history.begin();
|
||||
if (l_completion.size()) l_completion.clear();
|
||||
}
|
||||
|
||||
void DOS_Shell::Execute(char * name,char * args) {
|
||||
|
|
Loading…
Add table
Reference in a new issue