fix toolbar import
[ooovba.git] / tools / source / misc / pathutils.cxx
blob8df498bcaaa9666658ca39de013aca1defc49349
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pathutils.cxx,v $
10 * $Revision: 1.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "precompiled_tools.hxx"
32 #include "sal/config.h"
34 #if defined WNT
36 #include <cstddef>
38 #define WIN32_LEAN_AND_MEAN
39 #include <windows.h>
41 #include "sal/types.h"
42 #include "tools/pathutils.hxx"
44 namespace tools {
46 WCHAR * filename(WCHAR * path) {
47 WCHAR * f = path;
48 for (WCHAR * p = path;;) {
49 switch (*p++) {
50 case L'\0':
51 return f;
52 case L'\\':
53 f = p;
54 break;
59 WCHAR * buildPath(
60 WCHAR * path, WCHAR const * frontBegin, WCHAR const * frontEnd,
61 WCHAR const * backBegin, std::size_t backLength)
63 // Remove leading ".." segments in the second path together with matching
64 // segments in the first path that are neither empty nor "." nor ".." nor
65 // end in ":" (which is not foolprove, as it can erroneously erase the start
66 // of a UNC path, but only if the input is bad data):
67 while (backLength >= 2 && backBegin[0] == L'.' && backBegin[1] == L'.' &&
68 (backLength == 2 || backBegin[2] == L'\\'))
70 if (frontEnd - frontBegin < 2 || frontEnd[-1] != L'\\' ||
71 frontEnd[-2] == L'\\' || frontEnd[-2] == L':' ||
72 (frontEnd[-2] == L'.' &&
73 (frontEnd - frontBegin < 3 || frontEnd[-3] == L'\\' ||
74 (frontEnd[-3] == L'.' &&
75 (frontEnd - frontBegin < 4 || frontEnd[-4] == L'\\')))))
77 break;
79 WCHAR const * p = frontEnd - 1;
80 while (p != frontBegin && p[-1] != L'\\') {
81 --p;
83 if (p == frontBegin) {
84 break;
86 frontEnd = p;
87 if (backLength == 2) {
88 backBegin += 2;
89 backLength -= 2;
90 } else {
91 backBegin += 3;
92 backLength -= 3;
95 if (backLength <
96 static_cast< std::size_t >(MAX_PATH - (frontEnd - frontBegin)))
97 // hopefully std::size_t is large enough
99 WCHAR * p;
100 if (frontBegin == path) {
101 p = const_cast< WCHAR * >(frontEnd);
102 } else {
103 p = path;
104 while (frontBegin != frontEnd) {
105 *p++ = *frontBegin++;
108 for (; backLength > 0; --backLength) {
109 *p++ = *backBegin++;
111 *p = L'\0';
112 return p;
113 } else {
114 SetLastError(ERROR_FILENAME_EXCED_RANGE);
115 return NULL;
119 WCHAR * resolveLink(WCHAR * path) {
120 HANDLE h = CreateFileW(
121 path, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
122 if (h == INVALID_HANDLE_VALUE) {
123 return NULL;
125 char p1[MAX_PATH];
126 DWORD n;
127 BOOL ok = ReadFile(h, p1, MAX_PATH, &n, NULL);
128 CloseHandle(h);
129 if (!ok) {
130 return NULL;
132 WCHAR p2[MAX_PATH];
133 std::size_t n2 = 0;
134 bool colon = false;
135 for (DWORD i = 0; i < n;) {
136 unsigned char c = static_cast< unsigned char >(p1[i++]);
137 switch (c) {
138 case '\0':
139 SetLastError(ERROR_BAD_PATHNAME);
140 return NULL;
141 case '\x0A':
142 case '\x0D':
143 if (n2 == MAX_PATH) {
144 SetLastError(ERROR_FILENAME_EXCED_RANGE);
145 return NULL;
147 p2[n2] = L'\0';
148 break;
149 case ':':
150 colon = true;
151 // fall through
152 default:
153 // Convert from UTF-8 to UTF-16:
154 if (c <= 0x7F) {
155 p2[n2++] = c;
156 } else if (c >= 0xC2 && c <= 0xDF && i < n &&
157 static_cast< unsigned char >(p1[i]) >= 0x80 &&
158 static_cast< unsigned char >(p1[i]) <= 0xBF)
160 p2[n2++] = ((c & 0x1F) << 6) |
161 (static_cast< unsigned char >(p1[i++]) & 0x3F);
162 } else if (n - i > 1 &&
163 ((c == 0xE0 &&
164 static_cast< unsigned char >(p1[i]) >= 0xA0 &&
165 static_cast< unsigned char >(p1[i]) <= 0xBF) ||
166 ((c >= 0xE1 && c <= 0xEC || c >= 0xEE && c <= 0xEF) &&
167 static_cast< unsigned char >(p1[i]) >= 0x80 &&
168 static_cast< unsigned char >(p1[i]) <= 0xBF) ||
169 (c == 0xED &&
170 static_cast< unsigned char >(p1[i]) >= 0x80 &&
171 static_cast< unsigned char >(p1[i]) <= 0x9F)) &&
172 static_cast< unsigned char >(p1[i + 1]) >= 0x80 &&
173 static_cast< unsigned char >(p1[i + 1]) <= 0xBF)
175 p2[n2++] = ((c & 0x0F) << 12) |
176 ((static_cast< unsigned char >(p1[i]) & 0x3F) << 6) |
177 (static_cast< unsigned char >(p1[i + 1]) & 0x3F);
178 i += 2;
179 } else if (n - 2 > 1 &&
180 ((c == 0xF0 &&
181 static_cast< unsigned char >(p1[i]) >= 0x90 &&
182 static_cast< unsigned char >(p1[i]) <= 0xBF) ||
183 (c >= 0xF1 && c <= 0xF3 &&
184 static_cast< unsigned char >(p1[i]) >= 0x80 &&
185 static_cast< unsigned char >(p1[i]) <= 0xBF) ||
186 (c == 0xF4 &&
187 static_cast< unsigned char >(p1[i]) >= 0x80 &&
188 static_cast< unsigned char >(p1[i]) <= 0x8F)) &&
189 static_cast< unsigned char >(p1[i + 1]) >= 0x80 &&
190 static_cast< unsigned char >(p1[i + 1]) <= 0xBF &&
191 static_cast< unsigned char >(p1[i + 2]) >= 0x80 &&
192 static_cast< unsigned char >(p1[i + 2]) <= 0xBF)
194 sal_Int32 u = ((c & 0x07) << 18) |
195 ((static_cast< unsigned char >(p1[i]) & 0x3F) << 12) |
196 ((static_cast< unsigned char >(p1[i + 1]) & 0x3F) << 6) |
197 (static_cast< unsigned char >(p1[i + 2]) & 0x3F);
198 i += 3;
199 p2[n2++] = static_cast< WCHAR >(((u - 0x10000) >> 10) | 0xD800);
200 p2[n2++] = static_cast< WCHAR >(
201 ((u - 0x10000) & 0x3FF) | 0xDC00);
202 } else {
203 SetLastError(ERROR_BAD_PATHNAME);
204 return NULL;
206 break;
209 WCHAR * end;
210 if (colon || p2[0] == L'\\') {
211 // Interpret p2 as an absolute path:
212 end = path;
213 } else {
214 // Interpret p2 as a relative path:
215 end = filename(path);
217 return buildPath(path, path, end, p2, n2);
222 #endif