⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hhc.c

📁 又一开源的解压缩chm格式文件的代码
💻 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 + -