DBCS awareness for \ character

This commit is contained in:
Wengier 2021-06-24 04:25:03 -04:00
parent 53e18d7fe0
commit 16aff755d2
11 changed files with 146 additions and 104 deletions

View File

@ -70,6 +70,8 @@
now use internal Japanese font (also used by DOS/V
and JEGA systems) in addition to built-in 8x16 SBCS
font pre-generated from FREECG98.BMP. (Wengier)
- Added support for DBCS aware of the character "\"
in CJK code pages. (Wengier)
- The config option ttf.halfwidthkana (now in [ttf]
section) will enable low ASCII boxing characters
for the TrueType font (TTF) output too. This option

View File

@ -47,7 +47,7 @@
#define CROSS_FILESPLIT '\\'
#define F_OK 0
#else
#define CROSS_FILENAME(blah) strreplace(blah,'\\','/')
#define CROSS_FILENAME(blah) strreplace_dbcs(blah,'\\','/')
#define CROSS_FILESPLIT '/'
#endif

View File

@ -35,6 +35,7 @@
#include <strings.h>
#endif
void strreplace_dbcs(char * str,char o,char n);
void strreplace(char * str,char o,char n);
char *ltrim(char *str);
char *rtrim(char *str);

View File

@ -66,8 +66,8 @@ int sdrive = 0;
* internally by LFN and image handling functions. For non-LFN calls the value is fixed to
* be LFN_FILEFIND_NONE as defined in drives.h. */
int lfn_filefind_handle = LFN_FILEFIND_NONE;
extern uint8_t lead[6];
bool shiftjis_lead_byte(int c), isDBCSCP(), isDBCSLB(uint8_t chr, uint8_t* lead);
bool isDBCSCP(), isKanji1(uint8_t chr), shiftjis_lead_byte(int c);
char *strchr_dbcs(char *str, char ch), *strrchr_dbcs(char *str, char ch);
uint8_t DOS_GetDefaultDrive(void) {
// return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetDrive();
@ -88,12 +88,6 @@ bool DOS_MakeName(char const * const name,char * const fullname,uint8_t * drive)
DOS_SetError(DOSERR_FILE_NOT_FOUND);
return false;
}
for (int i=0; i<6; i++) lead[i] = 0;
if (isDBCSCP())
for (int i=0; i<6; i++) {
lead[i] = mem_readb(Real2Phys(dos.tables.dbcs)+i);
if (lead[i] == 0) break;
}
char names[LFN_NAMELENGTH];
strcpy(names,name);
char * name_int = names;
@ -137,7 +131,7 @@ bool DOS_MakeName(char const * const name,char * const fullname,uint8_t * drive)
else if (c==' ') continue; /* should be separator */
}
upname[w++]=(char)c;
if (((IS_PC98_ARCH && shiftjis_lead_byte(c)) || (isDBCSCP() && isDBCSLB(c, lead))) && r<DOS_PATHLENGTH) {
if (((IS_PC98_ARCH && shiftjis_lead_byte(c)) || (isDBCSCP() && isKanji1(c))) && r<DOS_PATHLENGTH) {
/* The trailing byte is NOT ASCII and SHOULD NOT be converted to uppercase like ASCII */
upname[w++]=name_int[r++];
}
@ -150,16 +144,22 @@ bool DOS_MakeName(char const * const name,char * const fullname,uint8_t * drive)
if (upname[0]!='\\') strcpy(fullname,Drives[*drive]->curdir);
else fullname[0]=0;
uint32_t lastdir=0;uint32_t t=0;
bool lead = false;
while (fullname[t]!=0) {
if ((fullname[t]=='\\') && (fullname[t+1]!=0)) lastdir=t;
if (lead) lead = false;
else if ((IS_PC98_ARCH && shiftjis_lead_byte(fullname[t])) || (isDBCSCP() && isKanji1(fullname[t]))) lead = true;
else if ((fullname[t]=='\\') && (fullname[t+1]!=0)) lastdir=t;
t++;
}
r=0;w=0;
tempdir[0]=0;
lead=false;
bool stop=false;
while (!stop) {
if (upname[r]==0) stop=true;
if ((upname[r]=='\\') || (upname[r]==0)){
if (lead) lead=false;
else if ((IS_PC98_ARCH && shiftjis_lead_byte(upname[r])) || (isDBCSCP() && isKanji1(upname[r]))) lead=true;
else if ((upname[r]=='\\') || (upname[r]==0)){
if (upname[r]==0) stop=true;
tempdir[w]=0;
if (tempdir[0]==0) { w=0;r++;continue;}
if (strcmp(tempdir,".")==0) {
@ -251,7 +251,7 @@ bool DOS_GetSFNPath(char const * const path,char * SFNPath,bool LFN) {
dos.dta(dos.tables.tempdta);
DOS_DTA dta(dos.dta());
int fbak=lfn_filefind_handle;
for (char *s = strchr(p,'\\'); s != NULL; s = strchr(p,'\\')) {
for (char *s = strchr_dbcs(p,'\\'); s != NULL; s = strchr_dbcs(p,'\\')) {
*s = 0;
if (SFNPath[strlen(SFNPath)-1]=='\\')
sprintf(pdir,"\"%s%s\"",SFNPath,p);
@ -409,11 +409,11 @@ bool DOS_RemoveDir(char const * const dir) {
}
static bool PathExists(char const * const name) {
const char* leading = strrchr(name,'\\');
const char* leading = strrchr_dbcs((char *)name,'\\');
if(!leading) return true;
char temp[CROSS_LEN];
strcpy(temp,name);
char * lead = strrchr(temp,'\\');
char * lead = strrchr_dbcs(temp,'\\');
if (lead == temp) return true;
*lead = 0;
uint8_t drive;char fulldir[DOS_PATHLENGTH];
@ -436,7 +436,7 @@ bool DOS_Rename(char const * const oldname,char const * const newname) {
if (!control->SecureMode()&&(dos_clipboard_device_access==3||dos_clipboard_device_access==4)) {
if (DOS_FindDevice(oldname) == DOS_DEVICES) {
const char* find_last;
find_last=strrchr(fullnew,'\\');
find_last=strrchr_dbcs(fullnew,'\\');
if (find_last==NULL) find_last=fullnew;
else find_last++;
if (!strcasecmp(find_last, *dos_clipboard_device_name?dos_clipboard_device_name:"CLIP$"))
@ -503,8 +503,7 @@ bool DOS_FindFirst(const char * search,uint16_t attr,bool fcb_findfirst) {
bool device = (DOS_FindDevice(search) != DOS_DEVICES);
/* Split the search in dir and pattern */
char * find_last;
find_last=strrchr(fullsearch,'\\');
char * find_last = strrchr_dbcs(fullsearch,'\\');
if (!find_last) { /*No dir */
strcpy(pattern,fullsearch);
dir[0]=0;
@ -884,7 +883,7 @@ bool DOS_UnlinkFile(char const * const name) {
}
if (!strchr(name,'\"')||!DOS_GetSFNPath(("\""+std::string(fullname)+"\"").c_str(), fname, false))
strcpy(fname, fullname);
char * find_last=strrchr(fname,'\\');
char * find_last=strrchr_dbcs(fname,'\\');
if (!find_last) {
dir[0]=0;
strcpy(pattern, fname);
@ -947,7 +946,7 @@ bool DOS_GetFileAttr(char const * const name,uint16_t * attr) {
#if defined (WIN32)
if (!control->SecureMode()&&dos_clipboard_device_access) {
const char* find_last;
find_last=strrchr(fullname,'\\');
find_last=strrchr_dbcs(fullname,'\\');
if (find_last==NULL) find_last=fullname;
else find_last++;
if (!strcasecmp(find_last, *dos_clipboard_device_name?dos_clipboard_device_name:"CLIP$"))
@ -1252,12 +1251,6 @@ static bool isvalid(const char in){
#define PARSE_RET_BADDRIVE 0xff
uint8_t FCB_Parsename(uint16_t seg,uint16_t offset,uint8_t parser ,char *string, uint8_t *change) {
for (int i=0; i<6; i++) lead[i] = 0;
if (isDBCSCP())
for (int i=0; i<6; i++) {
lead[i] = mem_readb(Real2Phys(dos.tables.dbcs)+i);
if (lead[i] == 0) break;
}
const char* string_begin = string;
uint8_t ret=0;
if (!(parser & PARSE_DFLT_DRIVE)) {
@ -1324,7 +1317,7 @@ uint8_t FCB_Parsename(uint16_t seg,uint16_t offset,uint8_t parser ,char *string,
/* Copy the name */
while (true) {
unsigned char nc = *reinterpret_cast<unsigned char*>(&string[0]);
if ((IS_PC98_ARCH && shiftjis_lead_byte(nc)) || (isDBCSCP() && isDBCSLB(nc, lead))) {
if ((IS_PC98_ARCH && shiftjis_lead_byte(nc)) || (isDBCSCP() && isKanji1(nc))) {
/* Shift-JIS is NOT ASCII and SHOULD NOT be converted to uppercase like ASCII */
fcb_name.part.name[index]=(char)nc;
string++;
@ -1362,14 +1355,14 @@ checkext:
hasext=true;finished=false;fill=' ';index=0;
while (true) {
unsigned char nc = *reinterpret_cast<unsigned char*>(&string[0]);
if ((IS_PC98_ARCH && shiftjis_lead_byte(nc)) || (isDBCSCP() && isDBCSLB(nc, lead))) {
/* Shift-JIS is NOT ASCII and SHOULD NOT be converted to uppercase like ASCII */
if ((IS_PC98_ARCH && shiftjis_lead_byte(nc)) || (isDBCSCP() && isKanji1(nc))) {
/* DBCS is NOT ASCII and SHOULD NOT be converted to uppercase like ASCII */
fcb_name.part.ext[index]=(char)nc;
string++;
index++;
if (index >= 3) break;
/* should be trailing byte of Shift-JIS */
/* should be trailing byte of DBCS character */
if (nc < 32u || nc >= 127u) continue;
fcb_name.part.ext[index]=(char)nc;

View File

@ -41,6 +41,8 @@
int fileInfoCounter = 0;
char *strrchr_dbcs(char *str, char ch);
bool SortByName(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b) {
return strcmp(a->shortname,b->shortname)<0;
}
@ -179,7 +181,7 @@ char* DOS_Drive_Cache::GetExpandName(const char* path) {
work[0] = 0;
strcpy (dir,path);
const char* pos = strrchr(path,CROSS_FILESPLIT);
const char* pos = strrchr_dbcs((char *)path,CROSS_FILESPLIT);
if (pos) dir[pos-path+1] = 0;
CFileInfo* dirInfo = FindDirInfo(dir, work);

View File

@ -48,6 +48,7 @@ static uint32_t dnum[256];
extern bool wpcolon, force_sfn;
extern int lfn_filefind_handle;
void dos_ver_menu(bool start);
char *strrchr_dbcs(char *str, char ch);
bool systemmessagebox(char const * aTitle, char const * aMessage, char const * aDialogType, char const * aIconType, int aDefaultButton);
bool filename_not_8x3(const char *n) {
@ -2139,12 +2140,12 @@ bool fatDrive::FileCreate(DOS_File **file, const char *name, uint16_t attributes
/* NTS: "name" is the full relative path. For LFN creation to work we need only the final element of the path */
if (uselfn && !force_sfn) {
lfn = strrchr(name,'\\');
lfn = strrchr_dbcs((char *)name,'\\');
if (lfn != NULL) {
lfn++; /* step past '\' */
strcpy(path, name);
*(strrchr(path,'\\')+1)=0;
*(strrchr_dbcs(path,'\\')+1)=0;
} else {
lfn = name; /* no path elements */
*path=0;
@ -2877,12 +2878,12 @@ bool fatDrive::MakeDir(const char *dir) {
/* NTS: "dir" is the full relative path. For LFN creation to work we need only the final element of the path */
if (uselfn && !force_sfn) {
lfn = strrchr(dir,'\\');
lfn = strrchr_dbcs((char *)dir,'\\');
if (lfn != NULL) {
lfn++; /* step past '\' */
strcpy(path, dir);
*(strrchr(path,'\\')+1)=0;
*(strrchr_dbcs(path,'\\')+1)=0;
} else {
lfn = dir; /* no path elements */
*path=0;
@ -3047,12 +3048,12 @@ bool fatDrive::Rename(const char * oldname, const char * newname) {
/* NTS: "newname" is the full relative path. For LFN creation to work we need only the final element of the path */
if (uselfn && !force_sfn) {
lfn = strrchr(newname,'\\');
lfn = strrchr_dbcs((char *)newname,'\\');
if (lfn != NULL) {
lfn++; /* step past '\' */
strcpy(path, newname);
*(strrchr(path,'\\')+1)=0;
*(strrchr_dbcs(path,'\\')+1)=0;
} else {
lfn = newname; /* no path elements */
*path=0;

View File

@ -576,7 +576,7 @@ bool isoDrive :: lookup(isoDirEntry *de, const char *path) {
char isoPath[ISO_MAXPATHNAME], longname[ISO_MAXPATHNAME];
safe_strncpy(isoPath, path, ISO_MAXPATHNAME);
strreplace(isoPath, '\\', '/');
strreplace_dbcs(isoPath, '\\', '/');
// iterate over all path elements (name), and search each of them in the current de
for(char* name = strtok(isoPath, "/"); NULL != name; name = strtok(NULL, "/")) {

View File

@ -135,6 +135,7 @@ static std::string hostname = "";
extern bool rsize, morelen, force_sfn, enable_share_exe, isDBCSCP();
extern int lfn_filefind_handle, freesizecap, file_access_tries;
extern unsigned long totalc, freec;
char *strchr_dbcs(char *str, char ch), *strrchr_dbcs(char *str, char ch);
bool String_ASCII_TO_HOST_UTF16(uint16_t *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/) {
const uint16_t* df = d + CROSS_LEN - 1;
@ -3523,7 +3524,7 @@ bool Overlay_Drive::MakeDir(const char * dir) {
}
char newdir[CROSS_LEN],sdir[CROSS_LEN],pdir[CROSS_LEN];
strcpy(sdir,dir);
char *p=strrchr(sdir,'\\');
char *p=strrchr_dbcs(sdir,'\\');
if (p!=NULL) {
*p=0;
char *temp_name=dirCache.GetExpandName(GetCrossedName(basedir,sdir));
@ -3537,7 +3538,7 @@ bool Overlay_Drive::MakeDir(const char * dir) {
strcpy(newdir,overlaydir);
strcat(newdir,sdir);
CROSS_FILENAME(newdir);
p=strrchr(sdir,'\\');
p=strrchr_dbcs(sdir,'\\');
int temp=-1;
bool madepdir=false;
const host_cnv_char_t* host_name;
@ -3681,7 +3682,7 @@ FILE* Overlay_Drive::create_file_in_overlay(const char* dos_filename, char const
f = fopen_wrap(newname,mode);
}
//Check if a directory is part of the name:
char* dir = strrchr((char *)dos_filename,'\\');
char* dir = strrchr_dbcs((char *)dos_filename,'\\');
if (!f && dir && *dir) {
if (logoverlay) LOG_MSG("Overlay: warning creating a file inside a directory %s",dos_filename);
//ensure they exist, else make them in the overlay if they exist in the original....
@ -3689,7 +3690,7 @@ FILE* Overlay_Drive::create_file_in_overlay(const char* dos_filename, char const
//try again
char temp_name[CROSS_LEN],tmp[CROSS_LEN];
strcpy(tmp, dos_filename);
char *p=strrchr(tmp, '\\');
char *p=strrchr_dbcs(tmp, '\\');
assert(p!=NULL);
*p=0;
bool found=false;
@ -3841,7 +3842,7 @@ void Overlay_Drive::convert_overlay_to_DOSname_in_base(char* dirname )
char* p = t;
char* b = t;
while ( (p =strchr(p,CROSS_FILESPLIT)) ) {
while ( (p =strchr_dbcs(p,CROSS_FILESPLIT)) ) {
char directoryname[CROSS_LEN]={0};
char dosboxdirname[CROSS_LEN]={0};
strcpy(directoryname,dirname);
@ -4022,12 +4023,12 @@ void Overlay_Drive::remove_DOSname_from_cache(const char* name) {
}
bool Overlay_Drive::Sync_leading_dirs(const char* dos_filename){
const char* lastdir = strrchr(dos_filename,'\\');
const char* lastdir = strrchr_dbcs((char *)dos_filename,'\\');
//If there are no directories, return success.
if (!lastdir) return true;
const char* leaddir = dos_filename;
while ( (leaddir=strchr(leaddir,'\\')) != 0) {
while ( (leaddir=strchr_dbcs((char *)leaddir,'\\')) != 0) {
char dirname[CROSS_LEN] = {0};
strncpy(dirname,dos_filename,leaddir-dos_filename);
@ -4240,7 +4241,7 @@ void Overlay_Drive::update_cache(bool read_directory_contents) {
dirCache.AddEntryDirOverlay(fakename,sdir,true);
if (strlen(sdir)) {
strcpy(tmp,(*(i+1)).c_str());
p=strrchr(tmp, '\\');
p=strrchr_dbcs(tmp, '\\');
if (p==NULL) *(i+1)=std::string(sdir);
else {
*p=0;
@ -4534,10 +4535,10 @@ bool Overlay_Drive::SetFileAttr(const char * name,uint16_t attr) {
CROSS_FILENAME(overlayname);
char* temp_name = dirCache.GetExpandName(GetCrossedName(basedir,name));
strcpy(tmp, name);
char *q=strrchr(tmp, '\\');
char *q=strrchr_dbcs(tmp, '\\');
if (q!=NULL) *(q+1)=0;
else *tmp=0;
char *p=strrchr(temp_name, '\\');
char *p=strrchr_dbcs(temp_name, '\\');
if (p!=NULL)
strcat(tmp,p+1);
else
@ -4676,10 +4677,10 @@ bool Overlay_Drive::GetFileAttr(const char * name,uint16_t * attr) {
CROSS_FILENAME(overlayname);
char* temp_name = dirCache.GetExpandName(GetCrossedName(basedir,name));
strcpy(tmp, name);
char *q=strrchr(tmp, '\\');
char *q=strrchr_dbcs(tmp, '\\');
if (q!=NULL) *(q+1)=0;
else *tmp=0;
char *p=strrchr(temp_name, '\\');
char *p=strrchr_dbcs(temp_name, '\\');
if (p!=NULL)
strcat(tmp,p+1);
else
@ -4752,10 +4753,10 @@ void Overlay_Drive::add_deleted_file(const char* name,bool create_on_disk) {
CROSS_FILENAME(tname);
char* temp_name = dirCache.GetExpandName(tname);
strcpy(tname, name);
char *q=strrchr(tname, '\\');
char *q=strrchr_dbcs(tname, '\\');
if (q!=NULL) *(q+1)=0;
else *tname=0;
char *p=strrchr(temp_name, '\\');
char *p=strrchr_dbcs(temp_name, '\\');
if (p!=NULL)
strcat(tname,p+1);
else
@ -4865,10 +4866,10 @@ bool Overlay_Drive::is_deleted_file(const char* name) {
CROSS_FILENAME(tname);
char* temp_name = dirCache.GetExpandName(tname);
strcpy(tname, name);
char *q=strrchr(tname, '\\');
char *q=strrchr_dbcs(tname, '\\');
if (q!=NULL) *(q+1)=0;
else *tname=0;
char *p=strrchr(temp_name, '\\');
char *p=strrchr_dbcs(temp_name, '\\');
if (p!=NULL)
strcat(tname,p+1);
else
@ -4917,10 +4918,10 @@ void Overlay_Drive::remove_deleted_file(const char* name,bool create_on_disk) {
CROSS_FILENAME(tname);
char* temp_name = dirCache.GetExpandName(tname);
strcpy(tname, name);
char *q=strrchr(tname, '\\');
char *q=strrchr_dbcs(tname, '\\');
if (q!=NULL) *(q+1)=0;
else *tname=0;
char *p=strrchr(temp_name, '\\');
char *p=strrchr_dbcs(temp_name, '\\');
if (p!=NULL)
strcat(tname,p+1);
else
@ -4974,7 +4975,7 @@ void Overlay_Drive::remove_deleted_path(const char* name, bool create_on_disk) {
}
}
bool Overlay_Drive::check_if_leading_is_deleted(const char* name){
const char* dname = strrchr(name,'\\');
const char* dname = strrchr_dbcs((char *)name,'\\');
if (dname != NULL) {
char dirname[CROSS_LEN];
strncpy(dirname,name,dname - name);
@ -5074,7 +5075,7 @@ bool Overlay_Drive::Rename(const char * oldname,const char * newname) {
(host_nameold, CodePageGuestToHost(overlaynameold));
}
strcpy(tmp,newname);
char *p=strrchr(tmp,'\\'), ndir[CROSS_LEN];
char *p=strrchr_dbcs(tmp,'\\'), ndir[CROSS_LEN];
if (p!=NULL) {
*p=0;
temp_name=dirCache.GetExpandName(GetCrossedName(basedir,tmp));
@ -5144,7 +5145,7 @@ bool Overlay_Drive::Rename(const char * oldname,const char * newname) {
(host_nameold, CodePageGuestToHost(overlaynameold));
}
strcpy(tmp,newname);
char *p=strrchr(tmp,'\\'), ndir[CROSS_LEN];
char *p=strrchr_dbcs(tmp,'\\'), ndir[CROSS_LEN];
if (p!=NULL) {
*p=0;
temp_name=dirCache.GetExpandName(GetCrossedName(basedir,tmp));
@ -5294,7 +5295,7 @@ bool Overlay_Drive::FileStat(const char* name, FileStat_Block * const stat_block
}
if (!success) {
strcpy(tmp,name);
char *p=strrchr(tmp, '\\'), *q=strrchr(temp_name, '\\');
char *p=strrchr_dbcs(tmp, '\\'), *q=strrchr_dbcs(temp_name, '\\');
if (p!=NULL&&q!=NULL) {
*p=0;
for(std::vector<std::string>::iterator it = DOSdirs_cache.begin(); it != DOSdirs_cache.end(); it+=2)

View File

@ -36,6 +36,8 @@
#include "menu.h"
#include "SDL.h"
extern bool isDBCSCP(), isKanji1(uint8_t chr), shiftjis_lead_byte(int c);
void upcase(std::string &str) {
int (*tf)(int) = std::toupper;
std::transform(str.begin(), str.end(), str.begin(), tf);
@ -58,6 +60,34 @@ void trim(std::string &str) {
str.erase(0, empty_pfx);
}
char *strchr_dbcs(char *str, char ch) {
bool lead = false;
int lastpos = -1;
if (ch == '\\' && (IS_PC98_ARCH || isDBCSCP())) {
for (size_t i=0; i<strlen(str); i++) {
if (lead) lead = false;
else if ((IS_PC98_ARCH && shiftjis_lead_byte(str[i])) || (isDBCSCP() && isKanji1(str[i]))) lead = true;
else if (str[i] == '\\') {lastpos = i;break;}
}
return lastpos>-1 ? str + lastpos : NULL;
} else
return strchr(str, ch);
}
char *strrchr_dbcs(char *str, char ch) {
bool lead = false;
int lastpos = -1;
if (ch == '\\' && (IS_PC98_ARCH || isDBCSCP())) {
for (size_t i=0; i<strlen(str); i++) {
if (lead) lead = false;
else if ((IS_PC98_ARCH && shiftjis_lead_byte(str[i])) || (isDBCSCP() && isKanji1(str[i]))) lead = true;
else if (str[i] == '\\') lastpos = i;
}
return lastpos>-1 ? str + lastpos : NULL;
} else
return strrchr(str, ch);
}
/*
Ripped some source from freedos for this one.
@ -68,6 +98,15 @@ void trim(std::string &str) {
* replaces all instances of character o with character c
*/
void strreplace_dbcs(char * str,char o,char n) {
bool lead = false;
while (*str) {
if (lead) lead = false;
else if ((IS_PC98_ARCH && shiftjis_lead_byte(*str)) || (isDBCSCP() && isKanji1(*str))) lead = true;
else if (*str==o) *str=n;
str++;
}
}
void strreplace(char * str,char o,char n) {
while (*str) {

View File

@ -120,6 +120,7 @@ extern unsigned long freec;
extern uint16_t countryNo;
void DOS_SetCountry(uint16_t countryNo);
void GetExpandedPath(std::string &path);
char *strchr_dbcs(char *str, char ch), *strrchr_dbcs(char *str, char ch);
/* support functions */
static char empty_char = 0;
@ -247,8 +248,8 @@ __do_command_begin:
/* This isn't an internal command execute it */
char ldir[CROSS_LEN], *p=ldir;
if (strchr(cmd_buffer,'\"')&&DOS_GetSFNPath(cmd_buffer,ldir,false)) {
if (!strchr(cmd_buffer, '\\') && strrchr(ldir, '\\'))
p=strrchr(ldir, '\\')+1;
if (!strchr_dbcs(cmd_buffer, '\\') && strrchr_dbcs(ldir, '\\'))
p=strrchr_dbcs(ldir, '\\')+1;
if (uselfn&&strchr(p, ' ')&&!DOS_FileExists(("\""+std::string(p)+"\"").c_str())) {
bool append=false;
if (DOS_FileExists(("\""+std::string(p)+".COM\"").c_str())) {append=true;strcat(p, ".COM");}
@ -475,7 +476,7 @@ void DOS_Shell::CMD_DELETE(char * args) {
strcat(args, ".*");
} else if (uselfn&&strchr(args, '*')) {
char * find_last;
find_last=strrchr(args,'\\');
find_last=strrchr_dbcs(args,'\\');
if (find_last==NULL) find_last=args;
else find_last++;
if (strlen(find_last)>0&&args[strlen(args)-1]=='*'&&strchr(find_last, '.')==NULL) strcat(args, ".*");
@ -531,7 +532,7 @@ first_2:
continue_1:
/* Command uses dta so set it to our internal dta */
if (!DOS_Canonicalize(args,full)) { WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));dos.dta(save_dta);return; }
char path[DOS_PATHLENGTH], spath[DOS_PATHLENGTH], pattern[DOS_PATHLENGTH], *r=strrchr(full, '\\');
char path[DOS_PATHLENGTH], spath[DOS_PATHLENGTH], pattern[DOS_PATHLENGTH], *r=strrchr_dbcs(full, '\\');
if (r!=NULL) {
*r=0;
strcpy(path, full);
@ -565,8 +566,8 @@ continue_1:
lfn_filefind_handle=fbak;
//end can't be 0, but if it is we'll get a nice crash, who cares :)
strcpy(sfull,full);
char * end=strrchr(full,'\\')+1;*end=0;
char * lend=strrchr(sfull,'\\')+1;*lend=0;
char * end=strrchr_dbcs(full,'\\')+1;*end=0;
char * lend=strrchr_dbcs(sfull,'\\')+1;*lend=0;
dta=dos.dta();
bool exist=false;
lfn_filefind_handle=uselfn?LFN_FILEFIND_INTERNAL:LFN_FILEFIND_NONE;
@ -648,7 +649,7 @@ std::vector<std::string> tdirs;
static bool doDeltree(DOS_Shell * shell, char * args, DOS_DTA dta, bool optY, bool first) {
char spath[DOS_PATHLENGTH],sargs[DOS_PATHLENGTH+4],path[DOS_PATHLENGTH+4],full[DOS_PATHLENGTH],sfull[DOS_PATHLENGTH+2];
if (!DOS_Canonicalize(args,full)||strrchr(full,'\\')==NULL) { shell->WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));return false; }
if (!DOS_Canonicalize(args,full)||strrchr_dbcs(full,'\\')==NULL) { shell->WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));return false; }
if (!DOS_GetSFNPath(args,spath,false)) {
if (first) shell->WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args);
return false;
@ -672,9 +673,9 @@ static bool doDeltree(DOS_Shell * shell, char * args, DOS_DTA dta, bool optY, bo
}
return true;
}
*(strrchr(path,'\\')+1)=0;
char * end=strrchr(full,'\\')+1;*end=0;
char * lend=strrchr(sfull,'\\')+1;*lend=0;
*(strrchr_dbcs(path,'\\')+1)=0;
char * end=strrchr_dbcs(full,'\\')+1;*end=0;
char * lend=strrchr_dbcs(sfull,'\\')+1;*lend=0;
char name[DOS_NAMELENGTH_ASCII],lname[LFN_NAMELENGTH+1];
uint32_t size;uint16_t time,date;uint8_t attr;uint16_t fattr;
std::vector<std::string> cdirs, cfiles;
@ -733,8 +734,8 @@ static bool doDeltree(DOS_Shell * shell, char * args, DOS_DTA dta, bool optY, bo
cfiles.erase(cfiles.begin());
}
if (!first&&strlen(args)>4&&!strcmp(args+strlen(args)-4,"\\*.*")) {
end=strrchr(full,'\\')+1;*end=0;
lend=strrchr(sfull,'\\')+1;*lend=0;
end=strrchr_dbcs(full,'\\')+1;*end=0;
lend=strrchr_dbcs(sfull,'\\')+1;*lend=0;
if (fdir) {
strcpy(spath, path);
strcat(spath, ".\\.");
@ -771,7 +772,7 @@ void DOS_Shell::CMD_DELTREE(char * args) {
if (uselfn&&strchr(args, '*')) {
char * find_last;
find_last=strrchr(args,'\\');
find_last=strrchr_dbcs(args,'\\');
if (find_last==NULL) find_last=args;
else find_last++;
if (strlen(find_last)>0&&args[strlen(args)-1]=='*'&&strchr(find_last, '.')==NULL) strcat(args, ".*");
@ -840,7 +841,7 @@ static bool doTree(DOS_Shell * shell, char * args, DOS_DTA dta, bool optA, bool
}
if (level>=200) return false;
char spath[DOS_PATHLENGTH],sargs[DOS_PATHLENGTH+4],path[DOS_PATHLENGTH+4],full[DOS_PATHLENGTH],sfull[DOS_PATHLENGTH+2];
if (!DOS_Canonicalize(args,full)||strrchr(full,'\\')==NULL) { shell->WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));return level; }
if (!DOS_Canonicalize(args,full)||strrchr_dbcs(full,'\\')==NULL) { shell->WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));return level; }
if (!DOS_GetSFNPath(args,spath,false)) {
if (!level) shell->WriteOut(MSG_Get("SHELL_CMD_TREE_ERROR"));
return level;
@ -848,7 +849,7 @@ static bool doTree(DOS_Shell * shell, char * args, DOS_DTA dta, bool optA, bool
if (!uselfn||!DOS_GetSFNPath(args,sfull,true)) strcpy(sfull,full);
if (level&&strlen(sfull)>4&&!strcasecmp(sfull+strlen(sfull)-4, "\\*.*")) {
*(sfull+strlen(sfull)-4)=0;
p=strrchr(sfull, '\\');
p=strrchr_dbcs(sfull, '\\');
char c=optA?(last?'\\':'+'):(last?'À':'Ã');
cont[level]=!last;
for (int i=1; i<level; i++) shell->WriteOut("%c ", cont[i]?(optA?'|':'³'):' ');
@ -863,9 +864,9 @@ static bool doTree(DOS_Shell * shell, char * args, DOS_DTA dta, bool optA, bool
}
uint16_t attribute=0;
strcpy(path,full);
*(strrchr(path,'\\')+1)=0;
char * end=strrchr(full,'\\')+1;*end=0;
char * lend=strrchr(sfull,'\\')+1;*lend=0;
*(strrchr_dbcs(path,'\\')+1)=0;
char * end=strrchr_dbcs(full,'\\')+1;*end=0;
char * lend=strrchr_dbcs(sfull,'\\')+1;*lend=0;
char name[DOS_NAMELENGTH_ASCII],lname[LFN_NAMELENGTH+1];
uint32_t size;uint16_t time,date;uint8_t attr;uint16_t fattr;
std::vector<std::string> cdirs;
@ -1023,7 +1024,7 @@ void DOS_Shell::CMD_RENAME(char * args){
char * arg2=StripArg(args);
StripSpaces(args);
if (*args) {SyntaxError();return;}
char* slash = strrchr(arg1,'\\');
char* slash = strrchr_dbcs(arg1,'\\');
uint32_t size;uint16_t date;uint16_t time;uint8_t attr;
char name[DOS_NAMELENGTH_ASCII], lname[LFN_NAMELENGTH+1], tname1[LFN_NAMELENGTH+1], tname2[LFN_NAMELENGTH+1], text1[LFN_NAMELENGTH+1], text2[LFN_NAMELENGTH+1], tfull[CROSS_LEN+2];
//dir_source and target are introduced for when we support multiple files being renamed.
@ -1038,7 +1039,7 @@ void DOS_Shell::CMD_RENAME(char * args){
//Copy first and then modify, makes GCC happy
safe_strncpy(dir_source,arg1,DOS_PATHLENGTH + 4);
char* dummy = strrchr(dir_source,'\\');
char* dummy = strrchr_dbcs(dir_source,'\\');
if (!dummy) dummy = strrchr(dir_source,':');
if (!dummy) { //Possible due to length
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
@ -1046,9 +1047,9 @@ void DOS_Shell::CMD_RENAME(char * args){
}
dummy++;
*dummy = 0;
if (strchr(arg2,'\\')||strchr(arg2,':')) {
if (strchr_dbcs(arg2,'\\')||strchr(arg2,':')) {
safe_strncpy(dir_target,arg2,DOS_PATHLENGTH + 4);
dummy = strrchr(dir_target,'\\');
dummy = strrchr_dbcs(dir_target,'\\');
if (!dummy) dummy = strrchr(dir_target,':');
if (dummy) {
dummy++;
@ -1058,12 +1059,12 @@ void DOS_Shell::CMD_RENAME(char * args){
return;
}
}
arg2=strrchr(arg2,strrchr(arg2,'\\')?'\\':':')+1;
arg2=strrchr_dbcs(arg2,strrchr_dbcs(arg2,'\\')?'\\':':')+1;
}
if (strlen(dummy)&&dummy[strlen(dummy)-1]==':')
strcat(dummy, ".\\");
} else {
if (strchr(arg2,'\\')||strchr(arg2,':')) {SyntaxError();return;};
if (strchr_dbcs(arg2,'\\')||strchr(arg2,':')) {SyntaxError();return;};
strcpy(dir_source, ".\\");
}
@ -1071,7 +1072,7 @@ void DOS_Shell::CMD_RENAME(char * args){
char path[DOS_PATHLENGTH], spath[DOS_PATHLENGTH], pattern[DOS_PATHLENGTH], full[DOS_PATHLENGTH], *r;
if (!DOS_Canonicalize(arg1,full)) return;
r=strrchr(full, '\\');
r=strrchr_dbcs(full, '\\');
if (r!=NULL) {
*r=0;
strcpy(path, full);
@ -1487,7 +1488,7 @@ static bool doDir(DOS_Shell * shell, char * args, DOS_DTA dta, char * numformat,
shell->WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
return true;
}
*(strrchr(path,'\\')+1)=0;
*(strrchr_dbcs(path,'\\')+1)=0;
if (!DOS_GetSFNPath(path,sargs,false)) {
shell->WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
return true;
@ -1667,7 +1668,7 @@ static bool doDir(DOS_Shell * shell, char * args, DOS_DTA dta, char * numformat,
if(result.attr&DOS_ATTR_DIRECTORY && strcmp(result.name, ".")&&strcmp(result.name, "..")) {
strcat(sargs, result.name);
strcat(sargs, "\\");
char *fname = strrchr(args, '\\');
char *fname = strrchr_dbcs(args, '\\');
if (fname==NULL) fname=args;
else fname++;
strcat(sargs, fname);
@ -1836,7 +1837,7 @@ void DOS_Shell::CMD_DIR(char * args) {
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
return;
}
*(strrchr(path,'\\')+1)=0;
*(strrchr_dbcs(path,'\\')+1)=0;
if (!DOS_GetSFNPath(path,sargs,true)) {
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
return;
@ -2128,7 +2129,7 @@ void DOS_Shell::CMD_COPY(char * args) {
if (source_x[source_x_len-1]==':') has_drive_spec = true;
else if (uselfn&&strchr(source_x, '*')) {
char * find_last;
find_last=strrchr(source_x,'\\');
find_last=strrchr_dbcs(source_x,'\\');
if (find_last==NULL) find_last=source_x;
else find_last++;
if (strlen(find_last)>0&&source_x[source_x_len-1]=='*'&&strchr(find_last, '.')==NULL) strcat(source_x, ".*");
@ -2198,7 +2199,7 @@ void DOS_Shell::CMD_COPY(char * args) {
strcpy(pathSource,pathSourcePre);
if (uselfn) sprintf(pathSource,"\"%s\"",pathSourcePre);
// cut search pattern
char* pos = strrchr(pathSource,'\\');
char* pos = strrchr_dbcs(pathSource,'\\');
if (pos) *(pos+1) = 0;
if (!DOS_Canonicalize(const_cast<char*>(target.filename.c_str()),pathTarget)) {
@ -2547,7 +2548,7 @@ void DOS_Shell::CMD_IF(char * args) {
{ /* DOS_FindFirst uses dta so set it to our internal dta */
char spath[DOS_PATHLENGTH], path[DOS_PATHLENGTH], pattern[DOS_PATHLENGTH], full[DOS_PATHLENGTH], *r;
if (!DOS_Canonicalize(word,full)) return;
r=strrchr(full, '\\');
r=strrchr_dbcs(full, '\\');
if (r!=NULL) {
*r=0;
strcpy(path, full);
@ -2564,7 +2565,7 @@ void DOS_Shell::CMD_IF(char * args) {
pattern[k++]=pattern[i];
pattern[k]=0;
strcpy(spath, path);
if (strchr(word,'\"')||uselfn) {
if (strchr_dbcs(word,'\"')||uselfn) {
if (!DOS_GetSFNPath(("\""+std::string(path)+"\\").c_str(), spath, false)) strcpy(spath, path);
if (!strlen(spath)||spath[strlen(spath)-1]!='\\') strcat(spath, "\\");
}
@ -3144,7 +3145,7 @@ void DOS_Shell::CMD_CHOICE(char * args){
static bool doAttrib(DOS_Shell * shell, char * args, DOS_DTA dta, bool optS, bool adda, bool adds, bool addh, bool addr, bool suba, bool subs, bool subh, bool subr) {
char spath[DOS_PATHLENGTH],sargs[DOS_PATHLENGTH+4],path[DOS_PATHLENGTH+4],full[DOS_PATHLENGTH],sfull[DOS_PATHLENGTH+2];
if (!DOS_Canonicalize(args,full)||strrchr(full,'\\')==NULL) { shell->WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));return false; }
if (!DOS_Canonicalize(args,full)||strrchr_dbcs(full,'\\')==NULL) { shell->WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));return false; }
if (!DOS_GetSFNPath(args,spath,false)) {
shell->WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args);
return false;
@ -3155,9 +3156,9 @@ static bool doAttrib(DOS_Shell * shell, char * args, DOS_DTA dta, bool optS, boo
if (!res&&!optS) return false;
//end can't be 0, but if it is we'll get a nice crash, who cares :)
strcpy(path,full);
*(strrchr(path,'\\')+1)=0;
char * end=strrchr(full,'\\')+1;*end=0;
char * lend=strrchr(sfull,'\\')+1;*lend=0;
*(strrchr_dbcs(path,'\\')+1)=0;
char * end=strrchr_dbcs(full,'\\')+1;*end=0;
char * lend=strrchr_dbcs(sfull,'\\')+1;*lend=0;
char name[DOS_NAMELENGTH_ASCII],lname[LFN_NAMELENGTH+1];
uint32_t size;uint16_t time,date;uint8_t attr;uint16_t fattr;
while (res) {
@ -3202,10 +3203,10 @@ static bool doAttrib(DOS_Shell * shell, char * args, DOS_DTA dta, bool optS, boo
DtaResult result;
dta.GetResult(result.name,result.lname,result.size,result.date,result.time,result.attr);
if(result.attr&DOS_ATTR_DIRECTORY && strcmp(result.name, ".")&&strcmp(result.name, "..")) {
if((result.attr&DOS_ATTR_DIRECTORY) && strcmp(result.name, ".")&&strcmp(result.name, "..")) {
strcat(path, result.name);
strcat(path, "\\");
char *fname = strrchr(args, '\\');
char *fname = strrchr_dbcs(args, '\\');
if (fname!=NULL) fname++;
else {
fname = strrchr(args, ':');
@ -3252,7 +3253,7 @@ void DOS_Shell::CMD_ATTRIB(char *args){
strcpy(sfull, arg1);
if (uselfn&&strchr(sfull, '*')) {
char * find_last;
find_last=strrchr(sfull,'\\');
find_last=strrchr_dbcs(sfull,'\\');
if (find_last==NULL) find_last=sfull;
else find_last++;
if (sfull[strlen(sfull)-1]=='*'&&strchr(find_last, '.')==NULL) strcat(sfull, ".*");
@ -3759,7 +3760,7 @@ void DOS_Shell::CMD_FOR(char *args) {
if (strchr(fp, '?') || strchr(fp, '*')) {
char name[DOS_NAMELENGTH_ASCII], lname[LFN_NAMELENGTH], spath[DOS_PATHLENGTH], path[DOS_PATHLENGTH], pattern[DOS_PATHLENGTH], full[DOS_PATHLENGTH], *r;
if (!DOS_Canonicalize(fp,full)) return;
r=strrchr(full, '\\');
r=strrchr_dbcs(full, '\\');
if (r!=NULL) {
*r=0;
strcpy(path, full);

View File

@ -53,6 +53,8 @@ extern bool ctrlbrk, gbk;
extern bool DOS_BreakFlag;
extern bool DOS_BreakConioFlag;
char *strrchr_dbcs(char *str, char ch);
void DOS_Shell::ShowPrompt(void) {
char dir[DOS_PATHLENGTH];
dir[0] = 0; //DOS_GetCurrentDir doesn't always return something. (if drive is messed up)
@ -186,7 +188,7 @@ bool DOS_Shell::BuildCompletions(char * line, uint16_t str_len) {
const char *path;
if ((path = strrchr(line+completion_index,':'))) completion_index = (uint16_t)(path-line+1);
if ((path = strrchr(line+completion_index,'\\'))) completion_index = (uint16_t)(path-line+1);
if ((path = strrchr_dbcs(line+completion_index,'\\'))) completion_index = (uint16_t)(path-line+1);
if ((path = strrchr(line+completion_index,'/'))) completion_index = (uint16_t)(path-line+1);
// build the completion list
@ -210,7 +212,7 @@ bool DOS_Shell::BuildCompletions(char * line, uint16_t str_len) {
if (p_completion_start) {
safe_strncpy(mask, p_completion_start,DOS_PATHLENGTH);
const char* dot_pos = strrchr(mask, '.');
const char* bs_pos = strrchr(mask, '\\');
const char* bs_pos = strrchr_dbcs(mask, '\\');
const char* fs_pos = strrchr(mask, '/');
const char* cl_pos = strrchr(mask, ':');
// not perfect when line already contains wildcards, but works
@ -948,7 +950,7 @@ bool DOS_Shell::Execute(char* name, const char* args) {
/* check for a drive change */
if (((strcmp(name + 1, ":") == 0) || (strcmp(name + 1, ":\\") == 0)) && isalpha(*name) && !control->SecureMode())
{
if (strrchr(name,'\\')) { WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND"),name); return true; }
if (strrchr_dbcs(name,'\\')) { WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND"),name); return true; }
if (!DOS_SetDrive(toupper(name[0])-'A')) {
#ifdef WIN32
if(!sec->Get_bool("automount")) { WriteOut(MSG_Get("SHELL_EXECUTE_DRIVE_NOT_FOUND"),toupper(name[0])); return true; }