X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=activex%2Futils.cpp;h=8750aa1ce2e6749e3e3b9492829a4d2dd58b975f;hb=d555c8a942eb34afd21dba4e443770aa8c29441d;hp=eecba670064722ccb089bbe26b47052cf54b12d8;hpb=f533f3d8aa01c57102e16a829fe9146b35a32cef;p=vlc diff --git a/activex/utils.cpp b/activex/utils.cpp index eecba67006..8750aa1ce2 100644 --- a/activex/utils.cpp +++ b/activex/utils.cpp @@ -1,101 +1,324 @@ -/***************************************************************************** - * utils.cpp: ActiveX control for VLC - ***************************************************************************** - * Copyright (C) 2005 VideoLAN - * - * Authors: Damien Fouilleul - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - *****************************************************************************/ - -#include "utils.h" - -/* -** conversion facilities -*/ - -using namespace std; - -char *CStrFromBSTR(int codePage, BSTR bstr) -{ - UINT len = SysStringLen(bstr); - if( len > 0 ) - { - size_t mblen = WideCharToMultiByte(codePage, - 0, bstr, len, NULL, 0, NULL, NULL); - if( mblen > 0 ) - { - char *buffer = (char *)malloc(mblen+1); - ZeroMemory(buffer, mblen+1); - if( WideCharToMultiByte(codePage, 0, bstr, len, buffer, mblen, NULL, NULL) ) - return buffer; - } - } - return NULL; -}; - -BSTR BSTRFromCStr(int codePage, const char *s) -{ - int wideLen = MultiByteToWideChar(codePage, 0, s, -1, NULL, 0); - if( wideLen ) - { - WCHAR* wideStr = (WCHAR*)malloc(wideLen*sizeof(WCHAR)); - if( NULL != wideStr ) - { - BSTR bstr; - - ZeroMemory(wideStr, wideLen*sizeof(WCHAR)); - MultiByteToWideChar(codePage, 0, s, -1, wideStr, wideLen); - bstr = SysAllocString(wideStr); - free(wideStr); - - return bstr; - } - } - return NULL; -}; - -/* -** properties -*/ - -HRESULT GetObjectProperty(LPUNKNOWN object, DISPID dispID, VARIANT& v) -{ - IDispatch *pDisp; - HRESULT hr = object->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp); - if( SUCCEEDED(hr) ) - { - DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; - VARIANT vres; - hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_USER_DEFAULT, - DISPATCH_PROPERTYGET, &dispparamsNoArgs, &vres, NULL, NULL); - if( SUCCEEDED(hr) ) - { - if( V_VT(&v) != V_VT(&vres) ) - { - hr = VariantChangeType(&v, &vres, 0, V_VT(&v)); - VariantClear(&vres); - } - else - { - v = vres; - } - } - pDisp->Release(); - } - return hr; -}; - - +/***************************************************************************** + * utils.cpp: ActiveX control for VLC + ***************************************************************************** + * Copyright (C) 2005 the VideoLAN team + * + * Authors: Damien Fouilleul + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#include "utils.h" + +#include +#include + +/* +** conversion facilities +*/ + +using namespace std; + +char *CStrFromWSTR(UINT codePage, LPCWSTR wstr, UINT len) +{ + if( len > 0 ) + { + size_t mblen = WideCharToMultiByte(codePage, + 0, wstr, len, NULL, 0, NULL, NULL); + if( mblen > 0 ) + { + char *buffer = (char *)CoTaskMemAlloc(mblen+1); + ZeroMemory(buffer, mblen+1); + if( WideCharToMultiByte(codePage, 0, wstr, len, buffer, mblen, NULL, NULL) ) + { + buffer[mblen] = '\0'; + return buffer; + } + } + } + return NULL; +}; + +char *CStrFromBSTR(UINT codePage, BSTR bstr) +{ + return CStrFromWSTR(codePage, bstr, SysStringLen(bstr)); +}; + +BSTR BSTRFromCStr(UINT codePage, LPCSTR s) +{ + int wideLen = MultiByteToWideChar(codePage, 0, s, -1, NULL, 0); + if( wideLen > 0 ) + { + WCHAR* wideStr = (WCHAR*)CoTaskMemAlloc(wideLen*sizeof(WCHAR)); + if( NULL != wideStr ) + { + BSTR bstr; + + ZeroMemory(wideStr, wideLen*sizeof(WCHAR)); + MultiByteToWideChar(codePage, 0, s, -1, wideStr, wideLen); + bstr = SysAllocStringLen(wideStr, wideLen-1); + CoTaskMemFree(wideStr); + + return bstr; + } + } + return NULL; +}; + +/* +** properties +*/ + +HRESULT GetObjectProperty(LPUNKNOWN object, DISPID dispID, VARIANT& v) +{ + IDispatch *pDisp; + HRESULT hr = object->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp); + if( SUCCEEDED(hr) ) + { + DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; + VARIANT vres; + VariantInit(&vres); + hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_USER_DEFAULT, + DISPATCH_PROPERTYGET, &dispparamsNoArgs, &vres, NULL, NULL); + if( SUCCEEDED(hr) ) + { + if( V_VT(&v) != V_VT(&vres) ) + { + hr = VariantChangeType(&v, &vres, 0, V_VT(&v)); + VariantClear(&vres); + } + else + { + v = vres; + } + } + pDisp->Release(); + } + return hr; +}; + +HDC CreateDevDC(DVTARGETDEVICE *ptd) +{ + HDC hdc=NULL; + if( NULL == ptd ) + { + hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); + } + else + { + LPDEVNAMES lpDevNames; + LPDEVMODE lpDevMode; + LPTSTR lpszDriverName; + LPTSTR lpszDeviceName; + LPTSTR lpszPortName; + + lpDevNames = (LPDEVNAMES) ptd; // offset for size field + + if (ptd->tdExtDevmodeOffset == 0) + { + lpDevMode = NULL; + } + else + { + lpDevMode = (LPDEVMODE) ((LPTSTR)ptd + ptd->tdExtDevmodeOffset); + } + + lpszDriverName = (LPTSTR) lpDevNames + ptd->tdDriverNameOffset; + lpszDeviceName = (LPTSTR) lpDevNames + ptd->tdDeviceNameOffset; + lpszPortName = (LPTSTR) lpDevNames + ptd->tdPortNameOffset; + + hdc = CreateDC(lpszDriverName, lpszDeviceName, lpszPortName, lpDevMode); + } + return hdc; +}; + +#define HIMETRIC_PER_INCH 2540 + +void DPFromHimetric(HDC hdc, LPPOINT pt, int count) +{ + LONG lpX = GetDeviceCaps(hdc, LOGPIXELSX); + LONG lpY = GetDeviceCaps(hdc, LOGPIXELSY); + while( count-- ) + { + pt->x = pt->x*lpX/HIMETRIC_PER_INCH; + pt->y = pt->y*lpY/HIMETRIC_PER_INCH; + ++pt; + } +}; + +void HimetricFromDP(HDC hdc, LPPOINT pt, int count) +{ + LONG lpX = GetDeviceCaps(hdc, LOGPIXELSX); + LONG lpY = GetDeviceCaps(hdc, LOGPIXELSY); + while( count-- ) + { + pt->x = pt->x*HIMETRIC_PER_INCH/lpX; + pt->y = pt->y*HIMETRIC_PER_INCH/lpY; + ++pt; + } +}; + + +LPWSTR CombineURL(LPCWSTR baseUrl, LPCWSTR url) +{ + if( NULL != url ) + { + // check whether URL is already absolute + const wchar_t *end=wcschr(url, L':'); + if( (NULL != end) && (end != url) ) + { + // validate protocol header + const wchar_t *start = url; + while( start != end ) { + wchar_t c = towlower(*start); + if( (c < L'a') || (c > L'z') ) + // not a valid protocol header, assume relative URL + goto relativeurl; + ++start; + } + /* we have a protocol header, therefore URL is absolute */ + UINT len = wcslen(url); + wchar_t *href = (LPWSTR)CoTaskMemAlloc((len+1)*sizeof(wchar_t)); + if( href ) + { + memcpy(href, url, len*sizeof(wchar_t)); + href[len] = L'\0'; + } + return href; + } + +relativeurl: + + if( baseUrl ) + { + size_t baseLen = wcslen(baseUrl); + wchar_t *href = (LPWSTR)CoTaskMemAlloc((baseLen+wcslen(url)+1)*sizeof(wchar_t)); + if( href ) + { + /* prepend base URL */ + wcscpy(href, baseUrl); + + /* + ** relative url could be empty, + ** in which case return base URL + */ + if( L'\0' == *url ) + return href; + + /* + ** locate pathname part of base URL + */ + + /* skip over protocol part */ + wchar_t *pathstart = wcschr(href, L':'); + wchar_t *pathend; + if( pathstart ) + { + if( L'/' == *(++pathstart) ) + { + if( L'/' == *(++pathstart) ) + { + ++pathstart; + } + } + /* skip over host part */ + pathstart = wcschr(pathstart, L'/'); + pathend = href+baseLen; + if( ! pathstart ) + { + // no path, add a / past end of url (over '\0') + pathstart = pathend; + *pathstart = L'/'; + } + } + else + { + /* baseURL is just a UNIX file path */ + if( L'/' != *href ) + { + /* baseURL is not an absolute path */ + return NULL; + } + pathstart = href; + pathend = href+baseLen; + } + + /* relative URL made of an absolute path ? */ + if( L'/' == *url ) + { + /* replace path completely */ + wcscpy(pathstart, url); + return href; + } + + /* find last path component and replace it */ + while( L'/' != *pathend ) + --pathend; + + /* + ** if relative url path starts with one or more './' or '../', + ** factor them out of href so that we return a + ** normalized URL + */ + while( pathend > pathstart ) + { + const wchar_t *p = url; + if( L'.' != *p ) + break; + ++p; + if( L'\0' == *p ) + { + /* relative url is just '.' */ + url = p; + break; + } + if( L'/' == *p ) + { + /* relative url starts with './' */ + url = ++p; + continue; + } + if( L'.' != *p ) + break; + ++p; + if( L'\0' == *p ) + { + /* relative url is '..' */ + } + else + { + if( L'/' != *p ) + break; + /* relative url starts with '../' */ + ++p; + } + url = p; + do + { + --pathend; + } + while( L'/' != *pathend ); + } + /* skip over '/' separator */ + ++pathend; + /* concatenate remaining base URL and relative URL */ + wcscpy(pathend, url); + } + return href; + } + } + return NULL; +} +