📄 selectdict.c
字号:
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
//
// Copyright (c) 2005 ZYM <yanming.zhang@gmail.com>
//
#include <pspkernel.h>
#include <pspctrl.h>
#include <stdio.h>
#include <string.h>
#include "main.h"
#include "chinesedraw.h"
static void disp_selectdict_page(void);
struct dictinfo {
char dirname[FILENAME_LEN];
char dictfile[FILENAME_LEN];
char idxfile[FILENAME_LEN];
char dictcname[DICTNAME_LEN];
char dictename[DICTNAME_LEN];
};
#define MAXDICTNUM 20
struct dictinfo dictlist[MAXDICTNUM];
static int dictnum;
static int dictindex;
struct SceIoDirent direntry, fileentry;
static void getdictslist(void)
{
int fd, dictdirfd, ifofd;
int readsize;
unsigned char ifo[100];
char *p, *p2;
dictnum=0;
fd = sceIoDopen(psp_full_path);
if (fd <0) {
ERR_PRINT("Open dir [%s] fail.", psp_full_path);
}
while (dictnum<MAXDICTNUM) {
memset(&dictlist[dictnum], 0, sizeof(struct dictinfo));
memset(&direntry, 0, sizeof(struct SceIoDirent));
if (sceIoDread(fd, &direntry) <= 0) {
DBG_PRINT("no more dict dir in %s, dictnum=%d",psp_full_path, dictnum);
break;
}
else {
DBG_PRINT("dictnum %d", dictnum);
}
DBG_PRINT("dir attr %x, dirname %s",direntry.d_stat.st_attr, direntry.d_name);
if (direntry.d_stat.st_attr & FIO_SO_IFDIR) {
if (!strcmp(direntry.d_name, "."))
continue;
if (!strcmp(direntry.d_name, ".."))
continue;
strcpy(dictdirpath, psp_full_path);
strcat(dictdirpath, direntry.d_name);
strcat(dictdirpath, "/");
dictdirfd = sceIoDopen(dictdirpath);
DBG_PRINT("dictdir %s", dictdirpath);
while (sceIoDread(dictdirfd, &fileentry) >0) {
DBG_PRINT("filename %s", fileentry.d_name);
if (fileentry.d_stat.st_attr & FIO_SO_IFREG) {
if (strstr(fileentry.d_name, "dict.pspz")) {
// get dict file
strcpy(dictlist[dictnum].dictfile, fileentry.d_name);
}
else if (strstr(fileentry.d_name, "idx.pspz")) {
// get idx file
strcpy(dictlist[dictnum].idxfile, fileentry.d_name);
}
else if (strstr(fileentry.d_name, "ifo.psp")) {
// get ifo file
strcat(dictdirpath, fileentry.d_name);
ifofd = sceIoOpen(dictdirpath, PSP_O_RDONLY, 0777);
if (!ifofd){
ERR_PRINT("open file[%s] fail.", fileentry.d_name);
}
else {
readsize = sceIoRead(ifofd, ifo, 100);
ifo[readsize]='\0';
DBG_PRINT("%s ifo %s",direntry.d_name, ifo);
p = strstr(ifo,"pspename=");
p += strlen("pspename=");
p2 = strchr(p, '\n');
strncpy(dictlist[dictnum].dictename, p, p2-p);
p = strstr(p2+1, "pspcname=");
p += strlen("pspcname=");
p2 = strchr(p, '\n');
strncpy(dictlist[dictnum].dictcname, p, p2-p);
}
sceIoClose(ifofd);
}
}
}
if ((strlen(dictlist[dictnum].dictfile)>0) &&
(strlen(dictlist[dictnum].idxfile)>0) &&
(strlen(dictlist[dictnum].dictename)>0) &&
(strlen(dictlist[dictnum].dictcname)>0))
strcpy(dictlist[dictnum].dirname, direntry.d_name);
dictnum++;
sceIoDclose(dictdirfd);
}
}
sceIoDclose(fd);
}
static unsigned long strbuftolong(unsigned char *s)
{
long l;
l = (*s) << 24;
l += (*(s+1)) << 16;
l += (*(s+2)) << 8;
l += (*(s+3));
return l;
}
// only for the oxford-ec dict
// return the symbol count in dict file
static int buildsymbolarray(void)
{
char *p, *wordoffset;
unsigned long len, wordidx;
long dictoff, dictlen;
long i;
int symbolcount,wordsymcount;
symbolcount=0;
wordidx=0;
p=idxfilep;
while (p<(idxfilep + idxfilesize)) {
len=strlen(p);
dictoff = strbuftolong(p+len+1);
dictlen = strbuftolong(p+len+1+4);
// analyse the symbol
i =0;
wordoffset = dictfilep + dictoff;
wordsymcount=0;
while(i<dictlen){
if ((*(wordoffset+i)=='/')&&
((*(wordoffset+i+1)==' ')||
(*(wordoffset+i+1)=='-'))){
// match frist "/ "
long j=i+1;
while (j<dictlen){
if (*(wordoffset+j)=='/'){
if ((*(wordoffset+j+1)==' ')||
(*(wordoffset+j+1)==';')||
(*(wordoffset+j+1)==',')||
(*(wordoffset+j+1)==')')||
(*(wordoffset+j+1)=='.')||
(*(wordoffset+j+1)=='n')||
(*(wordoffset+j+1)=='a')||
(*(wordoffset+j+1)=='v')){
// match second "/ "
((struct symbol *)(symbolarray+symbolcount))->symoffset = wordoffset+i;
((struct symbol *)(symbolarray+symbolcount))->symlen = j-i+1;
symbolcount++;
wordsymcount++;
//DBG_PRINT("symoffset 0x%x, symlen %d", i+dictoff, j-i+1);
break;
}
else {
// match second "/"
// no match second char
break;
}
}
else
j++;
}
if (j==dictlen){
// no match second "/"
}
i=(j+1);
}
else
i++;
}
((struct symidx *)(symidxarray+wordidx))->offset =
(symbolarray+symbolcount-wordsymcount);
((struct symidx *)(symidxarray+wordidx))->count = wordsymcount;
p+=(len+9);
wordidx++;
//DBG_PRINT("wordidx %d, idxoffset %x, count %d", wordidx,
// (symbolarray+symbolcount-wordsymcount), wordsymcount);
}
return symbolcount;
}
// return 0 fail, 1 ok.
//
static int loaddictfile(void)
{
int dictfd, idxfd, tagfd;
unsigned long gzfilesize;
unsigned char *p;
// save the tagfile if any changed
if ((tagfilep!=NULL)&&(tagchanged !=0)) {
tagfd = sceIoOpen(tagfilepath, PSP_O_WRONLY|PSP_O_CREAT, 0777);
if (tagfd>=0){
sceIoWrite(tagfd, tagfilep, tagfilesize);
DBG_PRINT("write tagfile %s", tagfilepath);
}
else{
ERR_PRINT("Open file [%s] fail.", tagfilepath);
}
sceIoClose(tagfd);
}
memset(dictfilepath, 0, PATH_LEN);
memset(idxfilepath, 0, PATH_LEN);
DBG_PRINT("mempool0x%x", mempool);
// load dict file
strcpy(dictfilepath, psp_full_path);
strcat(dictfilepath, ydictconf.dirname);
strcat(dictfilepath, "/");
strcat(dictfilepath, ydictconf.dictfile);
dictfd = sceIoOpen(dictfilepath, PSP_O_RDONLY, 0777);
if (dictfd<0) {
// must delete config file first
memset(configfilepath, 0, PATH_LEN);
strcpy(configfilepath, psp_full_path);
strcat(configfilepath, CONFIG_FILE);
sceIoRemove(configfilepath);
DBG_PRINT("open file [%s] fail.", ydictconf.dictfile);
return 0;
}
else {
gzfilesize = (unsigned long)sceIoLseek32(dictfd, 0, PSP_SEEK_END);
sceIoLseek32(dictfd, 0, PSP_SEEK_SET);
if (gzfilesize > MEMPOOL_SIZE) {
ERR_PRINT("file [%s] is too big.", ydictconf.dictfile);
}
dictfilesize = ydict_unzip(mempool, dictfd,
mempool+MEMPOOL_SIZE-MEMPOOL_FREE_SIZE-GZ_INBUF_SIZE,
mempool+MEMPOOL_SIZE-MEMPOOL_FREE_SIZE);
dictfilep = mempool;
sceIoClose(dictfd);
}
// load idxfile
strcpy(idxfilepath, psp_full_path);
strcat(idxfilepath, ydictconf.dirname);
strcat(idxfilepath, "/");
strcat(idxfilepath, ydictconf.idxfile);
idxfd = sceIoOpen(idxfilepath, PSP_O_RDONLY, 0777);
if (idxfd<0) {
// must delete config file first
memset(configfilepath, 0, PATH_LEN);
strcpy(configfilepath, psp_full_path);
strcat(configfilepath, CONFIG_FILE);
sceIoRemove(configfilepath);
DBG_PRINT("open file [%s] fail.", ydictconf.idxfile);
return 0;
}
else {
gzfilesize = (unsigned long)sceIoLseek(idxfd, 0, PSP_SEEK_END);
sceIoLseek(idxfd, 0, PSP_SEEK_SET);
idxfilep = mempool + ((dictfilesize +0xFFF) & 0xFFFFF000);
idxfilesize = ydict_unzip(idxfilep, idxfd,
mempool+MEMPOOL_SIZE-MEMPOOL_FREE_SIZE-GZ_INBUF_SIZE,
mempool+MEMPOOL_SIZE-MEMPOOL_FREE_SIZE);
sceIoClose(idxfd);
}
DBG_PRINT("load dict&idx ok");
// build the word offset array
wordarray = (char **)(((int)idxfilep + idxfilesize+ 0xFFF) & 0xFFFFF000);
wordcount = 0;
p= idxfilep;
while (p <(idxfilep + idxfilesize)) {
*(wordarray+wordcount)=p;
p+=strlen((char *)p);
p+=9;
wordcount++;
}
DBG_PRINT("build wordarray 0x%x, count %d ok",wordarray, wordcount);
// load the tag file, the tag name as "xxxxx.tg"
memset(tagfilepath, 0, PATH_LEN);
strcpy(tagfilepath, psp_full_path);
strcat(tagfilepath, ydictconf.dictename);
strcat(tagfilepath, ".tg");
tagfd = sceIoOpen(tagfilepath, PSP_O_RDONLY, 0777);
if (tagfd<0) {
// open tag file fail. create an empty one
DBG_PRINT("open file [%s.tg] fail.", ydictconf.dictename);
tagfilep = (unsigned char *)(((int)((unsigned char *)(wordarray+wordcount)+0xFFF))&0xFFFFF000);
tagfilesize=wordcount;
memset(tagfilep, 0, tagfilesize);
tagchanged=1;
}
else {
tagfilesize = (unsigned long)sceIoLseek(tagfd, 0, PSP_SEEK_END);
sceIoLseek(tagfd, 0, PSP_SEEK_SET);
tagfilep = (unsigned char *)(((int)((unsigned char *)(wordarray+wordcount)+0xFFF))&0xFFFFF000);
DBG_PRINT("tagfilep0x%x, size0x%x", tagfilep, tagfilesize);
if (tagfilesize!=wordcount){
ERR_PRINT("File %s.tg size NOT correct. Please delete it or re-install YDICT.", ydictconf.dictename);
}
if ((tagfilep+tagfilesize)>(mempool+MEMPOOL_SIZE)) {
// no enough memory to load tagfile
ERR_PRINT("no enough memory, want 0x%x bytes", tagfilep+tagfilesize-(mempool+MEMPOOL_SIZE));
}
else {
int readsize;
readsize = sceIoRead(tagfd, tagfilep, tagfilesize);
if (readsize != tagfilesize){
DBG_PRINT("load tagfile fail. readed 0x%x", readsize);
tagfilep=NULL;
}
else{
tagchanged = 0;
DBG_PRINT("load tagfile ok");
}
sceIoClose(tagfd);
}
}
// build the oxford-ec dict's phonetic symbol array
if (!strcmp(ydictconf.dictename, "oxford-ec")) {
int symbolnum;
// every word has an item in 'symidxarray', which has one pointer to 'symbolarray'
// if it has one or more phonetic symbol
if (tagfilep!=NULL)
symidxarray = (struct symidx *)(((int)(tagfilep+wordcount)+0xFFF) & 0xFFFFF000);
else
symidxarray = (struct symidx *)(((int)(wordarray+wordcount)+0xFFF) & 0xFFFFF000);
// symbolarray store all the symbols in the oxford-ec dict file,
// every array item mark the offset in dict file, and the length of symbol
symbolarray = (struct symbol *)(((int)(symidxarray+wordcount)+0xFFF) & 0xFFFFF000);
DBG_PRINT("symidxarray 0x%x,symarray0x%x", symidxarray, symbolarray);
symbolnum = buildsymbolarray();
DBG_PRINT("build symbolarry ok, count=%d",symbolnum);
}
return 1;
}
void ydict_selectdict(int laststate)
{
int cfgfd;
struct ydictctrl yctrl;
int menuindex;
if (laststate == STATE_START) {
// set tag param as NULL;
tagfilep = NULL;
tagchanged = 0;
// ydict start, read config file
memset(configfilepath, 0, PATH_LEN);
strcpy(configfilepath, psp_full_path);
strcat(configfilepath, CONFIG_FILE);
cfgfd = sceIoOpen(configfilepath, PSP_O_RDONLY, 0777);
if (cfgfd>=0) {
sceIoRead(cfgfd, &ydictconf, sizeof(struct configdata));
sceIoClose(cfgfd);
if (loaddictfile() ==0)
return;
if (ydictconf.mode == BROWSE_MODE)
gstate = STATE_BROWSE;
else if (ydictconf.mode == RINGKEY_MODE)
gstate = STATE_RING_KEY;
return ;
}
else {
// no config file
DBG_PRINT("no config file");
}
}
DBG_PRINT("before getdictslist\n");
getdictslist();
dictindex=0;
while (1) {
disp_selectdict_page();
getcontrol(&yctrl);
switch (yctrl.buttons)
{
case PSP_CTRL_TRIANGLE:
case PSP_CTRL_CIRCLE:
case PSP_CTRL_CROSS:
case PSP_CTRL_SQUARE:
if (yctrl.buttons == PSP_CTRL_TRIANGLE)
menuindex = 0;
else if (yctrl.buttons == PSP_CTRL_CIRCLE)
menuindex = 1;
else if (yctrl.buttons == PSP_CTRL_CROSS)
menuindex = 2;
else if (yctrl.buttons == PSP_CTRL_SQUARE)
menuindex = 3;
dictindex +=menuindex;
if ((dictindex<dictnum) &&(strlen(dictlist[dictindex].dictfile)>0) &&
(strcmp(ydictconf.dictfile, dictlist[dictindex].dictfile))) {
strcpy(ydictconf.dirname, dictlist[dictindex].dirname);
strcpy(ydictconf.dictfile, dictlist[dictindex].dictfile);
strcpy(ydictconf.idxfile, dictlist[dictindex].idxfile);
strcpy(ydictconf.dictename, dictlist[dictindex].dictename);
strcpy(ydictconf.dictcname, dictlist[dictindex].dictcname);
if (loaddictfile()==0)
return;
if (ydictconf.mode == BROWSE_MODE)
gstate = STATE_BROWSE;
else if (ydictconf.mode == RINGKEY_MODE)
gstate = STATE_RING_KEY;
else {
ydictconf.mode = BROWSE_MODE;
gstate = STATE_BROWSE;
}
ydictconf.changed = 1;
return;
}
else if (dictindex<dictnum){
if (ydictconf.mode == BROWSE_MODE)
gstate = STATE_BROWSE;
else if (ydictconf.mode == RINGKEY_MODE)
gstate = STATE_RING_KEY;
return;
}
break;
case PSP_CTRL_LEFT:
if ((dictindex-4)>=0)
dictindex -=4;
break;
case PSP_CTRL_RIGHT:
if ((dictindex+4)<dictnum)
dictindex +=4;
break;
default:
break;
}
}
}
static void disp_selectdict_page(void)
{
pgWaitV();
pgFillvram(rgb2col(0,0,0));
// draw select dict
chDrawString(16*3, 0, FG_COLOR, BG_COLOR, SELECT_DICT_STR, 1, 1);
// draw the top line
chDrawRec(0, 16, SCREEN_WIDTH, 4, FG_COLOR, 1);
// draw bottom horizon line
chDrawRec(0, 16+4+WORDLIST_SIZE*16, SCREEN_WIDTH, 2, FG_COLOR, 1);
// draw version
pgPrint(0, CMAX_Y-1, FG_COLOR, VERSION);
if (dictnum == 0) {
chDrawString(SCREEN_WIDTH/2 - strlen(NO_DICT_STR)/2*8,
SCREEN_HEIGHT/2 -8, FG_COLOR, BG_COLOR, NO_DICT_STR, 1, 1);
}
else {
if (dictindex<dictnum) {
// triangle menu
chDrawString(MENU_X, MENU_Y, TRIANGLE_COLOR, BG_COLOR, TRIANGLE_MENU, 1, 1);
chDrawString(MENU_X+3*16, MENU_Y,
FG_COLOR, BG_COLOR, dictlist[dictindex].dictcname, 1, 1);
}
if ((dictindex+1)<dictnum) {
// circle menu
chDrawString(MENU_X, MENU_Y+MENU_DELTA, CIRCLE_COLOR, BG_COLOR, CIRCLE_MENU, 1, 1);
chDrawString(MENU_X+3*16, MENU_Y+MENU_DELTA,
FG_COLOR, BG_COLOR, dictlist[dictindex+1].dictcname, 1, 1);
}
if ((dictindex+2)<dictnum) {
// cross menu
chDrawString(MENU_X, MENU_Y+MENU_DELTA*2, CROSS_COLOR, BG_COLOR, CROSS_MENU, 1, 1);
chDrawString(MENU_X+3*16, MENU_Y+MENU_DELTA*2,
FG_COLOR, BG_COLOR, dictlist[dictindex+2].dictcname, 1, 1);
}
if ((dictindex+3)<dictnum) {
// square menu
chDrawString(MENU_X, MENU_Y+MENU_DELTA*3, SQUARE_COLOR, BG_COLOR, SQUARE_MENU, 1, 1);
chDrawString(MENU_X+3*16, MENU_Y+MENU_DELTA*3,
FG_COLOR, BG_COLOR, dictlist[dictindex+3].dictcname, 1, 1);
}
// next page
// if ()
}
pgScreenFlipV();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -