]> git.sesse.net Git - vlc/blob - activex/utils.cpp
s/wxwindows/wxwidgets/
[vlc] / activex / utils.cpp
1 /*****************************************************************************
2  * utils.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  *
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 #include "utils.h"
24
25 #include <wchar.h>
26 #include <wctype.h>
27
28 /*
29 ** conversion facilities
30 */
31
32 using namespace std;
33
34 char *CStrFromWSTR(UINT codePage, LPCWSTR wstr, UINT len)
35 {
36     if( len > 0 )
37     {
38         size_t mblen = WideCharToMultiByte(codePage,
39                 0, wstr, len, NULL, 0, NULL, NULL);
40         if( mblen > 0 )
41         {
42             char *buffer = (char *)CoTaskMemAlloc(mblen+1);
43             ZeroMemory(buffer, mblen+1);
44             if( WideCharToMultiByte(codePage, 0, wstr, len, buffer, mblen, NULL, NULL) )
45             {
46                 buffer[mblen] = '\0';
47                 return buffer;
48             }
49         }
50     }
51     return NULL;
52 };
53
54 char *CStrFromBSTR(UINT codePage, BSTR bstr)
55 {
56     return CStrFromWSTR(codePage, bstr, SysStringLen(bstr));
57 };
58
59 BSTR BSTRFromCStr(UINT codePage, LPCSTR s)
60 {
61     int wideLen = MultiByteToWideChar(codePage, 0, s, -1, NULL, 0);
62     if( wideLen > 0 )
63     {
64         WCHAR* wideStr = (WCHAR*)CoTaskMemAlloc(wideLen*sizeof(WCHAR));
65         if( NULL != wideStr )
66         {
67             BSTR bstr;
68
69             ZeroMemory(wideStr, wideLen*sizeof(WCHAR));
70             MultiByteToWideChar(codePage, 0, s, -1, wideStr, wideLen);
71             bstr = SysAllocStringLen(wideStr, wideLen-1);
72             CoTaskMemFree(wideStr);
73
74             return bstr;
75         }
76     }
77     return NULL;
78 };
79
80 char *CStrFromGUID(REFGUID clsid)
81 {
82     LPOLESTR oleStr;
83
84     if( FAILED(StringFromIID(clsid, &oleStr)) )
85         return NULL;
86
87 #ifdef OLE2ANSI
88     return (LPCSTR)oleStr;
89 #else
90     char *pct_CLSID = NULL;
91     size_t len = WideCharToMultiByte(CP_ACP, 0, oleStr, -1, NULL, 0, NULL, NULL);
92     if( len > 0 )
93     {
94         pct_CLSID = (char *)CoTaskMemAlloc(len);
95         WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len, NULL, NULL);
96     }
97     CoTaskMemFree(oleStr);
98     return pct_CLSID;
99 #endif
100 };
101
102 /*
103 **  properties
104 */
105
106 HRESULT GetObjectProperty(LPUNKNOWN object, DISPID dispID, VARIANT& v)
107 {
108     IDispatch *pDisp;
109     HRESULT hr = object->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp);
110     if( SUCCEEDED(hr) )
111     {
112         DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
113         VARIANT vres;
114         VariantInit(&vres);
115         hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_USER_DEFAULT,
116                 DISPATCH_PROPERTYGET, &dispparamsNoArgs, &vres, NULL, NULL);
117         if( SUCCEEDED(hr) )
118         {
119             if( V_VT(&v) != V_VT(&vres) )
120             {
121                 hr = VariantChangeType(&v, &vres, 0, V_VT(&v));
122                 VariantClear(&vres);
123             }
124             else
125             {
126                 v = vres;
127             }
128         }
129         pDisp->Release();
130     }
131     return hr;
132 };
133
134 HDC CreateDevDC(DVTARGETDEVICE *ptd)
135 {
136     HDC hdc=NULL;
137     if( NULL == ptd )
138     {
139         hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
140     }
141     else
142     {
143         LPDEVNAMES lpDevNames;
144         LPDEVMODE lpDevMode;
145         LPTSTR lpszDriverName;
146         LPTSTR lpszDeviceName;
147         LPTSTR lpszPortName;
148
149         lpDevNames = (LPDEVNAMES) ptd; // offset for size field
150
151         if (ptd->tdExtDevmodeOffset == 0)
152         {
153             lpDevMode = NULL;
154         }
155         else
156         {
157             lpDevMode  = (LPDEVMODE) ((LPTSTR)ptd + ptd->tdExtDevmodeOffset);
158         }
159
160         lpszDriverName = (LPTSTR) lpDevNames + ptd->tdDriverNameOffset;
161         lpszDeviceName = (LPTSTR) lpDevNames + ptd->tdDeviceNameOffset;
162         lpszPortName   = (LPTSTR) lpDevNames + ptd->tdPortNameOffset;
163
164         hdc = CreateDC(lpszDriverName, lpszDeviceName, lpszPortName, lpDevMode);
165     }
166         return hdc;
167 };
168
169 #define HIMETRIC_PER_INCH 2540
170
171 void DPFromHimetric(HDC hdc, LPPOINT pt, int count)
172 {
173     LONG lpX = GetDeviceCaps(hdc, LOGPIXELSX);
174     LONG lpY = GetDeviceCaps(hdc, LOGPIXELSY);
175     while( count-- )
176     {
177         pt->x = pt->x*lpX/HIMETRIC_PER_INCH;
178         pt->y = pt->y*lpY/HIMETRIC_PER_INCH;
179         ++pt;
180     }
181 };
182
183 void HimetricFromDP(HDC hdc, LPPOINT pt, int count)
184 {
185     LONG lpX = GetDeviceCaps(hdc, LOGPIXELSX);
186     LONG lpY = GetDeviceCaps(hdc, LOGPIXELSY);
187     while( count-- )
188     {
189         pt->x = pt->x*HIMETRIC_PER_INCH/lpX;
190         pt->y = pt->y*HIMETRIC_PER_INCH/lpY;
191         ++pt;
192     }
193 };
194
195
196 LPWSTR CombineURL(LPCWSTR baseUrl, LPCWSTR url)
197 {
198     if( NULL != url )
199     {
200         // check whether URL is already absolute
201         const wchar_t *end=wcschr(url, L':');
202         if( (NULL != end) && (end != url) )
203         {
204             // validate protocol header
205             const wchar_t *start = url;
206             while( start != end ) {
207                 wchar_t c = towlower(*start);
208                 if( (c < L'a') || (c > L'z') )
209                     // not a valid protocol header, assume relative URL
210                     goto relativeurl;
211                 ++start;
212             }
213             /* we have a protocol header, therefore URL is absolute */
214             UINT len = wcslen(url);
215             wchar_t *href = (LPWSTR)CoTaskMemAlloc((len+1)*sizeof(wchar_t));
216             if( href )
217             {
218                 memcpy(href, url, len*sizeof(wchar_t));
219                 href[len] = L'\0';
220             }
221             return href;
222         }
223
224 relativeurl:
225
226         if( baseUrl )
227         {
228             size_t baseLen = wcslen(baseUrl);
229             wchar_t *href = (LPWSTR)CoTaskMemAlloc((baseLen+wcslen(url)+1)*sizeof(wchar_t));
230             if( href )
231             {
232                 /* prepend base URL */
233                 wcscpy(href, baseUrl);
234
235                 /*
236                 ** relative url could be empty,
237                 ** in which case return base URL
238                 */
239                 if( L'\0' == *url )
240                     return href;
241
242                 /*
243                 ** locate pathname part of base URL
244                 */
245
246                 /* skip over protocol part  */
247                 wchar_t *pathstart = wcschr(href, L':');
248                 wchar_t *pathend;
249                 if( pathstart )
250                 {
251                     if( L'/' == *(++pathstart) )
252                     {
253                         if( L'/' == *(++pathstart) )
254                         {
255                             ++pathstart;
256                         }
257                     }
258                     /* skip over host part */
259                     pathstart = wcschr(pathstart, L'/');
260                     pathend = href+baseLen;
261                     if( ! pathstart )
262                     {
263                         // no path, add a / past end of url (over '\0')
264                         pathstart = pathend;
265                         *pathstart = L'/';
266                     }
267                 }
268                 else
269                 {
270                     /* baseURL is just a UNIX file path */
271                     if( L'/' != *href )
272                     {
273                         /* baseURL is not an absolute path */
274                         return NULL;
275                     }
276                     pathstart = href;
277                     pathend = href+baseLen;
278                 }
279
280                 /* relative URL made of an absolute path ? */
281                 if( L'/' == *url )
282                 {
283                     /* replace path completely */
284                     wcscpy(pathstart, url);
285                     return href;
286                 }
287
288                 /* find last path component and replace it */ 
289                 while( L'/' != *pathend )
290                     --pathend;
291
292                 /*
293                 ** if relative url path starts with one or more './' or '../',
294                 ** factor them out of href so that we return a
295                 ** normalized URL
296                 */
297                 while( pathend > pathstart )
298                 {
299                     const wchar_t *p = url;
300                     if( L'.' != *p )
301                         break;
302                     ++p;
303                     if( L'\0' == *p  )
304                     {
305                         /* relative url is just '.' */
306                         url = p;
307                         break;
308                     }
309                     if( L'/' == *p  )
310                     {
311                         /* relative url starts with './' */
312                         url = ++p;
313                         continue;
314                     }
315                     if( L'.' != *p ) 
316                         break;
317                     ++p;
318                     if( L'\0' == *p )
319                     {
320                         /* relative url is '..' */
321                     }
322                     else
323                     {
324                         if( L'/' != *p ) 
325                             break;
326                         /* relative url starts with '../' */
327                         ++p;
328                     }
329                     url = p;
330                     do
331                     {
332                         --pathend;
333                     }
334                     while( L'/' != *pathend );
335                 }
336                 /* skip over '/' separator */
337                 ++pathend;
338                 /* concatenate remaining base URL and relative URL */
339                 wcscpy(pathend, url);
340             }
341             return href;
342         }
343     }
344     return NULL;
345 }
346