1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <infotips.hxx>
22 #include <shlxthdl.hxx>
23 #include <metainforeader.hxx>
24 #include <contentreader.hxx>
25 #include <utilities.hxx>
26 #include <registry.hxx>
27 #include <fileextensions.hxx>
28 #include <iso8601_converter.hxx>
39 const std::wstring
WSPACE(SPACE
);
42 CInfoTip::CInfoTip(LONG RefCnt
) :
45 InterlockedIncrement(&g_DllRefCnt
);
51 InterlockedDecrement(&g_DllRefCnt
);
58 HRESULT STDMETHODCALLTYPE
CInfoTip::QueryInterface(REFIID riid
, void __RPC_FAR
*__RPC_FAR
*ppvObject
)
62 IUnknown
* pUnk
= nullptr;
64 if (IID_IUnknown
== riid
|| IID_IQueryInfo
== riid
)
66 pUnk
= static_cast<IQueryInfo
*>(this);
71 else if (IID_IPersistFile
== riid
)
73 pUnk
= static_cast<IPersistFile
*>(this);
83 ULONG STDMETHODCALLTYPE
CInfoTip::AddRef()
85 return InterlockedIncrement(&m_RefCnt
);
89 ULONG STDMETHODCALLTYPE
CInfoTip::Release()
91 LONG refcnt
= InterlockedDecrement(&m_RefCnt
);
99 //********************helper functions for GetInfoTip functions**********************
101 /** get file type information from registry.
103 static std::wstring
getFileTypeInfo(const std::wstring
& file_extension
)
105 wchar_t extKeyValue
[MAX_STRING
];
106 wchar_t typeKeyValue
[MAX_STRING
];
107 ::std::wstring
sDot(L
".");
108 if (QueryRegistryKey(HKEY_CLASSES_ROOT
, sDot
.append(file_extension
).c_str(), L
"", extKeyValue
, MAX_STRING
))
109 if (QueryRegistryKey( HKEY_CLASSES_ROOT
, extKeyValue
, L
"",typeKeyValue
, MAX_STRING
))
117 static DWORD
getSizeOfFile( wchar_t const * FileName
)
119 HANDLE hFile
= CreateFileW(FileName
, // open file
120 GENERIC_READ
, // open for reading
121 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
, // share for all operations
122 nullptr, // no security
123 OPEN_EXISTING
, // existing file only
124 FILE_ATTRIBUTE_NORMAL
, // normal file
125 nullptr); // no attr. template
127 if (hFile
!= INVALID_HANDLE_VALUE
)
129 DWORD dwSize
= GetFileSize( hFile
, nullptr );
130 CloseHandle( hFile
);
134 return INVALID_FILE_SIZE
;
137 /** format file size in to be more readable.
139 static std::wstring
formatSizeOfFile( DWORD dwSize
)
144 int dFileSize
= dwSize
;
146 _itoa( dFileSize
, buffer
, 10 );
147 return StringToWString( buffer
).append(StringToWString("B"));
150 char *buffer
=nullptr;
152 double dFileSize
= static_cast<double>(dwSize
)/KB
;
154 buffer
= _fcvt( dFileSize
, 1, &decimal
, &sign
);
156 ::std::wstring wsTemp
= StringToWString( buffer
);
158 ::std::wstring wsBuffer
= wsTemp
.substr( 0,pos
);
161 for (;decimal
- pos
> 2;pos
+= 3)
164 wsBuffer
.append(StringToWString(","));
165 wsBuffer
.append( wsTemp
.substr( pos
, 3) );
168 wsBuffer
.append(StringToWString("0"));
170 wsBuffer
.append(StringToWString("."));
171 wsBuffer
.append(wsTemp
.substr( decimal
, wsTemp
.size()-decimal
));
172 wsBuffer
.append(StringToWString("KB"));
178 /** get file size information.
180 static std::wstring
getFileSizeInfo(wchar_t const * FileName
)
182 DWORD dwSize
=getSizeOfFile(FileName
);
183 if (dwSize
!= INVALID_FILE_SIZE
)
184 return formatSizeOfFile( dwSize
);
190 // IQueryInfo methods
193 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE
CInfoTip::GetInfoTip(DWORD
/*dwFlags*/, PWSTR
* ppwszTip
)
196 const std::wstring
CONST_SPACE(SPACE
);
198 //display File Type, no matter other info is loaded successfully or not.
199 std::wstring tmpTypeStr
= getFileTypeInfo( get_file_name_extension(m_FileName
) );
200 if ( tmpTypeStr
!= EMPTY_STRING
)
202 msg
+= GetResString(IDS_TYPE_COLON
) + CONST_SPACE
;
208 CMetaInfoReader
meta_info_accessor(m_FileName
);
210 //display document title;
211 if ( meta_info_accessor
.getTagData( META_INFO_TITLE
).length() > 0)
213 if ( msg
!= EMPTY_STRING
)
215 msg
+= GetResString(IDS_TITLE_COLON
) + CONST_SPACE
;
216 msg
+= meta_info_accessor
.getTagData( META_INFO_TITLE
);
220 if ( msg
!= EMPTY_STRING
)
222 msg
+= GetResString(IDS_TITLE_COLON
) + CONST_SPACE
;
223 msg
+= m_FileNameOnly
;
226 //display document author;
227 if ( meta_info_accessor
.getTagData( META_INFO_AUTHOR
).length() > 0)
229 if ( msg
!= EMPTY_STRING
)
231 msg
+= GetResString( IDS_AUTHOR_COLON
) + CONST_SPACE
;
232 msg
+= meta_info_accessor
.getTagData( META_INFO_AUTHOR
);
235 //display document subject;
236 if ( meta_info_accessor
.getTagData( META_INFO_SUBJECT
).length() > 0)
238 if ( msg
!= EMPTY_STRING
)
240 msg
+= GetResString(IDS_SUBJECT_COLON
) + CONST_SPACE
;
241 msg
+= meta_info_accessor
.getTagData( META_INFO_SUBJECT
);
244 //display document description;
245 if ( meta_info_accessor
.getTagData( META_INFO_DESCRIPTION
).length() > 0)
247 if ( msg
!= EMPTY_STRING
)
249 msg
+= GetResString( IDS_COMMENTS_COLON
) + CONST_SPACE
;
250 msg
+= meta_info_accessor
.getTagData( META_INFO_DESCRIPTION
);
253 //display modified time formatted into locale representation.
254 if ( iso8601_date_to_local_date(meta_info_accessor
.getTagData(META_INFO_MODIFIED
)).length() > 0)
256 if ( msg
!= EMPTY_STRING
)
258 msg
+= GetResString( IDS_MODIFIED_COLON
) + CONST_SPACE
;
259 msg
+= iso8601_date_to_local_date(meta_info_accessor
.getTagData(META_INFO_MODIFIED
));
262 catch (const std::exception
&)
266 //display file size, no matter other information is loaded successfully or not.
267 std::wstring tmpSizeStr
= getFileSizeInfo(m_FileName
.c_str());
268 if ( tmpSizeStr
!= EMPTY_STRING
)
271 msg
+= GetResString( IDS_SIZE_COLON
) + CONST_SPACE
;
276 //finalize and assign the string.
278 HRESULT hr
= SHGetMalloc(&lpMalloc
);
282 size_t len
= sizeof(wchar_t) * msg
.length() + sizeof(wchar_t);
283 wchar_t* pMem
= static_cast<wchar_t*>(lpMalloc
->Alloc(len
));
285 ZeroMemory(pMem
, len
);
287 wcscpy_s(pMem
, msg
.length()+1, msg
.c_str());
299 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE
CInfoTip::GetInfoFlags(DWORD
* /*pdwFlags*/ )
308 HRESULT STDMETHODCALLTYPE
CInfoTip::GetClassID(CLSID
* pClassID
)
310 *pClassID
= CLSID_INFOTIP_HANDLER
;
315 // IPersistFile methods
318 HRESULT STDMETHODCALLTYPE
CInfoTip::Load(LPCOLESTR pszFileName
, DWORD
/*dwMode*/)
320 std::wstring fname
= pszFileName
;
322 // there must be a '\' and there must even be an
323 // extension, else we would not have been called
324 std::wstring::iterator begin
= fname
.begin() + fname
.find_last_of(L
"\\") + 1;
325 std::wstring::iterator end
= fname
.end();
327 m_FileNameOnly
= std::wstring(begin
, end
);
329 m_FileName
= getShortPathName(fname
);
335 HRESULT STDMETHODCALLTYPE
CInfoTip::IsDirty()
341 HRESULT STDMETHODCALLTYPE
CInfoTip::Save(LPCOLESTR
/*pszFileName*/, BOOL
/*fRemember*/)
347 HRESULT STDMETHODCALLTYPE
CInfoTip::SaveCompleted(LPCOLESTR
/*pszFileName*/)
353 HRESULT STDMETHODCALLTYPE
CInfoTip::GetCurFile(LPOLESTR __RPC_FAR
* /*ppszFileName*/)
358 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */