📄 hhc.c
字号:
/*************************************************************************** * Copyright (C) 2003 by zhong * * zhongz@163.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/#include <sys/types.h>//#include <sys/stat.h>#include <unistd.h>#include <string.h>#include <stdio.h>#include <stdlib.h>//#include <dirent.h>#include <gtk/gtk.h>#include "interface.h"#include "hhc.h"static gint getTagNumber( const gchar *data );static gchar *getTag( const gchar *data, int index );static gchar *getNameFromTag( const gchar *data );static gchar *getParamValueFromTag( const gchar *data, const gchar *paramName );static int LoadHhc (ChmSee *window, FILE *hhc);// static int IsDirectory(char *buffer);/* * * 下面这些代码来自 chm_viewer 程序,但我作了修改,让本程序使用。 * 感谢 chm_viewer 作者 zbw(朱等翔) 的工作。 * */static gint getTagNumber( const gchar *data ) { gint length = strlen( data ); gint label = 0; gint num = 0; gint i; for( i=0; i<length; i++ ) { if( data[i]=='<' ) { label = 1; } else if( data[i]=='>' ) { if( label==1 ) { num++; label = 0; } } } return num;}static gchar *getTag( const gchar *data, int index ) { int length = strlen( data ); char buffer[512]; gchar *sendbuf; if( index<=0 || index > getTagNumber( data ) ) { sendbuf = g_strdup("\"\""); return ( sendbuf ); } int label = 0; int num = 0; int loop =0; int i; for( i=0; i<length; i++ ) { switch( data[i] ) { case '<': label = 1; num++; break; case '>': label = 0; break; } if( label==1 && num==index ) { buffer[loop] = data[i]; loop++; } if( label==0 && num==index ) { buffer[loop] = '>'; buffer[loop + 1] = '\0'; break; } } sendbuf = (gchar *) buffer; return sendbuf;}static gchar *getNameFromTag( const gchar *data ) { char buffer[512]; gchar *sendbuf; /** * 控制当前位置在 tag 中的位置的表示 * 0:初始状态 * 1:进入<并且在tag内的第一个字符前 * 2:在 tag name 内 * 3:离开 tag name * * < / tag >:5表示在 / 上 * 4表示在 / 和 tag 之间 * / 和 tag间的空格需要过滤掉,用 /tag表示这是一个 tag 标签的关闭标签 */ int label = 0; int loop = 0; int length = strlen( data ); int i; for( i=0; i<length; i++ ) { switch( data[i] ) { case '<': if( label==0 ) label = 1; break; case ' ': if( label==2 ) label = 3; if( label==5 ) label = 4; break; case '/': if( label==2 ) label = 3; if( label==1 ) label = 5; break; case '>': if( label==2 ) label = 3; break; default: if( label==1 || label==4 || label==5 ) label = 2; break; } if( label==3 ) { buffer[loop] = '\0'; break; } //是 name 的字符,添加 if( label==2 || label==5 ) { buffer[loop] = data[i]; loop ++; } } sendbuf = buffer; return sendbuf;}static gchar *getParamValueFromTag( const gchar *data, const gchar *paramName ) { char paramNameBuffer[255]; char paramValueBuffer[512]; int nameLoop = 0; int valueLoop = 0; gchar *sendbuffer; /** * 控制当前位置在 tag 中的位置的表示 * 0:初始状态 * 1:进入<并且在tag内的第一个字符前 * 2:在 tag name 内 * 3:结束tag * * < / tag >:5表示在 / 上 * 4表示在 / 和 tag 之间 * / 和 tag间的空格需要过滤掉,用 /tag表示这是一个 tag 标签的关闭标签 * 11:离开 name 进入参数区 * 12:进入参数名称 * 13:离开参数名称 * 14:进入参数名称后面的等号 * 16:在=后面的"上 * 15:进入参数的value区域 * value提取完后重新进入 11 状态 */ int label = 0; /** * 0:表示参数的value没有使用""引起来 * 1:表示参数的value使用""引起来了 */ int valueType = 0; int length = strlen( data ); int i; for( i=0; i<length; i++ ) { switch( data[i] ) { case '<': if( label==0 ) label = 1; if( label==16 ) { label = 15; } break; case ' ': if( label==2 ) label = 11; if( label==5 ) label = 4; if( label==12 ) label = 13; if( label==16 ) { label = 15; } if( label==15 && valueType==0) { //离开前一个参数的时候,需要把参数名称清空 paramNameBuffer[0] = '\0'; nameLoop = 0; label = 11; } break; case '/': if( label==2 ) label = 3; if( label==1 ) label = 5; if( label==16 ) { label = 15; } break; case '>': if( label==16 ) { label = 15; } if( valueType==0 ) label = 3; else { if( label!=15 ) label = 3; } break; case '=': if( label==12 || label==13 ) label = 14; if( label==16 ) { label = 15; } break; case '\"': if( label==15 || label==16 ) { //离开前一个参数的时候,需要把参数名称清空 paramNameBuffer[0] = '\0'; nameLoop = 0; label = 11; } if( label==14 ) { label = 16; valueType = 1; } break; default: if( label==1 || label==4 || label==5 ) label = 2; if( label==11 ) { //在参数前面的空格区域 label = 12; } if( label==14 ) { label = 15; valueType = 0; } if( label==16 ) { label = 15; } break; } if( label==5 || label==3) { //结束标签,不能有参数 break; } if( label==12 ) { //提取参数名称 paramNameBuffer[nameLoop] = data[i]; paramNameBuffer[nameLoop + 1] = '\0'; nameLoop++; } //printf( "label:%d========char:%c========param:%s\n", label, data[i], paramNameBuffer ); if( label==15 ) { //在value区域内,判断是否是需要的value if( g_strcasecmp(paramName, g_strdown(paramNameBuffer)) == 0) { paramValueBuffer[valueLoop] = data[i]; paramValueBuffer[valueLoop + 1] = '\0'; valueLoop++; } } } //printf( "loop:%d============value:%s=========data:%s\n", valueLoop, paramValueBuffer, data ); if( valueLoop==0 ) paramValueBuffer[valueLoop] = '\0'; sendbuffer = paramValueBuffer; return sendbuffer;}static intLoadHhc (ChmSee *window, FILE *hhc){ char lineBuf[256]; GtkTreeView *tree = GTK_TREE_VIEW(window->chm_tree); GtkTreeModel *model = gtk_tree_view_get_model (tree); GtkTreeIter iter; GtkTreeIter sibling_iter; gchar *tagData; gchar *tmpName; gchar *tmpValue; gchar *currentName = NULL; gchar *local = NULL; gchar *title_utf8; // = NULL; gchar *title; // = NULL; gchar *local_conv; // = NULL; gint label = 0; gint doc_label = 0; gint last_label = 0; gint tagNum; gint j; while (fgets (lineBuf, 512, hhc) != NULL) { tagNum = getTagNumber( lineBuf ); for( j=1; j<=tagNum; j++ ) { tagData = g_strdup(getTag( lineBuf, j )); tmpName = g_strdup(g_strdown(getNameFromTag( tagData ))); if( g_strcasecmp("ul", tmpName) == 0) { //进入一个 UL label = 1; doc_label++; } else if( g_strcasecmp("li", tmpName) == 0) { local = NULL; currentName = NULL; title_utf8 = NULL; title = NULL; local_conv = NULL; label = 3; } else if( g_strcasecmp("param", tmpName) == 0) { if( label==3 ) { //记录参数 tmpValue = g_strdup(getParamValueFromTag(tagData, "name")); if( g_strcasecmp("name", g_strdown(tmpValue)) == 0 ) { currentName = g_strdup( getParamValueFromTag( tagData, "value" )); } else if( g_strcasecmp("local", g_strdown(tmpValue)) == 0 ) { local = g_strdup( getParamValueFromTag( tagData, "value" )); } } } else if( g_strcasecmp("/object", tmpName) == 0) { if( label==3 ) { //生成目录条目 if (local == NULL) { local = g_strdup_printf("%s", "nolink"); } title_utf8 = g_convert(currentName, -1, "UTF-8", "GB18030", NULL, NULL, NULL); if (title_utf8) { title = g_strdup (title_utf8); } else { title = g_strdup(currentName); } local_conv = g_strdup(local); if (doc_label == 1) { gtk_tree_store_append(GTK_TREE_STORE (model), &iter, NULL); gtk_tree_store_set (GTK_TREE_STORE (model), &iter, TITLE_COLUMN, title, FILENAME_COLUMN, local_conv, -1); sibling_iter = iter; last_label = 1; } else { if ((doc_label - last_label) == 1) { gtk_tree_store_append(GTK_TREE_STORE (model), &iter, &sibling_iter); gtk_tree_store_set (GTK_TREE_STORE (model), &iter, TITLE_COLUMN, title, FILENAME_COLUMN, local_conv, -1); sibling_iter = iter; last_label++; } else if ((doc_label - last_label) == 0) { gtk_tree_store_insert_after(GTK_TREE_STORE (model), &iter, NULL, &sibling_iter); gtk_tree_store_set (GTK_TREE_STORE (model), &iter, TITLE_COLUMN, title, FILENAME_COLUMN, local_conv, -1); sibling_iter = iter; last_label = doc_label; } else if ((doc_label - last_label)== -1) { gtk_tree_store_insert_after(GTK_TREE_STORE (model), &iter, NULL, &sibling_iter); gtk_tree_store_set (GTK_TREE_STORE (model), &iter, TITLE_COLUMN, title, FILENAME_COLUMN, local_conv, -1); sibling_iter = iter; last_label--; } else { g_print("Error\n"); } } } } else if( g_strcasecmp("/ul", tmpName) == 0) { //向上返回一个级别 gtk_tree_model_iter_parent(model, &iter, &sibling_iter); sibling_iter = iter; doc_label--; last_label--; } } }// g_free(currentName);// g_free(local);// g_free(title_utf8);// g_free(title);// g_free(local_conv); return TRUE;}/* * 到这里结束 *///int open_hhc_file (ChmSee *window, const gchar *filename)intopen_hhc_file (ChmSee *window){ FILE *hhc; hhc = fopen (window->hhc_name, "r"); if (!hhc) { return FALSE; } if(!LoadHhc(window, hhc)) { return FALSE; } fclose (hhc); return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -