信息科学与技术学院学士学位论文
(6)读取文件流到结构体中,保存相应的参数; (7)将字符集编码转换为统一编码格式,并保存; (8)设置好当前偏移,进入SDL主窗口。 其主要代码如下:
int main(int argc, char **argv)
{
if (get_text_len(argv[1]) < TEXT_BUF_LEN_8M ) // 得到文件长度 { }
if ( (pos=get_space(TEXT_LEN)) == -1) { }
return -1;
// 申请空间
ret = process_arg(argc, argv); //实现对传入参数进行分析,可实现放大倍数设置 ret = sdl_init(); convert_init_local(); unicode_nchar = 0;
file_type = get_file_type_from_name(argv[1]); // 得到文件名,主要为了可支持
// 进行有关SDL有关的初始化操作 // 进行编码的初始化
其他文件格式的文件
charset = DetectCharSet(argv[1]); if(argc == 5) { }
pgtxt->fp = fopen(argv[1], \
// 得出文件的字符集编码格式
strcpy((char *)pgtxt->path, argv[1]);
get_file_name_from_path((char *)pgtxt->name, argv[1]);
if(charset == CHAR_SET_UNICODE || charset == CHAR_SET_UNICODE_BE)
26
信息科学与技术学院学士学位论文
{ } else {
len = fread(buf_text, 1, TEXT_LEN, pgtxt->fp); fclose(pgtxt->fp);
//为Utf-8编码格式的情况
//非Unicode编码
len = fread(buf_unicode, 1, UNICODE_LEN, pgtxt->fp); unicode_nchar = len/2;
if(charset == CHAR_SET_UTF8) { }
pgtxt->charset = CHAR_SET_UTF8;
unicode_nchar = utf8_to_unicode(buf_text, (unsigned short *)buf_unicode, len);
// 其他情况
else { }
pgtxt->charset = charset;
nicode_nchar = local_to_unicode(buf_text, (unsigned short *)buf_unicode, len);
pgtxt->buf = (unsigned char *)buf_unicode; pgtxt->unicode_len = unicode_nchar * 2;
if(pgtxt->cur_offset > pgtxt->unicode_len || pgtxt->cur_offset < 0)
pgtxt->cur_offset = 0;
pgtxt->cur_offset=pgtxt->cur_offset/2*2;
else
while(1) { }
27
s_table[cur_state].enter(NULL); // 进入到主窗口函数
信息科学与技术学院学士学位论文
}
5.2.2 字符编码解码的实现
return 0;
字符编码解码部分是整个开发中核心的,也是难点之处,如何从缓冲区中正确解析字符出来,是整个系统的关键之处,因涉及到的字符编码比较多,常见的编码有Utf-8编码,gb18030编码,big5编码,iso-8859编码体系,Unicode编码,如果文件所采用的编码格式本身就是Unicode编码,那么不需要进行编码解析就能直接正确读取数据出来,而非Unicode编码时,分2种情况来分析,一种是针对Utf-8编码体系的,因该编码可以找到规律,故分开来对待,其他的编码体系都是相似的解码方法,都是从编码体系-Unicode编码表中查询得到。
Utf-8编码和Unicode编码的对应关系如表5-1所示。
表 5-1 Utf-8 Unicode关系表
Utf-8编码 0xxxxxxx 110xxxxx 10xxxxxx 1110xxxxx 10xxxxxx 10xxxxxx Unicode编码 0x00 ~ 0x7F 0x80 ~ 0x7FF 0x8FF ~ FFFF 根据以上表中给出的Utf-8与Unicode的关系,以下是对Utf-8字符集编码的解析的主要代码。
int Utf8ToUnicode(uint8_t* src, uint16_t * punicode) {
if(0 == (src[0] & 0x80)){
// 单字节
*punicode = (uint16_t)src[0]; return 1; }
if(0xC0 == (src[0] & 0xE0) &&
28
信息科学与技术学院学士学位论文
0x80 == (src[1] & 0xC0)){
// 双字节
*punicode = (uint16_t)((((uint16_t)src[0] & 0x001F) << 6) | ((uint16_t)src[1] & 0x003F)); return 2; }
if(0xE0 == (src[0] & 0xF0) && 0x80 == (src[1] & 0xC0) && 0x80 == (src[2] & 0xC0)){
// 三字节
*punicode = (uint16_t)((((uint16_t)src[0] & 0x000F) << 12) | (((uint16_t)src[1] & 0x003F) << 6) | ((uint16_t)src[2] & 0x003F)); return 3; } return 0; }
主要的实现思想,就Utf-8编码的三种情况,一个字节的情况下直接转换为
Unicode编码,若是两个字节,将字节头去掉,三个字节和两个字节的处理方法相似,只要处理其字节头。 5.2.3 TXT主窗口实现
TXT主窗口是整个系统设计的难点,运用到了SDL库开发,电子书翻页以及行的处理,其主要设计思想为:
(1)初始化TXT窗口,即设置窗口大小; (2)装载背景图片; (3)装载字体; (4)创建窗口;
(5)进入循环,接受命令。 其主要代码如下:
29
信息科学与技术学院学士学位论文
{ }
5.2.4 命令循环实现
if(buf_text) { }
init_text_rect();
free(buf_text); buf_text = NULL;
int main_window_enter(void *data)
// 初始化窗口的宽度和高度
// 装载背景图片
background = load_image(PIXMAP_BACKGROUND);
font = TTF_OpenFont(DEFAULT_TTF_PATH, font_table[pgtxt->zoom]); if(window_free) { } goon = 1;
main_window_loop(); return 0;
// 命令接收函数
txt_main_window_create(); window_free = 0;
// 创建主窗口函数
命令循环用于接收输入命令执行响应的操作,利用了等待时间机制来接收命令
的输入,根据传的命令来进行相应的操作,包括上、下行,上、下一页查看以及方法查看,其主要代码如下: {
static void main_window_loop()
SDL_Event event;
30