how to view a CHM file?

Just starting out? Need help? Post your questions and find answers here.
Mr.L
Enthusiast
Enthusiast
Posts: 146
Joined: Sun Oct 09, 2011 7:39 am

Re: how to view a CHM file?

Post by Mr.L »

Awesome, infratec! nice work!
AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Re: how to view a CHM file?

Post by AZJIO »

infratec
Thanks, this is cool!
Jan2004
Enthusiast
Enthusiast
Posts: 163
Joined: Fri Jan 07, 2005 7:17 pm

Re: how to view a CHM file?

Post by Jan2004 »

infratec: Congratulations!
User avatar
SPH
Enthusiast
Enthusiast
Posts: 561
Joined: Tue Jan 04, 2011 6:21 pm

Re: how to view a CHM file?

Post by SPH »

infratec : ...er, no, nothing... :wink:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 6.12LTS - 64 bits
AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Re: how to view a CHM file?

Post by AZJIO »

Length = UncompressMemory(...
Length = -1
What am I doing wrong?

Code: Select all

Structure item
	path.s
	length.i
	offset.i
EndStructure

Global item.item
; =========

For i = 1 To NumberOfChunkEntries
	*Entry + EncInt(*Entry, @QuadValue)
	; Debug PeekS(*Entry, QuadValue, #PB_UTF8|#PB_ByteLength)
	item\path = PeekS(*Entry, QuadValue, #PB_UTF8 | #PB_ByteLength)
	*Entry + QuadValue
	
	*Entry + EncInt(*Entry, @QuadValue)
	; Debug "content section: " + Str(QuadValue)
	*Entry + EncInt(*Entry, @QuadValue)
	; Debug "offset: " + Str(QuadValue)
	item\offset = QuadValue
	*Entry + EncInt(*Entry, @QuadValue)
	; Debug "length: " + Str(QuadValue)
	item\length = QuadValue
Next i


#File = 0
If item\path = "/html/file.htm" And Right(item\path, 1) <> "/" And Asc(item\path) And item\offset  And item\length > 0 And CreateFile(#File, "C:\CHM\html" + item\path, #PB_Ascii)
	*Out = AllocateMemory($100000, #PB_Memory_NoClear)
	Length = UncompressMemory(*FileBuffer + item\offset, item\length, *Out, MemorySize(*Out))
	; ShowMemoryViewer(*Out, 1000)
	Debug Length
	If Length > 0
		WriteData(#File, *Out, Length)
	EndIf
	FreeMemory(*Out) 
	CloseFile(#File)
EndIf
This works, but it extracts a compressed version of the file, which I can't decompress with any archiver. The size of the compressed version is exactly the same as the size of this file opened in the 7zip archiver.

Code: Select all

#File = 0
If item\path = "/html/file.htm" And Right(item\path, 1) <> "/" And Asc(item\path) And item\offset  And item\length > 0 And CreateFile(#File, "C:\D\PureBasic\Source\!My_projects\CHM\folder" + item\path, #PB_Ascii)
	WriteData(#File, *FileBuffer + item\offset, item\length)
	CloseFile(#File)
EndIf
infratec
Always Here
Always Here
Posts: 7577
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: how to view a CHM file?

Post by infratec »

I modified my listing above.

But I need LZX decompression:

http://www.jedrea.com/chmlib/

I already started to convert the lzx decode part
AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Re: how to view a CHM file?

Post by AZJIO »

chmViewer v0.7.1
Download: yandex upload.ee (exe+source+ini+ico+gif)
video

Code: Select all

;- AZJIO 16.01.2025
EnableExplicit

Define UserIntLang

CompilerSelect #PB_Compiler_OS
	CompilerCase #PB_OS_Windows
		Global *Lang
		If OpenLibrary(0, "kernel32.dll")
			*Lang = GetFunction(0, "GetUserDefaultUILanguage")
			If *Lang And CallFunctionFast(*Lang) = 1049
				UserIntLang = 1
			EndIf
			CloseLibrary(0)
		EndIf
	CompilerCase #PB_OS_Linux
		If ExamineEnvironmentVariables()
			While NextEnvironmentVariable()
				If Left(EnvironmentVariableName(), 4) = "LANG" And Left(EnvironmentVariableValue(), 2) = "ru"
					UserIntLang = 1
					Break
				EndIf
			Wend
		EndIf
CompilerEndSelect

#CountStrLang = 29
Global Dim Lng.s(#CountStrLang)
Lng(1) = "Fix DOCTYPE"
Lng(2) = "Convert HTML from ANSI to UTF-8"
Lng(3) = "Open Page"
Lng(4) = "Find"
Lng(5) = "Match case"
Lng(6) = "Whole word"
Lng(7) = "From the beginning"
Lng(8) = "Recode?"
Lng(9) = "Transcode pages to UTF-8?"
Lng(10) = "Count"
Lng(11) = "Files converted: "
Lng(12) = "package 7zip?"
Lng(13) = "Fix pseudocode in tree"
Lng(14) = "Done"
Lng(15) = "Help"
Lng(16) = "About"
Lng(17) = "Open in editor"
Lng(18) = "Open ini file"
Lng(19) = "Open TOC"
Lng(20) = "Open folder"
Lng(21) = "Next"
Lng(22) = "Count"
Lng(23) = "Reached the end of the list, nothing else found, start over?"
Lng(24) = "Find"
Lng(25) = "Find in the tree"
Lng(26) = "Find on pages"
Lng(27) = "Find on page"
Lng(28) = "Not found"
Lng(29) = "Found %s files in %t seconds"
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
Lng(33) = "Fix paths in html files"
CompilerEndIf

If UserIntLang
	Lng(1) = "Исправить DOCTYPE"
	Lng(2) = "Преобразовать HTML из ANSI в UTF-8"
	Lng(3) = "Открыть страницу в браузере"
	Lng(4) = "Найти"
	Lng(5) = "Учитывать регистр"
	Lng(6) = "Целое слово"
	Lng(7) = "От начала слова"
	Lng(8) = "Перекодировать?"
	Lng(9) = "Перекодировать страницы в UTF-8?"
	Lng(10) = "Подсчёт"
	Lng(11) = "Преобразовано файлов: "
	Lng(12) = "Пакет 7zip не установлен?"
	Lng(13) = "Исправить псевдокод в дереве"
	Lng(14) = "Готово"
	Lng(15) = "Справка"
	Lng(16) = "О программе"
	Lng(17) = "Открыть в редакторе"
	Lng(18) = "Открыть ini-файл"
	Lng(19) = "Открыть TOC"
	Lng(20) = "Открыть папку справки"
	Lng(21) = "Далее"
	Lng(22) = "Подсчитать"
	Lng(23) = "Достигнут конец списка, больше ничего не найдено, начать сначала?"
	Lng(24) = "Найти"
	Lng(25) = "Найти в дереве"
	Lng(26) = "Найти на страницах"
	Lng(27) = "Найти на странице"
	Lng(28) = "Не найдено"
	Lng(29) = "Найдено файлов: %s, за %t сек."
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
	Lng(33) = "Исправить пути в html-файлах"
CompilerEndIf
EndIf

Structure item
	name.s
	path.s
	anchor.s
EndStructure

Structure Path2
	path.s
	pathLCase.s
	file.s
	fileLCase.s
EndStructure

#q$ = Chr(34)
#SearchFile = 0

Enumeration File
	#File
	#FileCE
EndEnumeration

Enumeration RegExp
	#RegExpTOC
	#RegExpConvEnc
	#RegExpFixDOCTYPE
	#RegDelComm
	#RegExpFixPathTOC
	#RegExpFixPathHTML
	#RegExpWholeWord
EndEnumeration

Enumeration Window
	#Window
	#WinFind
EndEnumeration

Enumeration Menu
	#Menu
	#HelpMenu
	#MenuTree
EndEnumeration

Enumeration Gadget
	#tree
	#web
	#btnBack
	#btnForward
	#btnFind
	#btnOpen
	#btnHelpMenu
	#btnMenu
	#Splitter
	#strFind
	#btnSearch
	#btnSearchNext
	#btnCount
	#chCase
	#chWholeWord
	#chWordStart
	#optToTree
	#optToWeb
	#optToPage
	#StatusBar
EndEnumeration

Enumeration Menu
	#mBack
	#mFind
	#mEnter
	#mOpenPage
	#mEditor
	#mConvEncoding
	#mFixDOCTYPE
	#mPseudo
	#mFixPath
	#mFolder
	#mTOC
	#mINI
	#mHelp
	#mAbout
	#mLast
EndEnumeration

Enumeration images
	#ImageOpen
	#ImageHelpMenu
	#ImageMenu
	#ImageRight
	#ImageLeft
	#ImageFind
	#ImageTitle
	#ImageFile
	#ImageFolder
	#ImageFileBlack
	#ImageFolderBlack
EndEnumeration

Global dir0$, dir$, SearchWord$, pathTOS$
Global icon1, icon2, hIcon1
Global w = 634
Global h = 502
Global s = 200
Global cw, ch
Global flgOpen, mLast2
Global flgFind, flgFindCache, flgCount
Global FindPos, isBlack
Global chmfilestart$
Global NewList item.item()
Global NewList menu.item()
Global NewMap FileDeletionMap()

Declare GetTOC()
Declare SizeWindowHandler()
Declare Search(SearchText$)
Declare SearchWeb(SearchText$)
Declare SearchPage(SearchText$)
Declare ForceDirectories(Dir.s)
Declare ConvEncoding()
Declare OpenFileToConv(FilePath$)
Declare FileSearchHTML(List Files.s(), dir.s)
Declare FixDOCTYPE()
Declare FixPseudo()
Declare OpenCHM(chmfile$ = "")
Declare SetWindowTheme()
Declare FileFormat(FilePath$)
Declare EmptyFolders(Dir.s)

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
	Declare FixPath(AndHTML = 0)
CompilerEndIf

Define *pitem.item
Define ind, tmp$, tmp
Define em, ColorBG, ColorFR, ColorWin
Define SelElem
Define editor$

XIncludeFile "AutoDetectTextEncoding_Trim.pbi"
XIncludeFile "ForchmViewer.pb"

UseGIFImageDecoder()


DataSection
	Open:
	IncludeBinary "images" + #PS$ +"folder.gif"
	HelpMenu:
	IncludeBinary "images" + #PS$ +"HelpMenu.gif"
	Menu:
	IncludeBinary "images" + #PS$ +"menu.gif"
	Left:
	IncludeBinary "images" + #PS$ +"left.gif"
	Right:
	IncludeBinary "images" + #PS$ +"right.gif"
	Find:
	IncludeBinary "images" + #PS$ +"find.gif"
	File:
	IncludeBinary "images" + #PS$ +"file.gif"
	Folder:
	IncludeBinary "images" + #PS$ +"folder.gif"
	FileBlack:
	IncludeBinary "images" + #PS$ +"fileBlack.gif"
	FolderBlack:
	IncludeBinary "images" + #PS$ +"folderBlack.gif"

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
	ini:
	IncludeBinary "sample-Windows.ini"
	iniend:
	CompilerElse
	ini:
	IncludeBinary "sample-Linux.ini"
	iniend:
CompilerEndIf
EndDataSection
CatchImage(#ImageOpen, ?Open)
CatchImage(#ImageHelpMenu, ?HelpMenu)
CatchImage(#ImageMenu, ?Menu)
CatchImage(#ImageLeft, ?Left)
CatchImage(#ImageRight, ?Right)
CatchImage(#ImageFind, ?Find)
CatchImage(#ImageFile, ?file)
CatchImage(#ImageFolder, ?folder)
CatchImage(#ImageFileBlack, ?fileBlack)
CatchImage(#ImageFolderBlack, ?folderBlack)

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
	ImportC ""
		gtk_window_set_icon(a.l, b.l)
	EndImport

	DataSection
		Title:
		IncludeBinary "images" + #PS$ +"title.gif"
	EndDataSection

	CatchImage(#ImageTitle, ?Title)
	hIcon1 = ImageID(#ImageTitle)
CompilerEndIf




Global ini$
Global PathConfig$
PathConfig$ = GetPathPart(ProgramFilename())
If FileSize(PathConfig$ + "chmViewer.ini") = -1
	CompilerSelect #PB_Compiler_OS
		CompilerCase #PB_OS_Windows
			PathConfig$ = GetHomeDirectory() + "AppData\Roaming\chmViewer\"
		CompilerCase #PB_OS_Linux
			PathConfig$ = GetHomeDirectory() + ".config/chmViewer/"
	CompilerEndSelect
EndIf
ini$ = PathConfig$ + "chmViewer.ini"

If FileSize(ini$) = -1 And ForceDirectories(PathConfig$)
	SaveFile_Buff(ini$, ?ini, ?iniend - ?ini)
EndIf

If OpenPreferences(ini$)

	If PreferenceGroup("set")
		w = ReadPreferenceInteger("width", w)
		h = ReadPreferenceInteger("height", h)
		s = ReadPreferenceInteger("splitter", s)
		flgFind = ReadPreferenceInteger("flgfind", 4)
		flgFindCache = flgFind
		ColorBG = ColorValidate(ReadPreferenceString("background", ""), 0)
		ColorFR = ColorValidate(ReadPreferenceString("foreground", ""), 0)
		ColorWin = ColorValidate(ReadPreferenceString("winbg", ""), 0)
		SelElem = ReadPreferenceInteger("select", 0)
		editor$ = ReadPreferenceString("editor", "")
	EndIf

	If PreferenceGroup("chm")
		ExaminePreferenceKeys()
		ind = 0
		While NextPreferenceKey()
			If FileSize(PreferenceKeyValue()) > 0
				ind + 1
				If SelElem = ind
					dir0$ = GetPathPart(PreferenceKeyValue())
					pathTOS$ = GetFilePart(PreferenceKeyValue(), #PB_FileSystem_NoExtension)
					Break
				EndIf
			EndIf
		Wend
		ind = 0
	EndIf

	ClosePreferences()
EndIf


If (Red(ColorBG) + Green(ColorBG) + Blue(ColorBG)) / 3 > 127
	isBlack = 0
	icon1 = ImageID(#ImageFile)
	icon2 = ImageID(#ImageFolder)
Else
	isBlack = 1
	icon1 = ImageID(#ImageFileBlack)
	icon2 = ImageID(#ImageFolderBlack)
EndIf

Procedure GetComParam()
	Protected param$, i
	CompilerSelect #PB_Compiler_OS
		CompilerCase #PB_OS_Windows
			#prefix = '/'
		CompilerCase #PB_OS_Linux
			#prefix = '-'
	CompilerEndSelect
	If CountProgramParameters() = 1 And Right(ProgramParameter(0), 4) = ".chm" And FileSize(ProgramParameter(0))
		chmfilestart$ = ProgramParameter(0)
		dir0$ = ""
		ProcedureReturn
	EndIf
	For i = 1 To CountProgramParameters()
		param$ = ProgramParameter()
		If Asc(param$) = #prefix And PeekC(@param$ + 2 * SizeOf(Character)) = ':'
			Select PeekC(@param$ + 1 * SizeOf(Character))
				Case 'w'
					SearchWord$ = Mid(param$, 4)
				Case 'h'
					param$ = Mid(param$, 4)
					param$ = Trim(param$, #q$)
					dir0$ = GetPathPart(param$)
					pathTOS$ = GetFilePart(param$, #PB_FileSystem_NoExtension)
				Case 'p'
					dir0$ = Mid(param$, 4)
					dir0$ = Trim(dir0$, #q$)
					If Right(dir0$, 1) <> #PS$
						dir0$ + #PS$
					EndIf
				Case 't'
					pathTOS$ = Mid(param$, 4)
					pathTOS$ = Trim(pathTOS$, #q$)
				Case 'f'
					flgFind = Val(Mid(param$, 4))
			EndSelect
		EndIf

	Next
EndProcedure

GetComParam()

If Asc(dir0$)
	dir$ = "file:///" + dir0$
Else
	flgOpen = 1
EndIf


cw = w
ch = h

If OpenWindow(#Window, 0,0, w, h, "chmViewer", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)
	CompilerIf #PB_Compiler_OS = #PB_OS_Linux
		gtk_window_set_icon_(WindowID(#Window), ImageID(#ImageTitle))
	CompilerEndIf
	If ColorWin
		SetWindowColor(#Window, ColorWin)
	EndIf

	ButtonImageGadget(#btnBack, 5, 5, 34, 34, ImageID(#ImageLeft))
	ButtonImageGadget(#btnForward, 45, 5, 34, 34,  ImageID(#ImageRight))

	ButtonImageGadget(#btnFind, 85, 5, 34, 34,  ImageID(#ImageFind))
	ButtonImageGadget(#btnOpen, 125, 5, 34, 34,  ImageID(#ImageOpen))
	ButtonImageGadget(#btnHelpMenu, 165, 5, 34, 34,  ImageID(#ImageHelpMenu))
	ButtonImageGadget(#btnMenu, 205, 5, 34, 34,  ImageID(#ImageMenu))
	
	If CreatePopupMenu(#Menu)
		MenuItem(#mFixDOCTYPE, Lng(1))
		MenuItem(#mConvEncoding, Lng(2))
		MenuItem(#mPseudo, Lng(13))

		CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
			MenuItem(#mFixPath, Lng(25))
		CompilerEndIf
		MenuBar()
		MenuItem(#mFolder, Lng(20))
		MenuItem(#mTOC, Lng(19))
		MenuItem(#mINI, Lng(18))
		MenuBar()
		MenuItem(#mHelp, Lng(15))
		MenuItem(#mAbout, Lng(16))
	EndIf
	

	If CreatePopupMenu(#MenuTree)
		MenuItem(#mOpenPage, Lng(3))
		MenuItem(#mEditor, Lng(17))
	EndIf

	If OpenPreferences(ini$)
		PreferenceGroup("chm")
		ExaminePreferenceKeys()
		While NextPreferenceKey()
			If FileSize(PreferenceKeyValue()) > 0 And AddElement(menu())
				menu()\path = PreferenceKeyValue()
				menu()\name = StringField(PreferenceKeyName(), 1, "|")
			EndIf
		Wend
		ClosePreferences()
	EndIf
	ind = #mLast
	If CreatePopupMenu(#HelpMenu)
		ForEach menu()
			MenuItem(ind, menu()\name)
			ind + 1
		Next
	EndIf
	If ListSize(menu())
		mLast2 = ind - 1
	Else
		mLast2 = ind
	EndIf


	TreeGadget(#tree, 0, 0, 0, 0)
	If ColorBG And ColorFR
		SetGadgetColor(#tree, #PB_Gadget_BackColor, ColorBG)
		SetGadgetColor(#tree, #PB_Gadget_FrontColor, ColorFR)
	EndIf
	
	CompilerIf #PB_Compiler_OS = #PB_OS_Windows
		If isBlack
			SetWindowTheme()
		EndIf
	CompilerEndIf
	
	WebGadget(#web, 0, 0, 0, 0, "")

	SplitterGadget(#Splitter, 5, 44, w - 10, h - 52, #tree, #web, #PB_Splitter_Vertical | #PB_Splitter_FirstFixed)
	SetGadgetAttribute(#Splitter , #PB_Splitter_FirstMinimumSize, 30)
	SetGadgetState(#Splitter, s)

	If flgOpen
		OpenCHM(chmfilestart$)
	Else
		GetTOC()
	EndIf

	BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())

	If OpenWindow(#WinFind, #PB_Ignore, #PB_Ignore, 475, 145, Lng(24),
	              #PB_Window_SystemMenu | #PB_Window_Tool | #PB_Window_Invisible | #PB_Window_ScreenCentered, WindowID(#Window))

		StringGadget(#strFind, 5, 5, 360, 27, "")
		ButtonGadget(#btnSearch, 370, 5, 69, 29, Lng(4))
		ButtonGadget(#btnSearchNext, 442, 5, 27, 29, Chr($23F5))
		ButtonGadget(#btnCount, 370, 37, 99, 29, Lng(22))
		
		CheckBoxGadget(#chCase, 9, 44, 160, 22, Lng(5))
		CheckBoxGadget(#chWholeWord, 9, 70, 120, 22, Lng(6))
		CheckBoxGadget(#chWordStart, 9, 96, 160, 22, Lng(7))
		If flgFind & 1
			SetGadgetState(#chCase, #PB_Checkbox_Checked)
		EndIf
		If flgFind & 2
			SetGadgetState(#chWholeWord, #PB_Checkbox_Checked)
		EndIf
		If flgFind & 4
			SetGadgetState(#chWordStart, #PB_Checkbox_Checked)
		EndIf
		OptionGadget(#optToTree, 200, 44, 150, 22, Lng(25))
		OptionGadget(#optToWeb, 200, 70, 160, 22, Lng(26))
		OptionGadget(#optToPage, 200, 96, 160, 22, Lng(27))
		SetGadgetState(#optToTree, #PB_Checkbox_Checked)
		TextGadget(#StatusBar, 5, 120, 465, 20, "")
		SetActiveGadget(#strFind)
	EndIf

	If Asc(SearchWord$)
		Search(SearchWord$)
	EndIf

	AddKeyboardShortcut(#Window, #PB_Shortcut_Back, #mBack)
	AddKeyboardShortcut(#Window, #PB_Shortcut_Control | #PB_Shortcut_F, #mFind)
	AddKeyboardShortcut(#WinFind, #PB_Shortcut_Return, #mEnter)
	
	SetActiveWindow(#Window)

	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_Gadget
				Select EventGadget()
					Case #tree
						Select EventType()
							Case #PB_EventType_LeftClick
								ind = GetGadgetState(#tree)
								If ind > -1
									*pitem = GetGadgetItemData(#tree, ind)
									If *pitem And FileSize(dir0$ + *pitem\path) > 0
										SetGadgetText(#web, dir$ + *pitem\path + *pitem\anchor)
									ElseIf Asc(*pitem\path) And CreateFile(#File, dir0$ + "404.htm", #PB_UTF8)
										WriteString(#File, "<html><body><font size=22>404</font><br />" + *pitem\path + "</body></html>")
										CloseFile(#File)
										SetGadgetText(#web, dir$ + "404.htm")
									EndIf
								EndIf
							Case #PB_EventType_RightClick
								DisplayPopupMenu(#MenuTree, WindowID(#Window))
						EndSelect
					Case #web
					Case #btnBack
						SetGadgetState(#web, #PB_Web_Back)
					Case #btnForward
						SetGadgetState(#web, #PB_Web_Forward)
					Case #btnFind
						HideWindow(#WinFind, 0)
					Case #btnOpen
						OpenCHM()
					Case #btnSearch
						SearchWord$ = GetGadgetText(#strFind)
						If Asc(SearchWord$)
							If GetGadgetState(#optToTree) & #PB_Checkbox_Checked
								FindPos = 0
								Search(SearchWord$)
							ElseIf GetGadgetState(#optToWeb) & #PB_Checkbox_Checked
								SearchWeb(SearchWord$)
							ElseIf GetGadgetState(#optToPage) & #PB_Checkbox_Checked
								SearchPage(SearchWord$)
							EndIf
						EndIf
					Case #btnSearchNext
						SearchWord$ = GetGadgetText(#strFind)
						If Asc(SearchWord$)
							While Search(SearchWord$)
								
							Wend
						EndIf
					Case #btnCount
						SearchWord$ = GetGadgetText(#strFind)
						If Asc(SearchWord$)
							flgCount = 1
							Search(SearchWord$)
							flgCount = 0
						EndIf
					Case #btnHelpMenu
						DisplayPopupMenu(#HelpMenu, WindowID(#Window))
					Case #btnMenu
						DisplayPopupMenu(#Menu, WindowID(#Window))
				EndSelect
			Case #PB_Event_Menu
				em = EventMenu()
				Select em
					Case #mEnter
						SearchWord$ = GetGadgetText(#strFind)
						If Asc(SearchWord$)
							Search(SearchWord$)
						EndIf
					Case #mFind
						HideWindow(#WinFind, 0)
					Case #mBack
						SetGadgetState(#web, #PB_Web_Back)
					Case #mOpenPage
						ind = GetGadgetState(#tree)
						If ind > -1
							*pitem = GetGadgetItemData(#tree, ind)
							If *pitem And FileSize(dir0$ + *pitem\path) > 0
								CompilerSelect #PB_Compiler_OS
									CompilerCase #PB_OS_Windows
										RunProgram(dir0$ + *pitem\path)
									CompilerCase #PB_OS_Linux
										RunProgram("xdg-open", dir0$ + *pitem\path, dir0$)
								CompilerEndSelect
								
							EndIf
						EndIf
					Case #mConvEncoding
						If MessageRequester(Lng(8), Lng(9), #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
							ConvEncoding()
						EndIf
					Case #mFixDOCTYPE
						If MessageRequester(Lng(1) + "?", Lng(1) + "?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
							FixDOCTYPE()
						EndIf
					Case #mPseudo
						If MessageRequester(Lng(13) + "?", Lng(13) + "?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
							FixPseudo()
						EndIf
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
					Case #mFixPath
						If MessageRequester(Lng(25) + "?", Lng(25) + "?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
							FixPath(1)
						EndIf
	CompilerEndIf
					Case #mFolder
						CompilerSelect #PB_Compiler_OS
							CompilerCase #PB_OS_Windows
								RunProgram("explorer.exe", #q$ + dir0$ + #q$, "")
							CompilerCase #PB_OS_Linux
								RunProgram("xdg-open", #q$ + dir0$ + #q$, "")
						CompilerEndSelect
					Case #mHelp
						CompilerSelect #PB_Compiler_OS
							CompilerCase #PB_OS_Windows
								RunProgram("chmViewer.chm")
							CompilerCase #PB_OS_Linux
								SetGadgetText(#web, "file:////usr/share/help/ru/chmviewer/index.htm")
						CompilerEndSelect
					Case #mAbout
						MessageRequester(Lng(16), "AZJIO, v0.7.1 16.01.2025")
						
					Case #mTOC
						CompilerSelect #PB_Compiler_OS
							CompilerCase #PB_OS_Windows
								If Asc(editor$) And FileSize(editor$) > 0
									RunProgram(editor$, #q$ + dir0$ + pathTOS$ + ".hhc" + #q$, "")
								Else
									RunProgram("notepad.exe", #q$ + dir0$ + pathTOS$ + ".hhc" + #q$, "")
								EndIf
							CompilerCase #PB_OS_Linux
								If Asc(editor$)
									RunProgram(editor$, #q$ + dir0$ + pathTOS$ + ".hhc" + #q$, "")
								Else
									RunProgram("xdg-open", #q$ + dir0$ + pathTOS$ + ".hhc" + #q$, "")
								EndIf
						CompilerEndSelect
						
					Case #mINI
						CompilerSelect #PB_Compiler_OS
							CompilerCase #PB_OS_Windows
								If Asc(editor$) And FileSize(editor$) > 0
									RunProgram(editor$, #q$ + ini$ + #q$, "")
								Else
									RunProgram("notepad.exe", #q$ + ini$ + #q$, "")
								EndIf
							CompilerCase #PB_OS_Linux
								If Asc(editor$)
									RunProgram(editor$, #q$ + ini$ + #q$, "")
								Else
									RunProgram("xdg-open", #q$ + ini$ + #q$, "")
								EndIf
						CompilerEndSelect
						
					Case #mEditor
						ind = GetGadgetState(#tree)
						If ind > -1
							*pitem = GetGadgetItemData(#tree, ind)
							If *pitem And FileSize(dir0$ + *pitem\path) > 0
								CompilerSelect #PB_Compiler_OS
									CompilerCase #PB_OS_Windows
										If Asc(editor$) And FileSize(editor$) > 0
											RunProgram(editor$, #q$ + dir0$ + *pitem\path + #q$, "")
										Else
											RunProgram("notepad.exe", #q$ + dir0$ + *pitem\path + #q$, "")
										EndIf
									CompilerCase #PB_OS_Linux
										If Asc(editor$)
											RunProgram(editor$, #q$ + dir0$ + *pitem\path + #q$, "")
										EndIf
								CompilerEndSelect
							EndIf
						EndIf
						
						
					Case #mLast To mLast2
						If SelectElement(menu(), em - #mLast)
							dir0$ = GetPathPart(menu()\path)
							pathTOS$ = GetFilePart(menu()\path, #PB_FileSystem_NoExtension)
							If Asc(dir0$) And FileSize(dir0$) = -2 And FileSize(menu()\path) > 0
								dir$ = "file:///" + dir0$
								ClearList(item())
								ClearGadgetItems(#tree)
								If GetTOC()
									SetWindowTitle(#Window, "chmViewer: " + menu()\name)
								EndIf
							EndIf
						EndIf


				EndSelect
			Case #PB_Event_CloseWindow
				If EventWindow() = #WinFind
					HideWindow(#WinFind, 1)
				Else
					tmp = GetGadgetState(#Splitter)
					If w <> cw Or h <> ch Or s <> tmp
						If OpenPreferences(ini$)
							PreferenceGroup("set")
							WritePreferenceInteger("width", cw)
							WritePreferenceInteger("height", ch)
							WritePreferenceInteger("splitter", tmp)
							ClosePreferences()
						EndIf
					EndIf
					If GetGadgetState(#chCase) & #PB_Checkbox_Checked
						flgFind | 1
					Else
						flgFind & ~1
					EndIf
					If GetGadgetState(#chWholeWord) & #PB_Checkbox_Checked
						flgFind | 2
					Else
						flgFind & ~2
					EndIf
					If GetGadgetState(#chWordStart) & #PB_Checkbox_Checked
						flgFind | 4
					Else
						flgFind & ~4
					EndIf
					If flgFindCache <> flgFind
						If OpenPreferences(ini$)
							PreferenceGroup("set")
							WritePreferenceInteger("flgfind", flgFind)
							ClosePreferences()
						EndIf
					EndIf
					CloseWindow(#WinFind)
					CloseWindow(#Window)
					ForEach FileDeletionMap()
						tmp$ = MapKey(FileDeletionMap())
						If FileSize(tmp$) > -1
							DeleteFile(tmp$, #PB_FileSystem_Force)
						EndIf
					Next
					
					End
				EndIf
		EndSelect
	ForEver
EndIf




CompilerIf #PB_Compiler_OS = #PB_OS_Windows

Procedure SetWindowTheme()
	Protected Theme.s
	If OSVersion() >= #PB_OS_Windows_10
		Theme = "DarkMode_Explorer"
	Else
		Theme = "Explorer"
	EndIf

	SetWindowTheme_(GadgetID(#tree), @Theme, 0)
EndProcedure

CompilerEndIf


CompilerIf #PB_Compiler_OS = #PB_OS_Linux

Procedure ToCP1251(*s.Unicode)
    Protected i
    Protected *ptr.Unicode

    While *s\u
        If *s\u > 127 And *s\u < 256
            *ptr = ?CP1251 + (*s\u - 128) * 2
            *s\u = *ptr\u
        EndIf
        *s + SizeOf(Unicode)
    Wend
EndProcedure

DataSection
    CP1251:
    Data.u 1026, 1027, 8218, 1107, 8222, 8230, 8224, 8225, 8364, 8240, 1033
    Data.u 8249, 1034, 1036, 1035, 1039, 1106, 8216, 8217, 8220, 8221, 8226
    Data.u 8211, 8212, 152, 8482, 1113, 8250, 1114, 1116, 1115, 1119, 160
    Data.u 1038, 1118, 1032, 164, 1168, 166, 167, 1025, 169, 1028, 171
    Data.u 172, 173, 174, 1031, 176, 177, 1030, 1110, 1169, 181, 182
    Data.u 183, 1105, 8470, 1108, 187, 1112, 1029, 1109, 1111, 1040, 1041
    Data.u 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052
    Data.u 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063
    Data.u 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074
    Data.u 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085
    Data.u 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096
    Data.u 1097, 1098, 1099, 1100, 1101, 1102, 1103
EndDataSection

CompilerEndIf

Procedure FileFormat(FilePath$)
	Protected length, oFile, bytes, *mem, Format, res
	oFile = ReadFile(#PB_Any, FilePath$)
	If oFile
		Format = ReadStringFormat(oFile)
		length = Lof(oFile)
		*mem = AllocateMemory(length)
		If *mem
			bytes = ReadData(oFile, *mem, length)
			If bytes And Format = #PB_Ascii
				Format = dte::detectTextEncodingInBuffer(*mem, bytes, 0)
				If Format = #PB_Ascii
					res = 1
				EndIf
			EndIf
			FreeMemory(*mem)
		EndIf
		CloseFile(oFile)
	EndIf
	ProcedureReturn res
EndProcedure

Procedure FileSearchHTML(List Files.s(), dir.s)
    Protected name.s, id, ext.s

    If Right(dir, 1) <> #PS$
        dir + #PS$
    EndIf

    id = ExamineDirectory(#PB_Any, dir, "")
    If id
        While NextDirectoryEntry(id)
            name = DirectoryEntryName(id)
            If name = "." Or name = ".."
                Continue
            EndIf
            If DirectoryEntryType(id) = #PB_DirectoryEntry_Directory
                FileSearchHTML(Files(), dir + name + #PS$)
            Else
            	ext = GetExtensionPart(name)
            	If (ext = "html" Or ext = "htm") And AddElement(Files())
            		Files() = dir + DirectoryEntryName(id)
            	EndIf
            EndIf
        Wend
        FinishDirectory(id)
    EndIf
EndProcedure


Procedure OpenFileToConv(FilePath$)
	Protected length, oFile, bytes, *mem, Text$, Format, res
	oFile = ReadFile(#PB_Any, FilePath$)
	If oFile
		Format = ReadStringFormat(oFile)
		length = Lof(oFile)
		*mem = AllocateMemory(length)
		If *mem
			bytes = ReadData(oFile, *mem, length)
			If bytes
				If Format = #PB_Ascii
					Format = dte::detectTextEncodingInBuffer(*mem, bytes, 0)
					If Format = #PB_Ascii
						Text$ = PeekS(*mem, bytes, #PB_Ascii)
						Text$ = ReplaceRegularExpression(#RegExpConvEnc, Text$, "UTF-8")
						CompilerIf #PB_Compiler_OS = #PB_OS_Linux
							ToCP1251(@Text$)
						CompilerEndIf
						res = 1
					EndIf
				EndIf
			EndIf
			FreeMemory(*mem)
		EndIf
		CloseFile(oFile)
	EndIf
	If res
		CreateFile(#FileCE, FilePath$, #PB_UTF8)
		WriteString(#FileCE, Text$)
		CloseFile(#FileCE)
	EndIf
	ProcedureReturn res
EndProcedure


Procedure ConvEncoding()
	Protected Count
	Protected NewList Files.s()
	If Asc(dir0$) And FileSize(dir0$) = -2
		If CreateRegularExpression(#RegExpConvEnc, "charset\h*=\h*\K([\w-]+)", #PB_RegularExpression_NoCase)
			FileSearchHTML(Files(), dir0$)
			ForEach Files()
				Count + OpenFileToConv(Files())
			Next
			FreeRegularExpression(#RegExpConvEnc)
			MessageRequester(Lng(10), Lng(11) + Str(Count))
		EndIf
	EndIf
EndProcedure

Procedure OpenFileFixDOCTYPE(Path$, Format)
	Protected id_file, Text$
	id_file = ReadFile(#PB_Any, Path$, Format)
	If id_file
		Text$ = ReadString(id_file, #PB_File_IgnoreEOL)
		Text$ = ReplaceRegularExpression(#RegExpFixDOCTYPE, Text$, ~"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">")
		CloseFile(id_file)
		If CreateFile(#FileCE, Path$, Format)
			WriteString(#FileCE, Text$)
			CloseFile(#FileCE)
		EndIf
	EndIf
EndProcedure


Procedure FixDOCTYPE()
	Protected Count
	Protected NewList Files.s()
	If Asc(dir0$) And FileSize(dir0$) = -2
		If CreateRegularExpression(#RegExpFixDOCTYPE, "<!DOCTYPE\h*[^>]+?>", #PB_RegularExpression_NoCase)
			FileSearchHTML(Files(), dir0$)
			ForEach Files()
				If FileFormat(Files())
					OpenFileFixDOCTYPE(Files(), #PB_Ascii)
				Else
					OpenFileFixDOCTYPE(Files(), #PB_UTF8)
				EndIf
			Next
			FreeRegularExpression(#RegExpFixDOCTYPE)
			MessageRequester(Lng(10), Lng(11) + Str(ListSize(Files())))
		EndIf
	EndIf
EndProcedure


CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
Procedure FixPath(AndHTML = 0)
	Protected NewList Files.s()
	Protected NewList Files2.Path2()
	Protected length, Format, pathTosTotal$, Text$, pathLCase$, htmpath$
	
	length = Len(dir0$) + 1
	FileSearchHTML(Files(), dir0$)
	ForEach Files()
		If AddElement(Files2())
			Files2()\path = Mid(Files(), length)
			Files2()\pathLCase = LCase(Files2()\path)
		EndIf
	Next
	 
	pathTosTotal$ = dir0$ + pathTOS$ + ".hhc"
	Text$ = OpenFileToGadget(pathTosTotal$, @Format)
	If Format <> #PB_Ascii
		Format = #PB_UTF8
	EndIf
	
	If CreateRegularExpression(#RegExpFixPathTOC, "<param name=.Local. value=.\K[^\r\n:*?<>|]+]*?(?=.>)", #PB_RegularExpression_NoCase)
		If ExamineRegularExpression(#RegExpFixPathTOC, Text$)
			While NextRegularExpressionMatch(#RegExpFixPathTOC)
				If FileSize(dir0$ + RegularExpressionMatchString(#RegExpFixPathTOC)) < 0
					Debug "не найден: " + RegularExpressionMatchString(#RegExpFixPathTOC)
					pathLCase$ = LCase(RegularExpressionMatchString(#RegExpFixPathTOC))
					ForEach Files2()
						If Files2()\pathLCase = pathLCase$
							ReplaceString(Text$, RegularExpressionMatchString(#RegExpFixPathTOC), Files2()\path, #PB_String_InPlace, RegularExpressionMatchPosition(#RegExpFixPathTOC), 1)
							Debug "замена в позиции: " + RegularExpressionMatchPosition(#RegExpFixPathTOC)
							Break
						EndIf
					Next
				EndIf
			Wend
			If CreateFile(#File, dir0$ + "0.hhc", #PB_UTF8)
				WriteString(#File, Text$)
				CloseFile(#File)
			EndIf
		EndIf
		FreeRegularExpression(#RegExpFixPathTOC)
	EndIf
	If AndHTML
		Debug "——————————————————————"
		If CreateRegularExpression(#RegExpFixPathHTML, "(?<=\hhref=([" + #q$ + "']))[^\r\n<>|?*:]+?(?=\1)", #PB_RegularExpression_NoCase)
			ForEach Files()
					Files2()\file = GetPathPart(Files2()\path)
					Files2()\fileLCase = GetPathPart(Files2()\pathLCase)
			Next
			ForEach Files()
				Text$ = OpenFileToGadget(Files(), @Format)
				If Format <> #PB_Ascii
					Format = #PB_UTF8
				EndIf
				htmpath$ = GetPathPart(Files())
				If ExamineRegularExpression(#RegExpFixPathHTML, Text$)
					While NextRegularExpressionMatch(#RegExpFixPathHTML)
						If Asc(RegularExpressionMatchString(#RegExpFixPathHTML)) <> '.' And FileSize(htmpath$ + RegularExpressionMatchString(#RegExpFixPathHTML)) < 0
							Debug "не найден: " + RegularExpressionMatchString(#RegExpFixPathHTML)
							pathLCase$ = LCase(RegularExpressionMatchString(#RegExpFixPathHTML))
							ForEach Files2()
								If Files2()\fileLCase = pathLCase$
									ReplaceString(Text$, RegularExpressionMatchString(#RegExpFixPathHTML), Files2()\file, #PB_String_InPlace, RegularExpressionMatchPosition(#RegExpFixPathHTML), 1)
									Debug "замена в позиции: " + RegularExpressionMatchPosition(#RegExpFixPathHTML)
									Break
								EndIf
							Next
						EndIf
					Wend
				EndIf
				If CreateFile(#File, Files(), Format)
					WriteString(#File, Text$)
					CloseFile(#File)
				EndIf
			Next
			
			FreeRegularExpression(#RegExpFixPathHTML)
		Else
			Debug "Error"
		EndIf
		
		MessageRequester(Lng(14), Lng(14))
	EndIf
EndProcedure
CompilerEndIf


Procedure FixPseudo()
	Protected id_file, Text$, Format
	Protected Path$ = dir0$ + pathTOS$ + ".hhc"

	If Asc(Path$) And FileSize(Path$) > 0
		If FileFormat(Path$)
			Format =  #PB_Ascii
		Else
			Format = #PB_UTF8
		EndIf
		id_file = ReadFile(#PB_Any, Path$, Format)
		If id_file
			Text$ = ReadString(id_file, #PB_File_IgnoreEOL)
			CloseFile(id_file)
			If CreateFile(#FileCE, Path$, #PB_UTF8)
	
Text$ = ReplaceString(Text$, "&ograve;", "т")
Text$ = ReplaceString(Text$, "&Ecirc;", "К")
Text$ = ReplaceString(Text$, "&Aacute;", "Б")
Text$ = ReplaceString(Text$, "&Oslash;", "Ш")
Text$ = ReplaceString(Text$, "&Icirc;", "О")
Text$ = ReplaceString(Text$, "&THORN;", "Ю")
Text$ = ReplaceString(Text$, "&ETH;", "Р")
Text$ = ReplaceString(Text$, "&atilde;", "г")
Text$ = ReplaceString(Text$, "&Uuml;", "Ь")
Text$ = ReplaceString(Text$, "&Ugrave;", "Щ")
Text$ = ReplaceString(Text$, "&ouml;", "ц")
Text$ = ReplaceString(Text$, "&Ccedil;", "З")
Text$ = ReplaceString(Text$, "&Aring;", "Е")
Text$ = ReplaceString(Text$, "&Ocirc;", "Ф")
Text$ = ReplaceString(Text$, "&ntilde;", "с")
Text$ = ReplaceString(Text$, "&iuml;", "п")
Text$ = ReplaceString(Text$, "&uuml;", "ь")
Text$ = ReplaceString(Text$, "&egrave;", "и")
Text$ = ReplaceString(Text$, "&Iacute;", "Н")
Text$ = ReplaceString(Text$, "&yuml;", "я")
Text$ = ReplaceString(Text$, "&aring;", "е")
Text$ = ReplaceString(Text$, "&auml;", "д")
Text$ = ReplaceString(Text$, "&Ntilde;", "С")
Text$ = ReplaceString(Text$, "&Iuml;", "П")
Text$ = ReplaceString(Text$, "&Egrave;", "И")
Text$ = ReplaceString(Text$, "&Auml;", "Д")
Text$ = ReplaceString(Text$, "&Oacute;", "У")
Text$ = ReplaceString(Text$, "&Agrave;", "А")
Text$ = ReplaceString(Text$, "&Euml;", "Л")
Text$ = ReplaceString(Text$, "&Uacute;", "Ъ")
Text$ = ReplaceString(Text$, "&acirc;", "в")
Text$ = ReplaceString(Text$, "&Otilde;", "Х")
Text$ = ReplaceString(Text$, "&oslash;", "ш")
Text$ = ReplaceString(Text$, "&szlig;", "Я")
Text$ = ReplaceString(Text$, "&oacute;", "у")
Text$ = ReplaceString(Text$, "&agrave;", "а")
Text$ = ReplaceString(Text$, "&Atilde;", "Г")
Text$ = ReplaceString(Text$, "&ucirc;", "ы")
Text$ = ReplaceString(Text$, "&yacute;", "э")
Text$ = ReplaceString(Text$, "&divide;", "ч")
Text$ = ReplaceString(Text$, "&eth;", "р")
Text$ = ReplaceString(Text$, "&Eacute;", "Й")
Text$ = ReplaceString(Text$, "&thorn;", "ю")
Text$ = ReplaceString(Text$, "&times;", "Ч")
Text$ = ReplaceString(Text$, "&AElig;", "Ж")
Text$ = ReplaceString(Text$, "&otilde;", "х")
Text$ = ReplaceString(Text$, "&Yacute;", "Э")
Text$ = ReplaceString(Text$, "&aelig;", "ж")
Text$ = ReplaceString(Text$, "&Ucirc;", "Ы")
Text$ = ReplaceString(Text$, "&eacute;", "й")
Text$ = ReplaceString(Text$, "&euml;", "л")
Text$ = ReplaceString(Text$, "&Igrave;", "М")
Text$ = ReplaceString(Text$, "&aacute;", "б")
Text$ = ReplaceString(Text$, "&ocirc;", "ф")
Text$ = ReplaceString(Text$, "&Acirc;", "В")
Text$ = ReplaceString(Text$, "&igrave;", "м")
Text$ = ReplaceString(Text$, "&Ograve;", "Т")
Text$ = ReplaceString(Text$, "&ecirc;", "к")
Text$ = ReplaceString(Text$, "&iacute;", "н")
Text$ = ReplaceString(Text$, "&ccedil;", "з")
Text$ = ReplaceString(Text$, "&icirc;", "о")
Text$ = ReplaceString(Text$, "&ugrave;", "щ")
Text$ = ReplaceString(Text$, "&Ouml;", "Ц")
Text$ = ReplaceString(Text$, "&uacute;", "ъ")
Text$ = ReplaceString(Text$, "&Dstrok;", "Р")
Text$ = ReplaceString(Text$, "&quot;", Chr(34))
			
				WriteString(#FileCE, Text$)
				CloseFile(#FileCE)
			EndIf
		EndIf
		MessageRequester(Lng(14), Lng(14))
	EndIf
EndProcedure


Procedure OpenCHM(chmfile$ = "")
	Protected FSize, tmp$, Text$

	If Not (Asc(chmfile$) And FileSize(chmfile$) > 0)
		Repeat
			chmfile$ = OpenFileRequester("", GetCurrentDirectory(), "*.chm|*.chm", 0)
			If Asc(chmfile$)
				If Right(chmfile$, 4) <> ".chm"
					chmfile$ + ".chm"
				EndIf
			EndIf
			FSize = FileSize(chmfile$)
		Until (Asc(chmfile$) And FSize > 0) Or Not Asc(chmfile$)
	Else
		FSize = FileSize(chmfile$)
	EndIf

	If Not Asc(chmfile$)
		ProcedureReturn
	EndIf
	dir0$ = PathConfig$ + GetFilePart(chmfile$) + "-" + Str(FSize) + #PS$
	If FileSize(dir0$) <> -2 And ForceDirectories(dir0$)
		CompilerIf #PB_Compiler_OS = #PB_OS_Windows
			If FileSize("C:\Program Files\7-Zip\7z.exe") > 0
				RunProgram("C:\Program Files\7-Zip\7z.exe", "x " + #q$ + chmfile$ + #q$ + " -o" + #q$ + dir0$ + #q$ + " * -r -aos" , "", #PB_Program_Hide | #PB_Program_Wait)
			Else
				MessageRequester("?", "C:\Program Files\7-Zip\7z.exe")
			EndIf
		CompilerElse
			If Not RunProgram("7z", "x " + ReplaceString(chmfile$, " ", "\ ") + " -o" + ReplaceString(dir0$, " ", "\ ") + " * -r -aos" , "", #PB_Program_Hide | #PB_Program_Wait)
				MessageRequester("?", Lng(12))
			EndIf
		CompilerEndIf
	EndIf
	If EmptyFolders(dir0$)
		DeleteDirectory(dir0$, "")
		ProcedureReturn
	EndIf

	If ExamineDirectory(#SearchFile, dir0$, "*.hhc")
		If NextDirectoryEntry(#SearchFile) And DirectoryEntryType(#SearchFile) = #PB_DirectoryEntry_File
			tmp$ = dir0$ + DirectoryEntryName(#SearchFile)
			pathTOS$ = GetFilePart(DirectoryEntryName(#SearchFile), #PB_FileSystem_NoExtension)
		EndIf
		FinishDirectory(#SearchFile)
	EndIf

	If Not (Asc(tmp$) And FileSize(tmp$) > 0)
		End
	EndIf


	CompilerIf #PB_Compiler_OS = #PB_OS_Linux
		If FileFormat(tmp$)
			If ReadFile(#File, tmp$, #PB_Ascii)
				Text$ = ReadString(#File, #PB_File_IgnoreEOL)
				CloseFile(#File)
				ToCP1251(@Text$)
				If CreateFile(#File, dir0$ + "0.hhc", #PB_UTF8)
					WriteString(#File , Text$)
					CloseFile(#File)
					pathTOS$ = "0"
					

				EndIf
			EndIf
		EndIf
		
	CompilerEndIf
	
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
		FixPath()
	CompilerEndIf

	dir$ = "file:///" + dir0$
	ClearList(item())
	ClearGadgetItems(#tree)
	If GetTOC()
		SetWindowTitle(#Window, "chmViewer: " + GetFilePart(chmfile$))
		If OpenPreferences(ini$)
			PreferenceGroup("chm")
			WritePreferenceString(GetFilePart(chmfile$) + "|" + Str(FileSize(chmfile$)), dir0$ + pathTOS$ + ".hhc")
			ClosePreferences()
			If ListSize(menu())
				mLast2 + 1
			EndIf
			If AddElement(menu())
				menu()\path = dir0$ + pathTOS$ + ".hhc"
				menu()\name = GetFilePart(chmfile$)
				MenuItem(mLast2, menu()\name)
			EndIf
		EndIf
	EndIf
EndProcedure


Procedure GetTOC()
	Protected Text$, *pitem, i, Level, pos, oldLevel, Result, pathTosTotal$, Format


	pathTosTotal$ = dir0$ + pathTOS$ + ".hhc"
	If Asc(pathTosTotal$) And FileSize(pathTosTotal$) > 0
		If FileFormat(pathTosTotal$)
			Format =  #PB_Ascii
		Else
			Format = #PB_UTF8
		EndIf
	Else
		ProcedureReturn
	EndIf
	If ReadFile(#File, pathTosTotal$, Format)
		Repeat
			Text$ = ReadString(#File)
		Until FindString(Text$, "<UL>", 1, #PB_String_NoCase) Or Eof(#File) = 1
		If Eof(#File) = 1
			FileSeek(#File, 0)
			Repeat
				Text$ = ReadString(#File)
			Until FindString(Text$, "<BODY>", 1, #PB_String_NoCase) Or Eof(#File) = 1
		EndIf
	Else
		ProcedureReturn
	EndIf
	Text$ = ReadString(#File, #PB_File_IgnoreEOL)
	
	CloseFile(#File)
	If CreateRegularExpression(#RegDelComm, "<!--.*?-->")
		Text$ = ReplaceRegularExpression(#RegDelComm, Text$, "")
		FreeRegularExpression(#RegDelComm)
	EndIf
	If CreateRegularExpression(#RegExpTOC,
	     "<UL\K>|<\K/UL>|\s*<LI>\s*<OBJECT type=.text/sitemap.>\s*<param name=.Name. value=.([^\r\n]*?).>(?:\s*<param name=.Local. value=.([^\r\n:*?<>|]+]*?).>)?(?:\s*<param name=.ImageNumber. value=.([^\r\n:*?<>|]+]*?).>)?\s*</OBJECT>", #PB_RegularExpression_NoCase)

		If ExamineRegularExpression(#RegExpTOC, Text$)
			While NextRegularExpressionMatch(#RegExpTOC)
				Select RegularExpressionMatchString(#RegExpTOC)
					Case ">"
						Level + 1
					Case "/UL>", "/ul>"
						Level - 1
					Default
						*pitem = AddElement(item())
						If *pitem
							item()\name = RegularExpressionGroup(#RegExpTOC, 1)
							item()\path = RegularExpressionGroup(#RegExpTOC, 2)
							pos = FindString(item()\path, "#")
							If pos
								item()\path = Left(item()\path, pos - 1)
								item()\anchor = Mid(item()\path, pos)
							EndIf
							pos = FindString(item()\path, "%")
							If pos
								item()\path = URLDecoder(item()\path)
							EndIf
							If Level > oldLevel
								SetGadgetItemImage(#tree, i-1, icon2)
							EndIf
							AddGadgetItem(#tree, i, item()\name, icon1, Level)
							SetGadgetItemData(#tree, i, *pitem)
							oldLevel = Level
							i+1
						EndIf
				EndSelect
			Wend
			If ListSize(item())
				Result = 1
				i = 0
				ForEach item()
					SelectElement(item(), i)
					If Left(LCase(GetExtensionPart(item()\path)), 3) = "htm" And FileSize(dir0$ + item()\path) > 1
						SetGadgetText(#web, dir$ + item()\path)
						Break
					EndIf
					i + 1
				Next
			EndIf
		EndIf
		FreeRegularExpression(#RegExpTOC)
	EndIf

	ProcedureReturn Result
EndProcedure


Procedure SizeWindowHandler()
	cw = WindowWidth(#Window)
	ch = WindowHeight(#Window)
	ResizeGadget(#Splitter, #PB_Ignore, #PB_Ignore, cw - 10 , ch - 52)
EndProcedure


Procedure Search(SearchText$)
	Protected ind, flgCase, length, FindPosOld, StartTime, tmp$
	Protected NewList Count()
	Protected *Point, Result.string, length2
	
	FindPosOld = FindPos
	If flgCount
		StartTime = ElapsedMilliseconds()
	EndIf

	If Asc(SearchText$)
		If GetGadgetState(#chCase) & #PB_Checkbox_Checked
			flgCase = #PB_String_CaseSensitive
		Else
			flgCase = #PB_String_NoCase
		EndIf
		
		If GetGadgetState(#chWholeWord) & #PB_Checkbox_Checked
			If CreateRegularExpression(#RegExpWholeWord, "\b\Q" + SearchText$ + "\E\b", flgCase)
				If flgCount
					ForEach item()
						If MatchRegularExpression(#RegExpWholeWord, item()\name) And AddElement(Count())
							length2 + Len(item()\name) + Len(item()\path)
							Count() = @item()
						EndIf
					Next
				Else
					If FindPos
						SelectElement(item(), FindPos)
					Else
						ResetList(item())
					EndIf
					While NextElement(item())
						If MatchRegularExpression(#RegExpWholeWord, item()\name)
							ind = ListIndex(item())
							If FileSize(dir0$ + item()\path) > 0
								SetGadgetText(#web, dir$ + item()\path)
								SetGadgetState(#tree, ind)
								FindPos = ind
							EndIf
							Break
						EndIf
					Wend
				EndIf
				FreeRegularExpression(#RegExpWholeWord)
			EndIf
			ProcedureReturn
		EndIf

		If GetGadgetState(#chWordStart) & #PB_Checkbox_Checked
			length = Len(SearchText$)
			If flgCount
				ForEach item()
					If FindString(Left(item()\name, length), SearchText$, 1, flgCase) And AddElement(Count())
						length2 + Len(item()\name) + Len(item()\path)
						Count() = @item()
					EndIf
				Next
			Else
				If FindPos
					SelectElement(item(), FindPos)
				Else
					ResetList(item())
				EndIf
				While NextElement(item())
					If FindString(Left(item()\name, length), SearchText$, 1, flgCase)
						ind = ListIndex(item())
						If FileSize(dir0$ + item()\path) > 0
							SetGadgetText(#web, dir$ + item()\path)
							SetGadgetState(#tree, ind)
							FindPos = ind
						EndIf
						Break
					EndIf
				Wend
			EndIf
		Else
			If flgCount
				ForEach item()
					If FindString(item()\name, SearchText$, 1, flgCase) And AddElement(Count())
						length2 + Len(item()\name) + Len(item()\path)
						Count() = @item()
					EndIf
				Next
			Else
				If FindPos
					SelectElement(item(), FindPos)
				Else
					ResetList(item())
				EndIf
				While NextElement(item())
					If FindString(item()\name, SearchText$, 1, flgCase)
						ind = ListIndex(item())
						If FileSize(dir0$ + item()\path) > 0
							SetGadgetText(#web, dir$ + item()\path)
							SetGadgetState(#tree, ind)
							FindPos = ind
						EndIf
						Break
					EndIf
				Wend
			EndIf
		EndIf
		
		If flgCount
			If ListSize(Count()) And CreateFile(#File, dir0$ + "chmViewerFind.htm", #PB_UTF8)
				length2 + (ListSize(Count()) * 20)
				Result\s = Space(length2)
				*Point = @Result\s
				ForEach Count()
					ChangeCurrentElement(item(), Count())
					CopyMemoryString(@"<a href=", @*Point)
					CopyMemoryString(@item()\path, @*Point)
					CopyMemoryString(@">", @*Point)
					CopyMemoryString(@item()\name, @*Point)
					CopyMemoryString("</a><br />" + #LF$, @*Point)
				Next
				StartTime = ElapsedMilliseconds() - StartTime
				tmp$ = ReplaceString(Lng(29), "%s", "<font color='#FF8080'>" + Str(ListSize(Count())) + "</font>", #PB_String_CaseSensitive, 1, 1)
				tmp$ = ReplaceString(tmp$, "%t", FormatNumber(StartTime / 1000, 2, ".", ""), #PB_String_CaseSensitive, 1, 1)
				WriteString(#File, "<html><meta http-equiv='Content-Type' content='text/html; charset=utf-8'><style>body{color:#aaa;font-family:Arial} a{text-decoration:none;color:#88d;}</style><body bgcolor='#333333'>" + 
				                   tmp$ + "<br />" + #LF$  + Result\s + "</body></html>")
				CloseFile(#File)
				SetGadgetText(#web, dir$ + "chmViewerFind.htm")
				AddMapElement(FileDeletionMap(), dir0$ + "chmViewerFind.htm")
				tmp$ = ReplaceString(Lng(29), "%s", Str(ListSize(Count())), #PB_String_CaseSensitive, 1, 1)
				tmp$ = ReplaceString(tmp$, "%t", FormatNumber(StartTime / 1000, 2, ".", ""), #PB_String_CaseSensitive, 1, 1)
				SetGadgetText(#StatusBar, tmp$)
				ClearList(Count())
			EndIf
		ElseIf FindPosOld = FindPos And MessageRequester(SearchText$, Lng(23), #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
			FindPos = 0
			ProcedureReturn 1
		EndIf
	EndIf
	ProcedureReturn 0
EndProcedure


Procedure SearchWeb(SearchText$)
	Protected tmp$, Format, length, Text$, Count, flgCase, flgWholeWord, flgWordStart, success, StartTime, i
	Protected NewList Files.s()
	Protected NewList Count.item()
	Protected *Point, Result.string, length2
	
	
	If Asc(dir0$) And FileSize(dir0$) = -2
		StartTime = ElapsedMilliseconds()
		If GetGadgetState(#chCase) & #PB_Checkbox_Checked
			flgCase = #PB_String_CaseSensitive
		Else
			flgCase = #PB_String_NoCase
		EndIf
		flgWholeWord = GetGadgetState(#chWholeWord) & #PB_Checkbox_Checked
		flgWordStart = GetGadgetState(#chWordStart) & #PB_Checkbox_Checked
		length = Len(dir0$) + 1
		FileSearchHTML(Files(), dir0$)
		
			If flgWholeWord
				If CreateRegularExpression(#RegExpWholeWord, "(?<=[\A\s.,|:;!\\?/@#$%^&*(){}\[\]<>" + #q$ + "])\Q" + SearchText$ + "\E(?=[\z\s.,|:;!\\?/@#$%^&*(){}\[\]<>" + #q$ + "])", flgCase)
					success = 1
				EndIf
			ElseIf flgWordStart
				If CreateRegularExpression(#RegExpWholeWord, "(?<=[\A\s.,|:;!\\?/@#$%^&*(){}\[\]<>" + #q$ + "])\Q" + SearchText$ + "\E", flgCase)
					success = 1
				EndIf
			EndIf
		
		
		ForEach Files()
			i + 1
			If i >10
				SetGadgetText(#StatusBar, Mid(Files(), length))
				WindowEvent()
			EndIf
			Text$ = OpenFileToGadget(Files(), @Format)
			If success
				If MatchRegularExpression(#RegExpWholeWord, Text$)
					If AddElement(Count())
						Count()\path = Mid(Files(), length)
						Count()\name = GetExtensionPart(Count()\path)
						Count()\name = Left(Count()\path, Len(Count()\path) - Len(Count()\name) - 1)
						Count()\name = ReplaceString(Count()\name, #PS$, " &rarr; ")
						length2 + Len(Count()\path) + Len(Count()\name)
					EndIf
				EndIf
			ElseIf FindString(Text$, SearchText$, 1, flgCase)
				If AddElement(Count())
					Count()\path = Mid(Files(), length)
					Count()\name = GetExtensionPart(Count()\path)
					Count()\name = Left(Count()\path, Len(Count()\path) - Len(Count()\name) - 1)
					Count()\name = ReplaceString(Count()\name, #PS$, " &rarr; ")
					length2 + Len(Count()\path) + Len(Count()\name)
				EndIf
			EndIf
		Next
		If success
			FreeRegularExpression(#RegExpWholeWord)
		EndIf
		
		length2 + (ListSize(Count()) * 20)
		Result\s = Space(length2)
		*Point = @Result\s
		ForEach Count()
			CopyMemoryString(@"<a href=", @*Point)
			CopyMemoryString(@Count()\path, @*Point)
			CopyMemoryString(@">", @*Point)
			CopyMemoryString(@Count()\name, @*Point)
			CopyMemoryString("</a><br />" + #LF$, @*Point)
		Next
		StartTime = ElapsedMilliseconds() - StartTime
		
		If ListSize(Count()) And CreateFile(#File, dir0$ + "chmViewerFind.htm", #PB_UTF8)
			tmp$ = ReplaceString(Lng(29), "%s", "<font color='#FF8080'>" + Str(ListSize(Count())) + "</font>", #PB_String_CaseSensitive, 1, 1)
			tmp$ = ReplaceString(tmp$, "%t", FormatNumber(StartTime / 1000, 2, ".", ""), #PB_String_CaseSensitive, 1, 1)
			WriteString(#File, "<html><meta http-equiv='Content-Type' content='text/html; charset=utf-8'><style>body{color:#aaa;font-family:Arial} a{text-decoration:none;color:#88d;}</style><body bgcolor='#333333'>" +
			                   tmp$ + " <br />" + #LF$  + Result\s + "</body></html>")
			CloseFile(#File)
			SetGadgetText(#web, dir$ + "chmViewerFind.htm")
			tmp$ = ReplaceString(Lng(29), "%s", Str(ListSize(Count())), #PB_String_CaseSensitive, 1, 1)
			tmp$ = ReplaceString(tmp$, "%t", FormatNumber(StartTime / 1000, 2, ".", ""), #PB_String_CaseSensitive, 1, 1)
			SetGadgetText(#StatusBar, tmp$)
			AddMapElement(FileDeletionMap(), dir0$ + "chmViewerFind.htm")
			SetActiveGadget(#strFind)
		EndIf
	EndIf
EndProcedure


Procedure SearchPage(SearchText$)
	Protected Format, Text$, flgCase, pathfile$, pos, isFound
	SetGadgetText(#StatusBar, "")
	If Asc(dir0$) And FileSize(dir0$) = -2
		If GetGadgetState(#chCase) & #PB_Checkbox_Checked
			flgCase = #PB_String_CaseSensitive
		Else
			flgCase = #PB_String_NoCase
		EndIf
		pathfile$ = GetGadgetText(#web)
		If Left(pathfile$, 9) = "file:////"
			pathfile$ = Mid(pathfile$, 9)
		EndIf
		Text$ = OpenFileToGadget(pathfile$, @Format)
		
		
		If GetGadgetState(#chWholeWord) & #PB_Checkbox_Checked
			If CreateRegularExpression(#RegExpWholeWord, "(?<=[\A\s.,|:;!\\?/@#$%^&*(){}\[\]<>" + #q$ + "])\Q" + SearchText$ + "\E(?=[\z\s.,|:;!\\?/@#$%^&*(){}\[\]<>" + #q$ + "])", flgCase)
				If MatchRegularExpression(#RegExpWholeWord, Text$)
					Text$ = ReplaceRegularExpression(#RegExpWholeWord, Text$, "<span style='background-color:#FF00FF;color:#FFFFFF'>" + SearchText$ + "</span>")
					isFound = 1
				Else
					SetGadgetText(#StatusBar, Lng(28) + ": " + SearchText$)
				EndIf
				FreeRegularExpression(#RegExpWholeWord)
			EndIf
		ElseIf GetGadgetState(#chWordStart) & #PB_Checkbox_Checked
			If CreateRegularExpression(#RegExpWholeWord, "(?<=[\A\s.,|:;!\\?/@#$%^&*(){}\[\]<>" + #q$ + "])\Q" + SearchText$ + "\E", flgCase)
				If MatchRegularExpression(#RegExpWholeWord, Text$)
					Text$ = ReplaceRegularExpression(#RegExpWholeWord, Text$, "<span style='background-color:#FF00FF;color:#FFFFFF'>" + SearchText$ + "</span>")
					isFound = 1
				Else
					SetGadgetText(#StatusBar, Lng(28) + ": " + SearchText$)
				EndIf
				FreeRegularExpression(#RegExpWholeWord)
			EndIf
		Else
			pos = FindString(Text$, SearchText$, 1, flgCase)
			If pos
				Text$ = ReplaceString(Text$, SearchText$, "<span style='background-color:#FF00FF;color:#FFFFFF'>" + SearchText$ + "</span>", flgCase, pos)
				isFound = 1
			Else
				SetGadgetText(#StatusBar, Lng(28) + ": " + SearchText$)
			EndIf
		EndIf
		
		If isFound
			pathfile$ = GetPathPart(pathfile$) + "chmViewerFind.htm"
			If CreateFile(#File, pathfile$, Format)
				WriteString(#File, Text$)
				CloseFile(#File)
				SetGadgetText(#web, "file:///" + pathfile$)
				AddMapElement(FileDeletionMap(), pathfile$)
			EndIf
		EndIf
	EndIf
EndProcedure
Post Reply