Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
cff5f60d
Commit
cff5f60d
authored
Feb 07, 2010
by
Erich Hoover
Committed by
Alexandre Julliard
Feb 08, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
hhctrl.ocx: Add Search capability.
parent
6627b902
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
318 additions
and
7 deletions
+318
-7
Makefile.in
dlls/hhctrl.ocx/Makefile.in
+1
-0
chm.c
dlls/hhctrl.ocx/chm.c
+0
-1
help.c
dlls/hhctrl.ocx/help.c
+45
-6
hhctrl.h
dlls/hhctrl.ocx/hhctrl.h
+12
-0
search.c
dlls/hhctrl.ocx/search.c
+247
-0
stream.c
dlls/hhctrl.ocx/stream.c
+12
-0
stream.h
dlls/hhctrl.ocx/stream.h
+1
-0
No files found.
dlls/hhctrl.ocx/Makefile.in
View file @
cff5f60d
...
...
@@ -12,6 +12,7 @@ C_SRCS = \
hhctrl.c
\
index.c
\
regsvr.c
\
search.c
\
stream.c
\
webbrowser.c
...
...
dlls/hhctrl.ocx/chm.c
View file @
cff5f60d
...
...
@@ -389,7 +389,6 @@ CHMInfo *OpenCHM(LPCWSTR szFile)
WARN
(
"Could not open storage: %08x
\n
"
,
hres
);
return
CloseCHM
(
ret
);
}
hres
=
IStorage_OpenStream
(
ret
->
pStorage
,
wszSTRINGS
,
NULL
,
STGM_READ
,
0
,
&
ret
->
strings_stream
);
if
(
FAILED
(
hres
))
{
...
...
dlls/hhctrl.ocx/help.c
View file @
cff5f60d
...
...
@@ -421,6 +421,7 @@ static LRESULT OnTopicChange(HHInfo *info, void *user_data)
{
LPCWSTR
chmfile
=
NULL
,
name
=
NULL
,
local
=
NULL
;
ContentItem
*
citer
;
SearchItem
*
siter
;
IndexItem
*
iiter
;
if
(
!
user_data
||
!
info
)
...
...
@@ -472,6 +473,12 @@ static LRESULT OnTopicChange(HHInfo *info, void *user_data)
local
=
iiter
->
items
[
0
].
local
;
chmfile
=
iiter
->
merge
.
chm_file
;
break
;
case
TAB_SEARCH
:
siter
=
(
SearchItem
*
)
user_data
;
name
=
siter
->
filename
;
local
=
siter
->
filename
;
chmfile
=
info
->
pCHMInfo
->
szFile
;
break
;
default:
FIXME
(
"Unhandled operation for this tab!
\n
"
);
return
0
;
...
...
@@ -523,8 +530,16 @@ static LRESULT CALLBACK Child_WndProc(HWND hWnd, UINT message, WPARAM wParam, LP
case
TVN_SELCHANGEDW
:
return
OnTopicChange
(
info
,
(
void
*
)((
NMTREEVIEWW
*
)
lParam
)
->
itemNew
.
lParam
);
case
NM_DBLCLK
:
if
(
info
&&
info
->
current_tab
==
TAB_INDEX
)
if
(
!
info
)
return
0
;
switch
(
info
->
current_tab
)
{
case
TAB_INDEX
:
return
OnTopicChange
(
info
,
(
void
*
)((
NMITEMACTIVATE
*
)
lParam
)
->
lParam
);
case
TAB_SEARCH
:
return
OnTopicChange
(
info
,
(
void
*
)((
NMITEMACTIVATE
*
)
lParam
)
->
lParam
);
}
break
;
case
NM_RETURN
:
if
(
!
info
)
return
0
;
...
...
@@ -540,11 +555,34 @@ static LRESULT CALLBACK Child_WndProc(HWND hWnd, UINT message, WPARAM wParam, LP
return
0
;
}
case
TAB_SEARCH
:
{
WCHAR
needle
[
100
];
GetWindowTextW
(
info
->
search
.
hwndEdit
,
needle
,
sizeof
(
needle
)
/
sizeof
(
WCHAR
));
FIXME
(
"Search for text: %s
\n
"
,
debugstr_w
(
needle
));
return
0
;
if
(
nmhdr
->
hwndFrom
==
info
->
search
.
hwndEdit
)
{
char
needle
[
100
];
DWORD
i
,
len
;
len
=
GetWindowTextA
(
info
->
search
.
hwndEdit
,
needle
,
sizeof
(
needle
));
if
(
!
len
)
{
FIXME
(
"Unable to get search text.
\n
"
);
return
0
;
}
/* Convert the requested text for comparison later against the
* lower case version of HTML file contents.
*/
for
(
i
=
0
;
i
<
len
;
i
++
)
needle
[
i
]
=
tolower
(
needle
[
i
]);
InitSearch
(
info
,
needle
);
return
0
;
}
else
if
(
nmhdr
->
hwndFrom
==
info
->
search
.
hwndList
)
{
HWND
hwndList
=
info
->
search
.
hwndList
;
LVITEMW
lvItem
;
lvItem
.
iItem
=
(
int
)
SendMessageW
(
hwndList
,
LVM_GETSELECTIONMARK
,
0
,
0
);
lvItem
.
mask
=
TVIF_PARAM
;
ListView_GetItemW
(
hwndList
,
&
lvItem
);
OnTopicChange
(
info
,
(
void
*
)
lvItem
.
lParam
);
return
0
;
}
break
;
}
}
break
;
...
...
@@ -1376,6 +1414,7 @@ void ReleaseHelpViewer(HHInfo *info)
ReleaseWebBrowser
(
info
);
ReleaseContent
(
info
);
ReleaseIndex
(
info
);
ReleaseSearch
(
info
);
if
(
info
->
WinType
.
hwndHelp
)
DestroyWindow
(
info
->
WinType
.
hwndHelp
);
...
...
dlls/hhctrl.ocx/hhctrl.h
View file @
cff5f60d
...
...
@@ -83,6 +83,14 @@ typedef struct IndexItem {
IndexSubItem
*
items
;
}
IndexItem
;
typedef
struct
SearchItem
{
struct
SearchItem
*
next
;
HTREEITEM
id
;
LPWSTR
title
;
LPWSTR
filename
;
}
SearchItem
;
typedef
struct
CHMInfo
{
IITStorage
*
pITStorage
;
...
...
@@ -115,6 +123,7 @@ typedef struct {
}
IndexPopup
;
typedef
struct
{
SearchItem
*
root
;
HWND
hwndEdit
;
HWND
hwndList
;
HWND
hwndContainer
;
...
...
@@ -175,6 +184,9 @@ void ReleaseHelpViewer(HHInfo*);
BOOL
NavigateToUrl
(
HHInfo
*
,
LPCWSTR
);
BOOL
NavigateToChm
(
HHInfo
*
,
LPCWSTR
,
LPCWSTR
);
void
InitSearch
(
HHInfo
*
info
,
const
char
*
needle
);
void
ReleaseSearch
(
HHInfo
*
info
);
/* memory allocation functions */
static
inline
void
*
__WINE_ALLOC_SIZE
(
1
)
heap_alloc
(
size_t
len
)
...
...
dlls/hhctrl.ocx/search.c
0 → 100644
View file @
cff5f60d
/*
* Copyright 2010 Erich Hoover
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "hhctrl.h"
#include "stream.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
htmlhelp
);
static
SearchItem
*
SearchCHM_Folder
(
SearchItem
*
item
,
IStorage
*
pStorage
,
const
WCHAR
*
folder
,
const
char
*
needle
);
/* Allocate a ListView entry for a search result. */
static
SearchItem
*
alloc_search_item
(
WCHAR
*
title
,
const
WCHAR
*
filename
)
{
int
filename_len
=
filename
?
(
strlenW
(
filename
)
+
1
)
*
sizeof
(
WCHAR
)
:
0
;
SearchItem
*
item
;
item
=
heap_alloc_zero
(
sizeof
(
SearchItem
));
if
(
filename
)
{
item
->
filename
=
heap_alloc
(
filename_len
);
memcpy
(
item
->
filename
,
filename
,
filename_len
);
}
item
->
title
=
title
;
/* Already allocated */
return
item
;
}
/* Fill the ListView object corresponding to the found Search tab items */
static
void
fill_search_tree
(
HWND
hwndList
,
SearchItem
*
item
)
{
int
index
=
0
;
LVITEMW
lvi
;
SendMessageW
(
hwndList
,
LVM_DELETEALLITEMS
,
0
,
0
);
while
(
item
)
{
TRACE
(
"list debug: %s
\n
"
,
debugstr_w
(
item
->
filename
));
memset
(
&
lvi
,
0
,
sizeof
(
lvi
));
lvi
.
iItem
=
index
++
;
lvi
.
mask
=
LVIF_TEXT
|
LVIF_PARAM
;
lvi
.
cchTextMax
=
strlenW
(
item
->
title
)
+
1
;
lvi
.
pszText
=
item
->
title
;
lvi
.
lParam
=
(
LPARAM
)
item
;
item
->
id
=
(
HTREEITEM
)
SendMessageW
(
hwndList
,
LVM_INSERTITEMW
,
0
,
(
LPARAM
)
&
lvi
);
item
=
item
->
next
;
}
}
/* Search the CHM storage stream (an HTML file) for the requested text.
*
* Before searching the HTML file all HTML tags are removed so that only
* the content of the document is scanned. If the search string is found
* then the title of the document is returned.
*/
static
WCHAR
*
SearchCHM_File
(
IStorage
*
pStorage
,
const
WCHAR
*
file
,
const
char
*
needle
)
{
char
*
buffer
=
heap_alloc
(
BLOCK_SIZE
);
strbuf_t
content
,
node
,
node_name
;
IStream
*
temp_stream
=
NULL
;
DWORD
i
,
buffer_size
=
0
;
WCHAR
*
title
=
NULL
;
BOOL
found
=
FALSE
;
stream_t
stream
;
HRESULT
hres
;
hres
=
IStorage_OpenStream
(
pStorage
,
file
,
NULL
,
STGM_READ
,
0
,
&
temp_stream
);
if
(
FAILED
(
hres
))
{
FIXME
(
"Could not open '%s' stream: %08x
\n
"
,
debugstr_w
(
file
),
hres
);
goto
cleanup
;
}
strbuf_init
(
&
node
);
strbuf_init
(
&
content
);
strbuf_init
(
&
node_name
);
stream_init
(
&
stream
,
temp_stream
);
/* Remove all HTML formatting and record the title */
buffer
=
heap_alloc
(
0
);
while
(
next_node
(
&
stream
,
&
node
))
{
get_node_name
(
&
node
,
&
node_name
);
if
(
next_content
(
&
stream
,
&
content
)
&&
content
.
len
>
1
)
{
char
*
text
=
&
content
.
buf
[
1
];
int
textlen
=
content
.
len
-
1
;
if
(
!
strcasecmp
(
node_name
.
buf
,
"title"
))
{
int
wlen
=
MultiByteToWideChar
(
CP_ACP
,
0
,
text
,
textlen
,
NULL
,
0
);
title
=
heap_alloc
((
wlen
+
1
)
*
sizeof
(
WCHAR
));
MultiByteToWideChar
(
CP_ACP
,
0
,
text
,
textlen
,
title
,
wlen
);
title
[
wlen
]
=
0
;
}
buffer
=
heap_realloc
(
buffer
,
buffer_size
+
textlen
+
1
);
memcpy
(
&
buffer
[
buffer_size
],
text
,
textlen
);
buffer
[
buffer_size
+
textlen
]
=
'\0'
;
buffer_size
+=
textlen
;
}
strbuf_zero
(
&
node
);
strbuf_zero
(
&
content
);
}
/* Convert the buffer to lower case for comparison against the
* requested text (already in lower case).
*/
for
(
i
=
0
;
i
<
buffer_size
;
i
++
)
buffer
[
i
]
=
tolower
(
buffer
[
i
]);
/* Search the decoded buffer for the requested text */
if
(
strstr
(
buffer
,
needle
))
found
=
TRUE
;
strbuf_free
(
&
node
);
strbuf_free
(
&
content
);
strbuf_free
(
&
node_name
);
cleanup:
heap_free
(
buffer
);
if
(
temp_stream
)
IStream_Release
(
temp_stream
);
if
(
!
found
)
{
heap_free
(
title
);
return
NULL
;
}
return
title
;
}
/* Search all children of a CHM storage object for the requested text and
* return the last found search item.
*/
static
SearchItem
*
SearchCHM_Storage
(
SearchItem
*
item
,
IStorage
*
pStorage
,
const
char
*
needle
)
{
const
WCHAR
szHTMext
[]
=
{
'.'
,
'h'
,
't'
,
'm'
,
0
};
IEnumSTATSTG
*
elem
=
NULL
;
WCHAR
*
filename
=
NULL
;
STATSTG
entries
;
HRESULT
hres
;
ULONG
retr
;
hres
=
IStorage_EnumElements
(
pStorage
,
0
,
NULL
,
0
,
&
elem
);
if
(
hres
!=
S_OK
)
{
FIXME
(
"Could not enumerate '/' storage elements: %08x
\n
"
,
hres
);
return
NULL
;
}
while
(
IEnumSTATSTG_Next
(
elem
,
1
,
&
entries
,
&
retr
)
==
NOERROR
)
{
switch
(
entries
.
type
)
{
case
STGTY_STORAGE
:
item
=
SearchCHM_Folder
(
item
,
pStorage
,
entries
.
pwcsName
,
needle
);
break
;
case
STGTY_STREAM
:
filename
=
entries
.
pwcsName
;
while
(
strchrW
(
filename
,
'/'
))
filename
=
strchrW
(
filename
,
'/'
)
+
1
;
if
(
strstrW
(
filename
,
szHTMext
))
{
WCHAR
*
title
=
SearchCHM_File
(
pStorage
,
filename
,
needle
);
if
(
title
)
{
item
->
next
=
alloc_search_item
(
title
,
entries
.
pwcsName
);
item
=
item
->
next
;
}
}
break
;
default:
FIXME
(
"Unhandled IStorage stream element.
\n
"
);
}
}
return
item
;
}
/* Open a CHM storage object (folder) by name and find all items with
* the requested text. The last found item is returned.
*/
static
SearchItem
*
SearchCHM_Folder
(
SearchItem
*
item
,
IStorage
*
pStorage
,
const
WCHAR
*
folder
,
const
char
*
needle
)
{
IStorage
*
temp_storage
=
NULL
;
HRESULT
hres
;
hres
=
IStorage_OpenStorage
(
pStorage
,
folder
,
NULL
,
STGM_READ
,
NULL
,
0
,
&
temp_storage
);
if
(
FAILED
(
hres
))
{
FIXME
(
"Could not open '%s' storage object: %08x
\n
"
,
debugstr_w
(
folder
),
hres
);
return
NULL
;
}
item
=
SearchCHM_Storage
(
item
,
temp_storage
,
needle
);
IStorage_Release
(
temp_storage
);
return
item
;
}
/* Search the entire CHM file for the requested text and add all of
* the found items to a ListView for the user to choose the item
* they want.
*/
void
InitSearch
(
HHInfo
*
info
,
const
char
*
needle
)
{
CHMInfo
*
chm
=
info
->
pCHMInfo
;
SearchItem
*
root_item
=
alloc_search_item
(
NULL
,
NULL
);
SearchCHM_Storage
(
root_item
,
chm
->
pStorage
,
needle
);
fill_search_tree
(
info
->
search
.
hwndList
,
root_item
->
next
);
if
(
info
->
search
.
root
)
ReleaseSearch
(
info
);
info
->
search
.
root
=
root_item
;
}
/* Free all of the found Search items. */
void
ReleaseSearch
(
HHInfo
*
info
)
{
SearchItem
*
item
=
info
->
search
.
root
;
info
->
search
.
root
=
NULL
;
while
(
item
)
{
heap_free
(
item
->
filename
);
item
=
item
->
next
;
}
}
dlls/hhctrl.ocx/stream.c
View file @
cff5f60d
...
...
@@ -98,6 +98,18 @@ void get_node_name(strbuf_t *node, strbuf_t *name)
strbuf_append
(
name
,
""
,
1
);
}
/* Return the stream content up to the next HTML tag.
*
* Note: the first returned character is the end of the last tag (>).
*/
BOOL
next_content
(
stream_t
*
stream
,
strbuf_t
*
buf
)
{
if
(
!
stream_chr
(
stream
,
buf
,
'<'
))
return
FALSE
;
return
TRUE
;
}
BOOL
next_node
(
stream_t
*
stream
,
strbuf_t
*
buf
)
{
if
(
!
stream_chr
(
stream
,
NULL
,
'<'
))
...
...
dlls/hhctrl.ocx/stream.h
View file @
cff5f60d
...
...
@@ -41,6 +41,7 @@ void strbuf_append(strbuf_t *buf, const char *data, int len);
void
stream_init
(
stream_t
*
stream
,
IStream
*
str
);
BOOL
stream_chr
(
stream_t
*
stream
,
strbuf_t
*
buf
,
char
c
);
void
get_node_name
(
strbuf_t
*
node
,
strbuf_t
*
name
);
BOOL
next_content
(
stream_t
*
stream
,
strbuf_t
*
buf
);
BOOL
next_node
(
stream_t
*
stream
,
strbuf_t
*
buf
);
const
char
*
get_attr
(
const
char
*
node
,
const
char
*
name
,
int
*
len
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment