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

📄 libchmfileimpl.cpp

📁 chm阅读器 用于在linux系统下chm文档的阅读
💻 CPP
📖 第 1 页 / 共 3 页
字号:
QCString LCHMFileImpl::convertSearchWord( const QString & src ){	static const char * searchwordtable[128] =	{		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "s", 0, "oe", 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "s", 0, "oe", 0, 0, "y",  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  "a", "a", "a", "a", "a", "a", "ae", "c", "e", "e", "e", "e", "i", "i", "i", "i",  "d", "n", "o", "o", "o", "o", "o", 0, "o", "u", "u", "u", "u", "y", "\xDE", "ss",  "a", "a", "a", "a", "a", "a", "ae", "c", "e", "e", "e", "e", "i", "i", "i", "i",  "o", "n", "o", "o", "o", "o", "o", 0, "o", "u", "u", "u", "u", "y", "\xFE", "y"	};	if ( !m_textCodec )		return (QCString) src.lower();	QCString dest = m_textCodec->fromUnicode (src);	for ( unsigned int i = 0; i < dest.size(); i++ )	{		if ( dest[i] & 0x80 )		{			int index = dest[i] & 0x7F;			if ( searchwordtable[index] )				dest.replace (i, 1, searchwordtable[index]);			else				dest.remove (i, 1);		}	}	return dest.lower();}void LCHMFileImpl::getSearchResults( const LCHMSearchProgressResults& tempres, 									 QStringList * results, 		  							 unsigned int limit_results ){	unsigned char combuf [COMMON_BUF_LEN];	QMap<u_int32_t, u_int32_t> urlsmap;  // used to prevent duplicated urls		for ( unsigned int i = 0; i < tempres.size(); i++ )	{		if ( urlsmap.find (tempres[i].urloff) != urlsmap.end() )			continue;				urlsmap[tempres[i].urloff] = 1;				if ( RetrieveObject (&m_chmURLSTR, combuf, tempres[i].urloff + 8, COMMON_BUF_LEN - 1) == 0 )			continue;		combuf[COMMON_BUF_LEN - 1] = 0;		results->push_back( LCHMUrlFactory::makeURLabsoluteIfNeeded( (const char*) combuf ) );				if ( --limit_results == 0 )			break;	}}QString LCHMFileImpl::normalizeUrl( const QString & path ) const{	int pos = path.find ('#');	QString fixedpath = pos == -1 ? path : path.left (pos);		return LCHMUrlFactory::makeURLabsoluteIfNeeded( fixedpath );}/* * FIXME: <OBJECT type="text/sitemap"><param name="Merge" value="hhaxref.chm::/HHOCX_c.hhc"></OBJECT> *  (from htmlhelp.chm)*/bool LCHMFileImpl::parseFileAndFillArray( const QString & file, QT34VECTOR< LCHMParsedEntry > * data, bool asIndex ){	QString src;	const int MAX_NEST_DEPTH = 256;	if ( !getFileContentAsString( &src, file ) || src.isEmpty() )		return false;	KCHMShowWaitCursor wc;		/*	// Save the index for debugging purposes	QFile outfile( "parsed.htm" );		if ( outfile.open( IO_WriteOnly ) )	{		QTextStream textstream( &outfile );		textstream << src;		outfile.close();	}*/		unsigned int defaultimagenum = asIndex ? LCHMBookIcons::IMAGE_INDEX : LCHMBookIcons::IMAGE_AUTO;	int pos = 0, indent = 0, root_indent_offset = 0;	bool in_object = false, root_indent_offset_set = false;		LCHMParsedEntry entry;	entry.imageid = defaultimagenum;		// Split the HHC file by HTML tags	int stringlen = src.length();		while ( pos < stringlen && (pos = src.find ('<', pos)) != -1 )	{		int i, word_end = 0;				for ( i = ++pos; i < stringlen; i++ )		{			// If a " or ' is found, skip to the next one.			if ( (src[i] == '"' || src[i] == '\'') )			{				// find where quote ends, either by another quote, or by '>' symbol (some people don't know HTML)				int nextpos = src.find (src[i], i+1);				if ( nextpos == -1 	&& (nextpos = src.find ('>', i+1)) == -1 )				{					qWarning ("LCHMFileImpl::ParseHhcAndFillTree: corrupted TOC: %s", src.mid(i).ascii());					return false;				}				i =  nextpos;			}			else if ( src[i] == '>'  )				break;			else if ( !src[i].isLetterOrNumber() && src[i] != '/' && !word_end )				word_end = i;		}				QString tagword, tag = src.mid (pos, i - pos);		 		if ( word_end )			tagword = src.mid (pos, word_end - pos).lower();		else			tagword = tag.lower();		//qDebug ("tag: '%s', tagword: '%s'\n", tag.ascii(), tagword.ascii());								// <OBJECT type="text/sitemap"> - a topic entry		if ( tagword == "object" && tag.find ("text/sitemap", 0, false) != -1 )			in_object = true;		else if ( tagword == "/object" && in_object ) 		{			// a topic entry closed. Add a tree item			if ( entry.name )			{				if ( !root_indent_offset_set )				{					root_indent_offset_set = true;					root_indent_offset = indent;										if ( root_indent_offset > 1 )						qWarning("CHM has improper index; root indent offset is %d", root_indent_offset);				}				int real_indent = indent - root_indent_offset;								entry.indent = real_indent;				data->push_back( entry );			}			else			{				if ( !entry.urls.isEmpty() )					qDebug ("LCHMFileImpl::ParseAndFillTopicsTree: <object> tag with url \"%s\" is parsed, but name is empty.", entry.urls[0].ascii());				else					qDebug ("LCHMFileImpl::ParseAndFillTopicsTree: <object> tag is parsed, but both name and url are empty.");				}			entry.name = QString::null;			entry.urls.clear();			entry.imageid = defaultimagenum;			in_object = false;		}		else if ( tagword == "param" && in_object )		{			// <param name="Name" value="First Page">			int offset; // strlen("param ")			QString name_pattern = "name=", value_pattern = "value=";			QString pname, pvalue;			if ( (offset = tag.find (name_pattern, 0, FALSE)) == -1 )				qFatal ("LCHMFileImpl::ParseAndFillTopicsTree: bad <param> tag '%s': no name=\n", tag.ascii());			// offset+5 skips 'name='			offset = findStringInQuotes (tag, offset + name_pattern.length(), pname, TRUE, FALSE);			pname = pname.lower();			if ( (offset = tag.find (value_pattern, offset, FALSE)) == -1 )				qFatal ("LCHMFileImpl::ParseAndFillTopicsTree: bad <param> tag '%s': no value=\n", tag.ascii());			// offset+6 skips 'value='			findStringInQuotes (tag, offset + value_pattern.length(), pvalue, FALSE, TRUE);			//qDebug ("<param>: name '%s', value '%s'", pname.ascii(), pvalue.ascii());			if ( pname == "name" )			{				// Some help files contain duplicate names, where the second name is empty. Work it around by keeping the first one				if ( !pvalue.isEmpty() )					entry.name = pvalue;			}			else if ( pname == "local" )			{				// Check for URL duplication				QString url = LCHMUrlFactory::makeURLabsoluteIfNeeded( pvalue );								if ( entry.urls.find( url ) == entry.urls.end() )					entry.urls.push_back( url );			}			else if ( pname == "see also" && asIndex && entry.name != pvalue )				entry.urls.push_back (":" + pvalue);			else if ( pname == "imagenumber" )			{				bool bok;				int imgnum = pvalue.toInt (&bok);					if ( bok && imgnum >= 0 && imgnum < LCHMBookIcons::MAX_BUILTIN_ICONS )					entry.imageid = imgnum;			}		}		else if ( tagword == "ul" ) // increase indent level		{			// Fix for buggy help files					if ( ++indent >= MAX_NEST_DEPTH )				qFatal("LCHMFileImpl::ParseAndFillTopicsTree: max nest depth (%d) is reached, error in help file", MAX_NEST_DEPTH);			// This intended to fix <ul><ul>, which was seen in some buggy chm files,			// and brokes rootentry[indent-1] check		}		else if ( tagword == "/ul" ) // decrease indent level		{			if ( --indent < root_indent_offset )				indent = root_indent_offset;						DEBUGPARSER(("</ul>: new intent is %d\n", indent - root_indent_offset));		}		pos = i;		}		return true;}bool LCHMFileImpl::getFileContentAsBinary( QByteArray * data, const QString & url ) const{	chmUnitInfo ui;	if( !ResolveObject( url, &ui ) )		return false;	data->resize( ui.length );				if ( RetrieveObject( &ui, (unsigned char*) data->data(), 0, ui.length ) )		return true;	else		return false;}	bool LCHMFileImpl::getFileContentAsString( QString * str, const QString & url, bool internal_encoding ){	QByteArray buf;		if ( getFileContentAsBinary( &buf, url ) )	{		unsigned int length = buf.size();				if ( length > 0 )		{			buf.resize( length + 1 );			buf [length] = '\0';						*str = internal_encoding ? (QString)((const char*) buf) :  encodeWithCurrentCodec((const char*) buf);			return true;		}	}		return false;}QString LCHMFileImpl::getTopicByUrl( const QString & url ) const{	QMap< QString, QString >::const_iterator it = m_url2topics.find( url );		if ( it == m_url2topics.end() )		return QString::null;		return it.data();}static int chm_enumerator_callback( struct chmFile*, struct chmUnitInfo *ui, void *context ){	((QStringList*) context)->push_back( ui->path );	return CHM_ENUMERATOR_CONTINUE;}bool LCHMFileImpl::enumerateFiles( QStringList * files ){	files->clear();	return chm_enumerate( m_chmFile, CHM_ENUMERATE_ALL, chm_enumerator_callback, files );}const QPixmap * LCHMFileImpl::getBookIconPixmap( unsigned int imagenum ){	return m_imagesKeeper.getImage( imagenum );}bool LCHMFileImpl::setCurrentEncoding( const LCHMTextEncoding * encoding ){	m_currentEncoding = encoding;	return changeFileEncoding( encoding->qtcodec );}bool LCHMFileImpl::guessTextEncoding( ){	const LCHMTextEncoding * enc = 0;	if ( !m_detectedLCID || (enc = lookupByLCID (m_detectedLCID)) == 0 )		qFatal ("Could not detect text encoding by LCID");		if ( changeFileEncoding (enc->qtcodec) )	{		m_currentEncoding = enc;		return true;	}		return false;}bool LCHMFileImpl::changeFileEncoding( const char *qtencoding  ){	// Encoding could be either simple Qt codepage, or set like CP1251/KOI8, which allows to	// set up encodings separately for text (first) and internal files (second)	const char * p = strchr( qtencoding, '/' );	if ( p )	{		char buf[128]; // much bigger that any encoding possible. No DoS; all encodings are hardcoded.		strcpy( buf, qtencoding );		buf[p - qtencoding] = '\0';				m_textCodec = QTextCodec::codecForName( buf );			if ( !m_textCodec )		{			qWarning( "Could not set up Text Codec for encoding '%s'", buf );			return false;		}				m_textCodecForSpecialFiles = QTextCodec::codecForName( p + 1 );			if ( !m_textCodecForSpecialFiles )		{			qWarning( "Could not set up Text Codec for encoding '%s'", p + 1 );			return false;		}	}	else	{		m_textCodecForSpecialFiles = m_textCodec = QTextCodec::codecForName (qtencoding);			if ( !m_textCodec )		{			qWarning( "Could not set up Text Codec for encoding '%s'", qtencoding );			return false;		}	}		m_entityDecodeMap.clear();	return true;}void LCHMFileImpl::fillTopicsUrlMap(){	if ( !m_lookupTablesValid )		return;	// Read those tables	QByteArray topics( m_chmTOPICS.length ), urltbl( m_chmURLTBL.length ), urlstr( m_chmURLSTR.length ), strings( m_chmSTRINGS.length );	if ( !RetrieveObject( &m_chmTOPICS, (unsigned char*) topics.data(), 0, m_chmTOPICS.length )	|| !RetrieveObject( &m_chmURLTBL, (unsigned char*) urltbl.data(), 0, m_chmURLTBL.length )	|| !RetrieveObject( &m_chmURLSTR, (unsigned char*) urlstr.data(), 0, m_chmURLSTR.length )	|| !RetrieveObject( &m_chmSTRINGS, (unsigned char*) strings.data(), 0, m_chmSTRINGS.length ) )		return;		for ( unsigned int i = 0; i < m_chmTOPICS.length; i += TOPICS_ENTRY_LEN )	{		u_int32_t off_title = get_int32_le( (u_int32_t *)(topics.data() + i + 4) );		u_int32_t off_url = get_int32_le( (u_int32_t *)(topics.data() + i + 8) );		off_url = get_int32_le( (u_int32_t *)( urltbl.data() + off_url + 8) ) + 8;		QString url = LCHMUrlFactory::makeURLabsoluteIfNeeded( (const char*) urlstr.data() + off_url );		if ( off_title < strings.size() )			m_url2topics[url] = encodeWithCurrentCodec ( (const char*) strings.data() + off_title );		else			m_url2topics[url] = "Untitled";	}}bool LCHMFileImpl::getFileSize(unsigned int * size, const QString & url){	chmUnitInfo ui;	if( !ResolveObject( url, &ui ) )		return false;	*size = ui.length;	return true;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -