📄 fat.i
字号:
extern unsigned short FAT_FindItem(unsigned int cluster, unsigned char *name, struct FileInfoStruct *FileInfo);
extern unsigned int FAT_Open(unsigned char * dir);
extern unsigned int FAT_OpenDir(unsigned char * dir);
extern unsigned char FAT_Read(unsigned int pointer, unsigned int size);
extern unsigned char FAT_Rename(unsigned char *dir,unsigned char *newname);
extern unsigned char FAT_ModifyFAT(unsigned int cluster,unsigned int val);
extern unsigned char FAT_Delete(unsigned char *dir);
extern unsigned char FAT_DelItem(struct FileInfoStruct *FileInfo);
extern unsigned short FAT_FindFreeItem(unsigned int cluster, struct FileInfoStruct *FileInfo);
extern unsigned char FAT_MkDir(unsigned char * dir);
extern unsigned char FAT_Write(unsigned int cluster,unsigned char *data,unsigned int size);
extern unsigned int FAT_Create(unsigned char * dir,unsigned int size);
extern unsigned char FAT_RmDir(unsigned char * dir);
extern unsigned short FAT_Close(unsigned int * p);
#line 19 "FAT.c"
unsigned int FirstDirClust;
unsigned int FirstDataSector;
unsigned short BytesPerSector;
unsigned int FATsectors;
unsigned short SectorsPerClust;
unsigned int FirstFATSector;
unsigned int FirstDirSector;
unsigned int RootDirSectors;
unsigned int RootDirCount;
unsigned char FAT32_Enable;
unsigned char TABLE_READ = 0;
unsigned int START_CLUSTER = 0x0ffffff8;
unsigned char FAT_TABLE[512];
unsigned char LongNameBuffer[80];
unsigned char LongNameFlag = 0;
unsigned char (* FAT_ReadSector)(unsigned int,unsigned char *);
unsigned char (* FAT_WriteSector)(unsigned int,unsigned char *);
unsigned int (* FAT_ReadCapacity)(void);
struct FileInfoStruct FileInfo;
unsigned char FAT_Init()
{
struct bootsector710 *bs = 0;
struct bpb710Bytes *bpb = 0;
struct partrecordBytes *pr = 0;
unsigned char buffer[512];
unsigned int hidsec=0;
unsigned int Capacity;
Capacity = FAT_ReadCapacity();
if(Capacity<0xff)return 1;
if(FAT_ReadSector(0,buffer))return 1;
bs = (struct bootsector710 *)buffer;
pr = (struct partrecordBytes*)((struct partsector*)buffer)->psPart;
hidsec = get32_little(pr->prStartLBA);
if(hidsec >= Capacity/512)
{
hidsec = 0;
}
else
{
if(FAT_ReadSector(get32_little(pr->prStartLBA),buffer))return 1;
bs = (struct bootsector710 *)buffer;
if(bs->bsJump[0]!=0xE9 && bs->bsJump[0]!=0xEB)
{
hidsec = 0;
if(FAT_ReadSector(0,buffer))return 1;
bs = (struct bootsector710 *)buffer;
}
}
if(bs->bsJump[0]!=0xE9 && bs->bsJump[0]!=0xEB)
{
return 1;
}
bpb = (struct bpb710Bytes*)bs->bsBPB;
if(get16_little(bpb->bpbFATsecs))
{
FAT32_Enable=0;
FATsectors = get16_little(bpb->bpbFATsecs);
FirstDirClust = 2;
}
else
{
FAT32_Enable=1;
FATsectors = get32_little(bpb->bpbBigFATsecs);
FirstDirClust = get32_little(bpb->bpbRootClust);
}
BytesPerSector = get16_little(bpb->bpbBytesPerSec);
SectorsPerClust = bpb->bpbSecPerClust;
FirstFATSector = get16_little(bpb->bpbResSectors)+hidsec;
RootDirCount = get16_little(bpb->bpbRootDirEnts);
RootDirSectors = (RootDirCount*32)>>9;
FirstDirSector = FirstFATSector+bpb->bpbFATs*FATsectors;
FirstDataSector = FirstDirSector+RootDirSectors;
return 0;
}
unsigned char FAT_LoadPartCluster(unsigned int cluster,unsigned char part,unsigned char * buffer)
{
unsigned int sector;
sector=(unsigned int)FirstDataSector+(unsigned int)(cluster-2)*(unsigned int)SectorsPerClust;
if(FAT_ReadSector(sector+part,buffer))return 1;
else return 0;
}
unsigned int FAT_NextCluster(unsigned int cluster)
{
unsigned char temp;
unsigned int sector;
unsigned int offset;
if(cluster<2)return 0x0ffffff8;
if(FAT32_Enable)temp = 127;
else temp = 255;
offset = cluster/(temp+1);
sector=FirstFATSector+offset;
offset=cluster%(temp+1);
cluster -= offset;
if(TABLE_READ == 0 || cluster != START_CLUSTER)
{
if(FAT_ReadSector(sector,FAT_TABLE))return 0x0ffffff8;
START_CLUSTER = cluster;
TABLE_READ = 1;
}
if(FAT32_Enable)
{
sector=((unsigned int *)FAT_TABLE)[offset];
}
else
{
sector=((unsigned short *)FAT_TABLE)[offset];
}
return (unsigned int)sector;
}
#line 225 "FAT.c"
#line 1002 "FAT.c"
unsigned short FAT_FindItem(unsigned int cluster, unsigned char *name, struct FileInfoStruct *FileInfo)
{
unsigned char buffer[512];
unsigned int tempclust;
unsigned int sector;
unsigned short cnt;
unsigned short offset;
unsigned char i;
struct direntryBytes*item = 0;
if((cluster==0) && (FAT32_Enable == 0))
{
for(cnt=0;cnt<RootDirSectors;cnt++)
{
if(FAT_ReadSector(FirstDirSector+cnt,buffer)){return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntryBytes*)(&buffer[offset]);
if((item->deName[0] != 0x00) && (item->deName[0] != 0xe5) && (item->deAttributes != 0x0f))
{
for(i=0;i<11;i++)
{
if(buffer[offset+i]!=name[i])break;
}
if(i==11)
{
FileInfo->StartCluster = get16_little(item->deStartCluster) + (((unsigned int)get16_little(item->deHighClust))<<16);
FileInfo->Size = get32_little(item->deFileSize);
FileInfo->Attr = item->deAttributes;
FileInfo->Sector = FirstDirSector+cnt;
FileInfo->Offset = offset;
return 0;
}
}
}
}
}
else
{
tempclust=cluster;
while(1)
{
sector=(unsigned int)FirstDataSector+(unsigned int)(tempclust-2)*(unsigned int)SectorsPerClust;
for(cnt=0;cnt<SectorsPerClust;cnt++)
{
if(FAT_ReadSector(sector+cnt,buffer)){return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntryBytes*)(&buffer[offset]);
if((item->deName[0] != 0x00) && (item->deName[0] != 0xe5) && (item->deAttributes != 0x0f))
{
for(i=0;i<11;i++)
{
if(buffer[offset+i]!=name[i])break;
}
if(i==11)
{
FileInfo->StartCluster = get16_little(item->deStartCluster) + (((unsigned int)get16_little(item->deHighClust))<<16);
FileInfo->Size = get32_little(item->deFileSize);
FileInfo->Attr = item->deAttributes;
FileInfo->Sector = sector+cnt;
FileInfo->Offset = offset;
return 0;
}
}
}
}
tempclust=FAT_NextCluster(tempclust);
if((FAT32_Enable == 0 && tempclust == 0xffff) || tempclust == 0x0ffffff8 || tempclust == 0x0fffffff)break;
}
}
return 1;
}
unsigned int FAT_Open(unsigned char * dir)
{
unsigned char name[11];
unsigned char *p=dir;
unsigned char deep=0;
unsigned char i,j;
unsigned int cluster=0;
if(FAT32_Enable)cluster=FirstDirClust;
if(*p != '\\')return 1;
while(*p)
{
if(*p == '\\')
{
deep++;
}
p++;
}
p=dir;
for(i=0;i<deep-1;i++)
{
p++;
for(j=0;j<11;j++)name[j]=0x20;
j=0;
while(*p != '\\')
{
if((*p) >= 'a' && (*p) <= 'z')name[j] = (*p++)-0x20;
else name[j] = *p++;
j++;
}
if(FAT_FindItem(cluster,name, &FileInfo))return 1;
cluster = FileInfo.StartCluster;
}
p++;
for(j=0;j<11;j++)name[j]=0x20;
j=0;
while(*p != '.')
{
if(*p>='a' && *p<='z')name[j]=(*p++)-0x20;
else name[j]=*p++;
j++;
}
j=8;
p++;
while(*p)
{
if(*p>='a' && *p<='z')name[j]=(*p++)-0x20;
else name[j]=*p++;
j++;
}
if(FAT_FindItem(cluster,name, &FileInfo))return 1;
cluster = FileInfo.StartCluster;
return cluster;
}
unsigned int FAT_OpenDir(unsigned char * dir)
{
unsigned char name[11];
unsigned char *p=dir;
unsigned char deep=0;
unsigned char i,j;
unsigned int cluster=0;
if(FAT32_Enable)cluster = FirstDirClust;
if(*p != '\\')return 1;
while(*p)
{
if(*p == '\\')
{
deep++;
}
p++;
}
p=dir;
for(i=0;i<deep-1;i++)
{
p++;
for(j=0;j<11;j++)name[j]=0x20;
j=0;
while(*p != '\\')
{
if((*p) >= 'a' && (*p) <= 'z')name[j] = (*p++)-0x20;
else name[j] = *p++;
j++;
}
if(FAT_FindItem(cluster,name, &FileInfo))return 1;
cluster = FileInfo.StartCluster;
}
p++;
for(j=0;j<11;j++)name[j]=0x20;
j=0;
while(*p)
{
if(*p>='a' && *p<='z')name[j]=(*p++)-0x20;
else name[j]=*p++;
j++;
}
if(j == 0)return cluster;
if(FAT_FindItem(cluster,name, &FileInfo))return 1;
cluster = FileInfo.StartCluster;
return cluster;
}
void CopyDirentruyItem(struct direntryBytes *Desti,struct direntryBytes *Source)
{
unsigned char temp;
unsigned int * i = (unsigned int *)Desti;
unsigned int * j = (unsigned int *)Source;
for(temp=0;temp<8;temp++) *i++ = *j++;
}
#line 1558 "FAT.c"
unsigned char recordBuf[256*4];
void WriteFolderCluster(unsigned short addr,unsigned int cluster)
{
*(unsigned int *)(&recordBuf[addr]) = cluster;
}
unsigned int GetFolderCluster(unsigned short addr)
{
return *(unsigned int *)(&recordBuf[addr]);
}
unsigned char SearchFolder(unsigned int cluster,unsigned short *addr)
{
unsigned char *buffer;
unsigned int sector;
unsigned int tempclust;
unsigned char cnt;
unsigned short offset;
struct direntryBytes *item = 0;
if(cluster==0 && FAT32_Enable==0)
{
buffer=malloc(512);
if(buffer==0)return 1;
for(cnt=0;cnt<RootDirSectors;cnt++)
{
if(FAT_ReadSector(FirstDirSector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntryBytes *)(&buffer[offset]);
if((item->deName[0] != '.') && (item->deName[0] != 0x00) && (item->deName[0] != 0xe5))
{
if(item->deAttributes & 0x10 )
{
if(*addr==256*4)return 0;
else
{
WriteFolderCluster(*addr,get16_little(item->deStartCluster)+(((unsigned int)get16_little(item->deHighClust))<<16));
*addr+=4;
}
}
}
}
}
free(buffer);
}
else
{
tempclust=cluster;
while(1)
{
sector=FirstDataSector+(unsigned int)(tempclust-2)*(unsigned int)SectorsPerClust;
buffer=malloc(512);
if(buffer==0)return 1;
for(cnt=0;cnt<SectorsPerClust;cnt++)
{
if(FAT_ReadSector(sector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntryBytes *)(&buffer[offset]);
if((item->deName[0] != '.') && (item->deName[0] != 0x00) && (item->deName[0] != 0xe5))
{
if(item->deAttributes & 0x10 )
{
if(*addr==256*4)return 0;
else
{
WriteFolderCluster(*addr,get16_little(item->deStartCluster)+(((unsigned int)get16_little(item->deHighClust))<<16));
*addr+=4;
}
}
}
}
}
free(buffer);
tempclust=FAT_NextCluster(tempclust);
if(tempclust == 0x0fffffff || tempclust == 0x0ffffff8 || (FAT32_Enable == 0 && tempclust == 0xffff))break;
}
}
return 0;
}
unsigned char SearchInit()
{
unsigned short addr = 0;
unsigned short temp_addr;
unsigned int cluster;
if(FAT32_Enable)
WriteFolderCluster(addr,FirstDirClust);
else
WriteFolderCluster(0,0);
addr += 4;
WriteFolderCluster(addr, 0xffffffff);
temp_addr = addr;
addr = 0;
while(1)
{
cluster = GetFolderCluster(addr);
if(cluster == 0xffffffff)break;
else
{
if(SearchFolder(cluster,&temp_addr))
{
}
if(GetFolderCluster(temp_addr) != 0xffffffff)
WriteFolderCluster(temp_addr,0XFFFFFFFF);
if(temp_addr == 256*4)
{
WriteFolderCluster(temp_addr - 4,0XFFFFFFFF);
break;
}
}
addr+=4;
}
return 0;
}
unsigned char Search( unsigned short *music_record_addr,struct direntryBytes *MusicInfo,unsigned short *Count,unsigned char *type)
{
unsigned char *buffer;
unsigned int sector;
unsigned int cluster;
unsigned int tempclust;
unsigned char cnt;
unsigned short offset;
unsigned short i=0;
unsigned char j;
unsigned char *p;
struct direntryBytes *item = 0;
struct winentryBytes *we =0;
unsigned short addr = 0;
while(1)
{
cluster = GetFolderCluster(addr);
addr += 4;
if(cluster == 0xffffffff)break;
else
{
if(music_record_addr != 0) *music_record_addr = addr - 4;
if(cluster==0 && FAT32_Enable==0)
{
buffer=malloc(512);
if(buffer==0)return 1;
for(cnt=0;cnt<RootDirSectors;cnt++)
{
if(FAT_ReadSector(FirstDirSector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntryBytes *)(&buffer[offset]);
if((item->deName[0] != '.') && (item->deName[0] != 0x00) && (item->deName[0] != 0xe5))
{
if(item->deAttributes == 0x0f)
{
we = (struct winentryBytes *)(&buffer[offset]);
j = 26 *( (we->weCnt-1) & 0x3f);
if(j<80-25)
{
p = &LongNameBuffer[j];
for (j=0;j<10;j++) *p++ = we->wePart1[j];
for (j=0;j<12;j++) *p++ = we->wePart2[j];
for (j=0;j<4;j++) *p++ = we->wePart3[j];
if (we->weCnt & 0x40) (*(unsigned short *)p) = 0;
if ((we->weCnt & 0x3f) == 1) LongNameFlag = 1;
}
LongNameBuffer[80-1] = 0;
LongNameBuffer[80-2] = 0;
}
else if((item->deExtension[0] == 'M')&&(item->deExtension[1] == 'P')&&(item->deExtension[2] == '3'))
{
#line 1821 "FAT.c"
CopyDirentruyItem(MusicInfo,item);
*type=1;
i++;
if(i==*Count){free(buffer);return 0;}
else LongNameFlag = 0;
}
else if((item->deExtension[0] == 'W')&&(item->deExtension[1] == 'M')&&(item->deExtension[2] == 'A'))
{
#line 1836 "FAT.c"
CopyDirentruyItem(MusicInfo,item);
*type=2;
i++;
if(i==*Count){free(buffer);return 0;}
else LongNameFlag = 0;
}
else if((item->deExtension[0] == 'M')&&(item->deExtension[1] == 'I')&&(item->deExtension[2] == 'D'))
{
#line 1851 "FAT.c"
CopyDirentruyItem(MusicInfo,item);
*type=3;
i++;
if(i==*Count){free(buffer);return 0;}
else LongNameFlag = 0;
}
else if((item->deExtension[0] == 'W')&&(item->deExtension[1] == 'A')&&(item->deExtension[2] == 'V'))
{
#line 1866 "FAT.c"
CopyDirentruyItem(MusicInfo,item);
*type=4;
i++;
if(i==*Count){free(buffer);return 0;}
else LongNameFlag = 0;
}
else LongNameFlag = 0;
}
}
}
free(buffer);
}
else
{
tempclust=cluster;
while(1)
{
sector=FirstDataSector+(unsigned int)(tempclust-2)*(unsigned int)SectorsPerClust;
buffer=malloc(512);
if(buffer==0)return 1;
for(cnt=0;cnt<SectorsPerClust;cnt++)
{
if(FAT_ReadSector(sector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntryBytes *)(&buffer[offset]);
if((item->deName[0] != '.') && (item->deName[0] != 0x00) && (item->deName[0] != 0xe5))
{
if(item->deAttributes == 0x0f)
{
we = (struct winentryBytes *)(&buffer[offset]);
j = 26 *( (we->weCnt-1) & 0x3f);
if(j<80-25)
{
p = &LongNameBuffer[j];
for (j=0;j<10;j++) *p++ = we->wePart1[j];
for (j=0;j<12;j++) *p++ = we->wePart2[j];
for (j=0;j<4;j++) *p++ = we->wePart3[j];
if (we->weCnt & 0x40) (*(unsigned short *)p) = 0;
if ((we->weCnt & 0x3f) == 1) LongNameFlag = 1;
}
LongNameBuffer[80-1] = 0;
LongNameBuffer[80-2] = 0;
}
else if((item->deExtension[0] == 'M')&&(item->deExtension[1] == 'P')&&(item->deExtension[2] == '3'))
{
#line 1925 "FAT.c"
CopyDirentruyItem(MusicInfo,item);
*type = 1;
i++;
if(i==*Count){free(buffer);return 0;}
else LongNameFlag = 0;
}
else if((item->deExtension[0] == 'W')&&(item->deExtension[1] == 'M')&&(item->deExtension[2] == 'A'))
{
#line 1940 "FAT.c"
CopyDirentruyItem(MusicInfo,item);
*type = 2;
i++;
if(i==*Count){free(buffer);return 0;}
else LongNameFlag = 0;
}
else if((item->deExtension[0] == 'M')&&(item->deExtension[1] == 'I')&&(item->deExtension[2] == 'D'))
{
#line 1956 "FAT.c"
CopyDirentruyItem(MusicInfo,item);
*type = 3;
i++;
if(i==*Count){free(buffer);return 0;}
else LongNameFlag = 0;
}
else if((item->deExtension[0] == 'W')&&(item->deExtension[1] == 'A')&&(item->deExtension[2] == 'V'))
{
#line 1972 "FAT.c"
CopyDirentruyItem(MusicInfo,item);
*type=4;
i++;
if(i==*Count){free(buffer);return 0;}
else LongNameFlag = 0;
}
else LongNameFlag = 0;
}
}
}
free(buffer);
tempclust=FAT_NextCluster(tempclust);
if(tempclust == 0x0fffffff || tempclust == 0x0ffffff8 || (FAT32_Enable == 0 && tempclust == 0xffff))break;
}
}
}
}
if(*Count==0)*Count=i;
return 0;
}
unsigned char SearchLrc(unsigned char *dir,unsigned char * longnamebuffer,struct direntryBytes *LrcInfo,unsigned short music_record_addr)
{
unsigned char *buffer;
unsigned char longbuffertemp[130];
unsigned char * p1, * p2;
unsigned char match = 0;
unsigned int sector;
unsigned int cluster;
unsigned int tempclust;
unsigned char i;
unsigned char cnt;
unsigned short offset;
unsigned char j;
unsigned char *p;
struct direntryBytes *item = 0;
struct winentryBytes *we =0;
for(i=0;i<2;i++)
{
if(i==0)cluster = GetFolderCluster(music_record_addr);
else cluster = FAT_OpenDir(dir);
if(cluster == 1)return 1;
if(cluster==0 && FAT32_Enable==0)
{
buffer=malloc(512);
if(buffer==0)return 1;
for(cnt=0;cnt<RootDirSectors;cnt++)
{
if(FAT_ReadSector(FirstDirSector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntryBytes*)(&buffer[offset]);
if((item->deName[0] != '.') && (item->deName[0] != 0x00) && (item->deName[0] != 0xe5))
{
if(item->deAttributes == 0x0f)
{
we = (struct winentryBytes*)(&buffer[offset]);
j = 26 *( (we->weCnt-1) & 0x3f);
if(j<80-25)
{
p = &longbuffertemp[j];
for (j=0;j<10;j++) *p++ = we->wePart1[j];
for (j=0;j<12;j++) *p++ = we->wePart2[j];
for (j=0;j<4;j++) *p++ = we->wePart3[j];
if (we->weCnt & 0x40) (*(unsigned short *)p) = 0;
if ((we->weCnt & 0x3f) == 1) LongNameFlag = 1;
}
longbuffertemp[80-1] = 0;
longbuffertemp[80-2] = 0;
}
else if((item->deExtension[0] == 'L')&&(item->deExtension[1] == 'R')&&(item->deExtension[2] == 'C'))
{
CopyDirentruyItem(LrcInfo,item);
p1 = longnamebuffer;
p2 = longbuffertemp;
match = 1;
if(LongNameFlag)
{
while(*((unsigned short*)p1))
{
if(*(unsigned short*)p1 != *(unsigned short*)p2)
{
match = 0;
break;
}
p1 += 2;
p2 += 2;
}
}
else
{
p2 = item->deName;
while(*p1)
{
if(*p1++ != *p2++)
{
match = 0;
break;
}
}
}
if(match){free(buffer);return 0;}
else LongNameFlag = 0;
}
else LongNameFlag = 0;
}
}
}
free(buffer);
}
else
{
tempclust=cluster;
while(1)
{
sector=FirstDataSector+(unsigned int)(tempclust-2)*(unsigned int)SectorsPerClust;
buffer=malloc(512);
if(buffer==0)return 1;
for(cnt=0;cnt<SectorsPerClust;cnt++)
{
if(FAT_ReadSector(sector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntryBytes *)(&buffer[offset]);
if((item->deName[0] != '.') && (item->deName[0] != 0x00) && (item->deName[0] != 0xe5))
{
if(item->deAttributes == 0x0f)
{
we = (struct winentryBytes *)(&buffer[offset]);
j = 26 *( (we->weCnt-1) & 0x3f);
if(j<80-25)
{
p = &longbuffertemp[j];
for (j=0;j<10;j++) *p++ = we->wePart1[j];
for (j=0;j<12;j++) *p++ = we->wePart2[j];
for (j=0;j<4;j++) *p++ = we->wePart3[j];
if (we->weCnt & 0x40) (*(unsigned short *)p) = 0;
if ((we->weCnt & 0x3f) == 1) LongNameFlag = 1;
}
longbuffertemp[80-1] = 0;
longbuffertemp[80-2] = 0;
}
else if((item->deExtension[0] == 'L')&&(item->deExtension[1] == 'R')&&(item->deExtension[2] == 'C'))
{
CopyDirentruyItem(LrcInfo,item);
p1 = longnamebuffer;
p2 = longbuffertemp;
match = 1;
if(LongNameFlag)
{
while(*((unsigned short*)p1))
{
if(*(unsigned short*)p1 != *(unsigned short*)p2)
{
match = 0;
break;
}
p1 += 2;
p2 += 2;
}
}
else
{
p2 = item->deName;
while(*p1)
{
if(*p1++ != *p2++)
{
match = 0;
break;
}
}
}
if(match){free(buffer);return 0;}
else LongNameFlag = 0;
}
else LongNameFlag = 0;
}
}
}
free(buffer);
tempclust=FAT_NextCluster(tempclust);
if(tempclust == 0x0fffffff || tempclust == 0x0ffffff8 || (FAT32_Enable == 0 && tempclust == 0xffff))break;
}
}
}
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -