]> git.sesse.net Git - vlc/blob - projects/activex/utils.cpp
macosx/framework: Build a fat framework (x86_64 and i386) in Release mode.
[vlc] / projects / 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;
115     if( NULL == ptd )
116     {
117         hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
118     }
119     else
120     {
121         LPDEVNAMES lpDevNames = (LPDEVNAMES) ptd; // offset for size field
122         LPDEVMODE  lpDevMode  = NULL;
123
124         if (ptd->tdExtDevmodeOffset != 0)
125             lpDevMode  = (LPDEVMODE) ((LPTSTR)ptd + ptd->tdExtDevmodeOffset);
126
127         hdc = CreateDC( (LPTSTR) lpDevNames + ptd->tdDriverNameOffset,
128                         (LPTSTR) lpDevNames + ptd->tdDeviceNameOffset,
129                         (LPTSTR) lpDevNames + ptd->tdPortNameOffset,
130                         lpDevMode );
131     }
132     return hdc;
133 };
134
135 #define HIMETRIC_PER_INCH 2540
136
137 void DPFromHimetric(HDC hdc, LPPOINT pt, int count)
138 {
139     LONG lpX = GetDeviceCaps(hdc, LOGPIXELSX);
140     LONG lpY = GetDeviceCaps(hdc, LOGPIXELSY);
141     while( count-- )
142     {
143         pt->x = pt->x*lpX/HIMETRIC_PER_INCH;
144         pt->y = pt->y*lpY/HIMETRIC_PER_INCH;
145         ++pt;
146     }
147 };
148
149 void HimetricFromDP(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*HIMETRIC_PER_INCH/lpX;
156         pt->y = pt->y*HIMETRIC_PER_INCH/lpY;
157         ++pt;
158     }
159 };
160
161
162 LPWSTR CombineURL(LPCWSTR baseUrl, LPCWSTR url)
163 {
164     if( NULL != url )
165     {
166         // check whether URL is already absolute
167         const wchar_t *end=wcschr(url, L':');
168         if( (NULL != end) && (end != url) )
169         {
170             // validate protocol header
171             const wchar_t *start = url;
172             wchar_t c = *start;
173             if( iswalpha(c) )
174             {
175                 ++start;
176                 while( start != end )
177                 {
178                     c = *start;
179                     if( ! (iswalnum(c)
180                        || (L'-' == c)
181                        || (L'+' == c)
182                        || (L'.' == c)
183                        || (L'/' == c)) ) /* VLC uses / to allow user to specify a demuxer */
184                         // not valid protocol header, assume relative URL
185                         goto relativeurl;
186                     ++start;
187                 }
188                 /* we have a protocol header, therefore URL is absolute */
189                 UINT len = wcslen(url);
190                 wchar_t *href = (LPWSTR)CoTaskMemAlloc((len+1)*sizeof(wchar_t));
191                 if( href )
192                 {
193                     memcpy(href, url, len*sizeof(wchar_t));
194                     href[len] = L'\0';
195                 }
196                 return href;
197             }
198         }
199
200 relativeurl:
201
202         if( baseUrl )
203         {
204             size_t baseLen = wcslen(baseUrl);
205             wchar_t *href = (LPWSTR)CoTaskMemAlloc((baseLen+wcslen(url)+1)*sizeof(wchar_t));
206             if( href )
207             {
208                 /* prepend base URL */
209                 wcscpy(href, baseUrl);
210
211                 /*
212                 ** relative url could be empty,
213                 ** in which case return base URL
214                 */
215                 if( L'\0' == *url )
216                     return href;
217
218                 /*
219                 ** locate pathname part of base URL
220                 */
221
222                 /* skip over protocol part  */
223                 wchar_t *pathstart = wcschr(href, L':');
224                 wchar_t *pathend;
225                 if( pathstart )
226                 {
227                     if( L'/' == *(++pathstart) )
228                     {
229                         if( L'/' == *(++pathstart) )
230                         {
231                             ++pathstart;
232                         }
233                     }
234                     /* skip over host part */
235                     pathstart = wcschr(pathstart, L'/');
236                     pathend = href+baseLen;
237                     if( ! pathstart )
238                     {
239                         // no path, add a / past end of url (over '\0')
240                         pathstart = pathend;
241                         *pathstart = L'/';
242                     }
243                 }
244                 else
245                 {
246                     /* baseURL is just a UNIX file path */
247                     if( L'/' != *href )
248                     {
249                         /* baseURL is not an absolute path */
250                         return NULL;
251                     }
252                     pathstart = href;
253                     pathend = href+baseLen;
254                 }
255
256                 /* relative URL made of an absolute path ? */
257                 if( L'/' == *url )
258                 {
259                     /* replace path completely */
260                     wcscpy(pathstart, url);
261                     return href;
262                 }
263
264                 /* find last path component and replace it */
265                 while( L'/' != *pathend )
266                     --pathend;
267
268                 /*
269                 ** if relative url path starts with one or more './' or '../',
270                 ** factor them out of href so that we return a
271                 ** normalized URL
272                 */
273                 while( pathend > pathstart )
274                 {
275                     const wchar_t *p = url;
276                     if( L'.' != *p )
277                         break;
278                     ++p;
279                     if( L'\0' == *p  )
280                     {
281                         /* relative url is just '.' */
282                         url = p;
283                         break;
284                     }
285                     if( L'/' == *p  )
286                     {
287                         /* relative url starts with './' */
288                         url = ++p;
289                         continue;
290                     }
291                     if( L'.' != *p )
292                         break;
293                     ++p;
294                     if( L'\0' == *p )
295                     {
296                         /* relative url is '..' */
297                     }
298                     else
299                     {
300                         if( L'/' != *p )
301                             break;
302                         /* relative url starts with '../' */
303                         ++p;
304                     }
305                     url = p;
306                     do
307                     {
308                         --pathend;
309                     }
310                     while( L'/' != *pathend );
311                 }
312                 /* skip over '/' separator */
313                 ++pathend;
314                 /* concatenate remaining base URL and relative URL */
315                 wcscpy(pathend, url);
316             }
317             return href;
318         }
319     }
320     return NULL;
321 }
322