]> git.sesse.net Git - vlc/blob - activex/utils.cpp
Removes trailing spaces. Removes tabs.
[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             wchar_t c = *start;
185             if( iswalpha(c) )
186             {
187                 ++start;
188                 while( start != end )
189                 {
190                     c = *start;
191                     if( ! (iswalnum(c)
192                        || (L'-' == c)
193                        || (L'+' == c)
194                        || (L'.' == c)
195                        || (L'/' == c)) ) /* VLC uses / to allow user to specify a demuxer */
196                         // not valid protocol header, assume relative URL
197                         goto relativeurl;
198                     ++start;
199                 }
200                 /* we have a protocol header, therefore URL is absolute */
201                 UINT len = wcslen(url);
202                 wchar_t *href = (LPWSTR)CoTaskMemAlloc((len+1)*sizeof(wchar_t));
203                 if( href )
204                 {
205                     memcpy(href, url, len*sizeof(wchar_t));
206                     href[len] = L'\0';
207                 }
208                 return href;
209             }
210         }
211
212 relativeurl:
213
214         if( baseUrl )
215         {
216             size_t baseLen = wcslen(baseUrl);
217             wchar_t *href = (LPWSTR)CoTaskMemAlloc((baseLen+wcslen(url)+1)*sizeof(wchar_t));
218             if( href )
219             {
220                 /* prepend base URL */
221                 wcscpy(href, baseUrl);
222
223                 /*
224                 ** relative url could be empty,
225                 ** in which case return base URL
226                 */
227                 if( L'\0' == *url )
228                     return href;
229
230                 /*
231                 ** locate pathname part of base URL
232                 */
233
234                 /* skip over protocol part  */
235                 wchar_t *pathstart = wcschr(href, L':');
236                 wchar_t *pathend;
237                 if( pathstart )
238                 {
239                     if( L'/' == *(++pathstart) )
240                     {
241                         if( L'/' == *(++pathstart) )
242                         {
243                             ++pathstart;
244                         }
245                     }
246                     /* skip over host part */
247                     pathstart = wcschr(pathstart, L'/');
248                     pathend = href+baseLen;
249                     if( ! pathstart )
250                     {
251                         // no path, add a / past end of url (over '\0')
252                         pathstart = pathend;
253                         *pathstart = L'/';
254                     }
255                 }
256                 else
257                 {
258                     /* baseURL is just a UNIX file path */
259                     if( L'/' != *href )
260                     {
261                         /* baseURL is not an absolute path */
262                         return NULL;
263                     }
264                     pathstart = href;
265                     pathend = href+baseLen;
266                 }
267
268                 /* relative URL made of an absolute path ? */
269                 if( L'/' == *url )
270                 {
271                     /* replace path completely */
272                     wcscpy(pathstart, url);
273                     return href;
274                 }
275
276                 /* find last path component and replace it */
277                 while( L'/' != *pathend )
278                     --pathend;
279
280                 /*
281                 ** if relative url path starts with one or more './' or '../',
282                 ** factor them out of href so that we return a
283                 ** normalized URL
284                 */
285                 while( pathend > pathstart )
286                 {
287                     const wchar_t *p = url;
288                     if( L'.' != *p )
289                         break;
290                     ++p;
291                     if( L'\0' == *p  )
292                     {
293                         /* relative url is just '.' */
294                         url = p;
295                         break;
296                     }
297                     if( L'/' == *p  )
298                     {
299                         /* relative url starts with './' */
300                         url = ++p;
301                         continue;
302                     }
303                     if( L'.' != *p )
304                         break;
305                     ++p;
306                     if( L'\0' == *p )
307                     {
308                         /* relative url is '..' */
309                     }
310                     else
311                     {
312                         if( L'/' != *p )
313                             break;
314                         /* relative url starts with '../' */
315                         ++p;
316                     }
317                     url = p;
318                     do
319                     {
320                         --pathend;
321                     }
322                     while( L'/' != *pathend );
323                 }
324                 /* skip over '/' separator */
325                 ++pathend;
326                 /* concatenate remaining base URL and relative URL */
327                 wcscpy(pathend, url);
328             }
329             return href;
330         }
331     }
332     return NULL;
333 }
334