]> git.sesse.net Git - vlc/blob - activex/utils.cpp
Long overdue update
[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 /*
81 **  properties
82 */
83
84 HRESULT GetObjectProperty(LPUNKNOWN object, DISPID dispID, VARIANT& v)
85 {
86     IDispatch *pDisp;
87     HRESULT hr = object->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp);
88     if( SUCCEEDED(hr) )
89     {
90         DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
91         VARIANT vres;
92         VariantInit(&vres);
93         hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_USER_DEFAULT,
94                 DISPATCH_PROPERTYGET, &dispparamsNoArgs, &vres, NULL, NULL);
95         if( SUCCEEDED(hr) )
96         {
97             if( V_VT(&v) != V_VT(&vres) )
98             {
99                 hr = VariantChangeType(&v, &vres, 0, V_VT(&v));
100                 VariantClear(&vres);
101             }
102             else
103             {
104                 v = vres;
105             }
106         }
107         pDisp->Release();
108     }
109     return hr;
110 };
111
112 HDC CreateDevDC(DVTARGETDEVICE *ptd)
113 {
114     HDC hdc=NULL;
115     if( NULL == ptd )
116     {
117         hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
118     }
119     else
120     {
121         LPDEVNAMES lpDevNames;
122         LPDEVMODE lpDevMode;
123         LPTSTR lpszDriverName;
124         LPTSTR lpszDeviceName;
125         LPTSTR lpszPortName;
126
127         lpDevNames = (LPDEVNAMES) ptd; // offset for size field
128
129         if (ptd->tdExtDevmodeOffset == 0)
130         {
131             lpDevMode = NULL;
132         }
133         else
134         {
135             lpDevMode  = (LPDEVMODE) ((LPTSTR)ptd + ptd->tdExtDevmodeOffset);
136         }
137
138         lpszDriverName = (LPTSTR) lpDevNames + ptd->tdDriverNameOffset;
139         lpszDeviceName = (LPTSTR) lpDevNames + ptd->tdDeviceNameOffset;
140         lpszPortName   = (LPTSTR) lpDevNames + ptd->tdPortNameOffset;
141
142         hdc = CreateDC(lpszDriverName, lpszDeviceName, lpszPortName, lpDevMode);
143     }
144         return hdc;
145 };
146
147 #define HIMETRIC_PER_INCH 2540
148
149 void DPFromHimetric(HDC hdc, LPPOINT pt, int count)
150 {
151     LONG lpX = GetDeviceCaps(hdc, LOGPIXELSX);
152     LONG lpY = GetDeviceCaps(hdc, LOGPIXELSY);
153     while( count-- )
154     {
155         pt->x = pt->x*lpX/HIMETRIC_PER_INCH;
156         pt->y = pt->y*lpY/HIMETRIC_PER_INCH;
157         ++pt;
158     }
159 };
160
161 void HimetricFromDP(HDC hdc, LPPOINT pt, int count)
162 {
163     LONG lpX = GetDeviceCaps(hdc, LOGPIXELSX);
164     LONG lpY = GetDeviceCaps(hdc, LOGPIXELSY);
165     while( count-- )
166     {
167         pt->x = pt->x*HIMETRIC_PER_INCH/lpX;
168         pt->y = pt->y*HIMETRIC_PER_INCH/lpY;
169         ++pt;
170     }
171 };
172
173
174 LPWSTR CombineURL(LPCWSTR baseUrl, LPCWSTR url)
175 {
176     if( NULL != url )
177     {
178         // check whether URL is already absolute
179         const wchar_t *end=wcschr(url, L':');
180         if( (NULL != end) && (end != url) )
181         {
182             // validate protocol header
183             const wchar_t *start = url;
184             while( start != end ) {
185                 wchar_t c = towlower(*start);
186                 if( (c < L'a') || (c > L'z') )
187                     // not a valid protocol header, assume relative URL
188                     goto relativeurl;
189                 ++start;
190             }
191             /* we have a protocol header, therefore URL is absolute */
192             UINT len = wcslen(url);
193             wchar_t *href = (LPWSTR)CoTaskMemAlloc((len+1)*sizeof(wchar_t));
194             if( href )
195             {
196                 memcpy(href, url, len*sizeof(wchar_t));
197                 href[len] = L'\0';
198             }
199             return href;
200         }
201
202 relativeurl:
203
204         if( baseUrl )
205         {
206             size_t baseLen = wcslen(baseUrl);
207             wchar_t *href = (LPWSTR)CoTaskMemAlloc((baseLen+wcslen(url)+1)*sizeof(wchar_t));
208             if( href )
209             {
210                 /* prepend base URL */
211                 wcscpy(href, baseUrl);
212
213                 /*
214                 ** relative url could be empty,
215                 ** in which case return base URL
216                 */
217                 if( L'\0' == *url )
218                     return href;
219
220                 /*
221                 ** locate pathname part of base URL
222                 */
223
224                 /* skip over protocol part  */
225                 wchar_t *pathstart = wcschr(href, L':');
226                 wchar_t *pathend;
227                 if( pathstart )
228                 {
229                     if( L'/' == *(++pathstart) )
230                     {
231                         if( L'/' == *(++pathstart) )
232                         {
233                             ++pathstart;
234                         }
235                     }
236                     /* skip over host part */
237                     pathstart = wcschr(pathstart, L'/');
238                     pathend = href+baseLen;
239                     if( ! pathstart )
240                     {
241                         // no path, add a / past end of url (over '\0')
242                         pathstart = pathend;
243                         *pathstart = L'/';
244                     }
245                 }
246                 else
247                 {
248                     /* baseURL is just a UNIX file path */
249                     if( L'/' != *href )
250                     {
251                         /* baseURL is not an absolute path */
252                         return NULL;
253                     }
254                     pathstart = href;
255                     pathend = href+baseLen;
256                 }
257
258                 /* relative URL made of an absolute path ? */
259                 if( L'/' == *url )
260                 {
261                     /* replace path completely */
262                     wcscpy(pathstart, url);
263                     return href;
264                 }
265
266                 /* find last path component and replace it */ 
267                 while( L'/' != *pathend )
268                     --pathend;
269
270                 /*
271                 ** if relative url path starts with one or more './' or '../',
272                 ** factor them out of href so that we return a
273                 ** normalized URL
274                 */
275                 while( pathend > pathstart )
276                 {
277                     const wchar_t *p = url;
278                     if( L'.' != *p )
279                         break;
280                     ++p;
281                     if( L'\0' == *p  )
282                     {
283                         /* relative url is just '.' */
284                         url = p;
285                         break;
286                     }
287                     if( L'/' == *p  )
288                     {
289                         /* relative url starts with './' */
290                         url = ++p;
291                         continue;
292                     }
293                     if( L'.' != *p ) 
294                         break;
295                     ++p;
296                     if( L'\0' == *p )
297                     {
298                         /* relative url is '..' */
299                     }
300                     else
301                     {
302                         if( L'/' != *p ) 
303                             break;
304                         /* relative url starts with '../' */
305                         ++p;
306                     }
307                     url = p;
308                     do
309                     {
310                         --pathend;
311                     }
312                     while( L'/' != *pathend );
313                 }
314                 /* skip over '/' separator */
315                 ++pathend;
316                 /* concatenate remaining base URL and relative URL */
317                 wcscpy(pathend, url);
318             }
319             return href;
320         }
321     }
322     return NULL;
323 }
324