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 ZeroMemory(m_szFileName
, sizeof(m_szFileName
));
46 InterlockedIncrement(&g_DllRefCnt
);
52 InterlockedDecrement(&g_DllRefCnt
);
59 HRESULT STDMETHODCALLTYPE
CInfoTip::QueryInterface(REFIID riid
, void __RPC_FAR
*__RPC_FAR
*ppvObject
)
63 IUnknown
* pUnk
= nullptr;
65 if (IID_IUnknown
== riid
|| IID_IQueryInfo
== riid
)
67 pUnk
= static_cast<IQueryInfo
*>(this);
72 else if (IID_IPersistFile
== riid
)
74 pUnk
= static_cast<IPersistFile
*>(this);
84 ULONG STDMETHODCALLTYPE
CInfoTip::AddRef()
86 return InterlockedIncrement(&m_RefCnt
);
90 ULONG STDMETHODCALLTYPE
CInfoTip::Release()
92 long refcnt
= InterlockedDecrement(&m_RefCnt
);
100 //********************helper functions for GetInfoTip functions**********************
102 /** get file type information from registry.
104 static std::wstring
getFileTypeInfo(const std::wstring
& file_extension
)
106 wchar_t extKeyValue
[MAX_STRING
];
107 wchar_t typeKeyValue
[MAX_STRING
];
108 ::std::wstring
sDot(L
".");
109 if (QueryRegistryKey(HKEY_CLASSES_ROOT
, sDot
.append(file_extension
).c_str(), L
"", extKeyValue
, MAX_STRING
))
110 if (QueryRegistryKey( HKEY_CLASSES_ROOT
, extKeyValue
, L
"",typeKeyValue
, MAX_STRING
))
118 static DWORD
getSizeOfFile( wchar_t const * FileName
)
120 HANDLE hFile
= CreateFileW(FileName
, // open file
121 GENERIC_READ
, // open for reading
122 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
, // share for all operations
123 nullptr, // no security
124 OPEN_EXISTING
, // existing file only
125 FILE_ATTRIBUTE_NORMAL
, // normal file
126 nullptr); // no attr. template
128 if (hFile
!= INVALID_HANDLE_VALUE
)
130 DWORD dwSize
= GetFileSize( hFile
, nullptr );
131 CloseHandle( hFile
);
135 return INVALID_FILE_SIZE
;
138 /** format file size in to be more readable.
140 static std::wstring
formatSizeOfFile( DWORD dwSize
)
145 int dFileSize
= dwSize
;
147 _itoa( dFileSize
, buffer
, 10 );
148 return StringToWString( buffer
).append(StringToWString("B"));
151 char *buffer
=nullptr;
153 double dFileSize
= static_cast<double>(dwSize
)/KB
;
155 buffer
= _fcvt( dFileSize
, 1, &decimal
, &sign
);
157 ::std::wstring wsTemp
= StringToWString( buffer
);
159 ::std::wstring wsBuffer
= wsTemp
.substr( 0,pos
);
162 for (;decimal
- pos
> 2;pos
+= 3)
165 wsBuffer
.append(StringToWString(","));
166 wsBuffer
.append( wsTemp
.substr( pos
, 3) );
169 wsBuffer
.append(StringToWString("0"));
171 wsBuffer
.append(StringToWString("."));
172 wsBuffer
.append(wsTemp
.substr( decimal
, wsTemp
.size()-decimal
));
173 wsBuffer
.append(StringToWString("KB"));
179 /** get file size information.
181 static std::wstring
getFileSizeInfo(wchar_t const * FileName
)
183 DWORD dwSize
=getSizeOfFile(FileName
);
184 if (dwSize
!= INVALID_FILE_SIZE
)
185 return formatSizeOfFile( dwSize
);
191 // IQueryInfo methods
194 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE
CInfoTip::GetInfoTip(DWORD
/*dwFlags*/, PWSTR
* ppwszTip
)
197 const std::wstring
CONST_SPACE(SPACE
);
199 //display File Type, no matter other info is loaded successfully or not.
200 std::wstring tmpTypeStr
= getFileTypeInfo( get_file_name_extension(m_szFileName
) );
201 if ( tmpTypeStr
!= EMPTY_STRING
)
203 msg
+= GetResString(IDS_TYPE_COLON
) + CONST_SPACE
;
209 CMetaInfoReader
meta_info_accessor(m_szFileName
);
211 //display document title;
212 if ( meta_info_accessor
.getTagData( META_INFO_TITLE
).length() > 0)
214 if ( msg
!= EMPTY_STRING
)
216 msg
+= GetResString(IDS_TITLE_COLON
) + CONST_SPACE
;
217 msg
+= meta_info_accessor
.getTagData( META_INFO_TITLE
);
221 if ( msg
!= EMPTY_STRING
)
223 msg
+= GetResString(IDS_TITLE_COLON
) + CONST_SPACE
;
224 msg
+= m_FileNameOnly
;
227 //display document author;
228 if ( meta_info_accessor
.getTagData( META_INFO_AUTHOR
).length() > 0)
230 if ( msg
!= EMPTY_STRING
)
232 msg
+= GetResString( IDS_AUTHOR_COLON
) + CONST_SPACE
;
233 msg
+= meta_info_accessor
.getTagData( META_INFO_AUTHOR
);
236 //display document subject;
237 if ( meta_info_accessor
.getTagData( META_INFO_SUBJECT
).length() > 0)
239 if ( msg
!= EMPTY_STRING
)
241 msg
+= GetResString(IDS_SUBJECT_COLON
) + CONST_SPACE
;
242 msg
+= meta_info_accessor
.getTagData( META_INFO_SUBJECT
);
245 //display document description;
246 if ( meta_info_accessor
.getTagData( META_INFO_DESCRIPTION
).length() > 0)
248 if ( msg
!= EMPTY_STRING
)
250 msg
+= GetResString( IDS_COMMENTS_COLON
) + CONST_SPACE
;
251 msg
+= meta_info_accessor
.getTagData( META_INFO_DESCRIPTION
);
254 //display modified time formatted into locale representation.
255 if ( iso8601_date_to_local_date(meta_info_accessor
.getTagData(META_INFO_MODIFIED
)).length() > 0)
257 if ( msg
!= EMPTY_STRING
)
259 msg
+= GetResString( IDS_MODIFIED_COLON
) + CONST_SPACE
;
260 msg
+= iso8601_date_to_local_date(meta_info_accessor
.getTagData(META_INFO_MODIFIED
));
263 catch (const std::exception
&)
267 //display file size, no matter other information is loaded successfully or not.
268 std::wstring tmpSizeStr
= getFileSizeInfo( m_szFileName
);
269 if ( tmpSizeStr
!= EMPTY_STRING
)
272 msg
+= GetResString( IDS_SIZE_COLON
) + CONST_SPACE
;
277 //finalize and assign the string.
279 HRESULT hr
= SHGetMalloc(&lpMalloc
);
283 size_t len
= sizeof(wchar_t) * msg
.length() + sizeof(wchar_t);
284 wchar_t* pMem
= static_cast<wchar_t*>(lpMalloc
->Alloc(len
));
286 ZeroMemory(pMem
, len
);
288 wcscpy_s(pMem
, msg
.length()+1, msg
.c_str());
300 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE
CInfoTip::GetInfoFlags(DWORD
* /*pdwFlags*/ )
309 HRESULT STDMETHODCALLTYPE
CInfoTip::GetClassID(CLSID
* pClassID
)
311 pClassID
= const_cast<CLSID
*>(&CLSID_INFOTIP_HANDLER
);
316 // IPersistFile methods
319 HRESULT STDMETHODCALLTYPE
CInfoTip::Load(LPCOLESTR pszFileName
, DWORD
/*dwMode*/)
321 std::wstring fname
= pszFileName
;
323 // there must be a '\' and there must even be an
324 // extension, else we would not have been called
325 std::wstring::iterator begin
= fname
.begin() + fname
.find_last_of(L
"\\") + 1;
326 std::wstring::iterator end
= fname
.end();
328 m_FileNameOnly
= std::wstring(begin
, end
);
330 fname
= getShortPathName( fname
);
332 // ZeroMemory because strncpy doesn't '\0'-terminates the destination
333 // string; reserve the last place in the buffer for the final '\0'
334 // that's why '(sizeof(m_szFileName) - 1)'
335 ZeroMemory(m_szFileName
, sizeof(m_szFileName
));
336 wcsncpy(m_szFileName
, fname
.c_str(), (sizeof(m_szFileName
)/sizeof(*m_szFileName
) - 1));
342 HRESULT STDMETHODCALLTYPE
CInfoTip::IsDirty()
348 HRESULT STDMETHODCALLTYPE
CInfoTip::Save(LPCOLESTR
/*pszFileName*/, BOOL
/*fRemember*/)
354 HRESULT STDMETHODCALLTYPE
CInfoTip::SaveCompleted(LPCOLESTR
/*pszFileName*/)
360 HRESULT STDMETHODCALLTYPE
CInfoTip::GetCurFile(LPOLESTR __RPC_FAR
* /*ppszFileName*/)
365 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */