Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

546 lines
9.5 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name: Shell String Class Implementation
  4. shstr.cpp
  5. Author:
  6. Zeke Lucas (zekel) 27-Oct-96
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. Abstract:
  11. this allows automatic resizing and stuff.
  12. NOTE: this class is specifically designed to be used as a stack variable
  13. --*/
  14. #include "stock.h"
  15. #pragma hdrstop
  16. #include <shstr.h>
  17. #define MALLOC(c) LocalAlloc(LPTR, (c))
  18. #define FREE(p) LocalFree(p)
  19. //
  20. // ShStr Public Methods
  21. //
  22. //
  23. // Constructors
  24. //
  25. ShStr :: ShStr ()
  26. {
  27. _szDefaultBuffer[0] = '\0';
  28. _pszStr = _szDefaultBuffer;
  29. _cchSize = ARRAYSIZE(_szDefaultBuffer);
  30. }
  31. /**************
  32. StrStr SetStr() methods
  33. Return:
  34. Success - a pointer to the object
  35. Failure - NULL
  36. **************/
  37. HRESULT
  38. ShStr :: SetStr (LPCSTR pszStr)
  39. {
  40. Reset();
  41. return _SetStr(pszStr);
  42. }
  43. HRESULT
  44. ShStr :: SetStr (LPCSTR pszStr, DWORD cchStr)
  45. {
  46. Reset();
  47. return _SetStr(pszStr, cchStr);
  48. }
  49. HRESULT
  50. ShStr :: SetStr (LPCWSTR pwszStr, DWORD cchStr)
  51. {
  52. Reset();
  53. return _SetStr(pwszStr, cchStr);
  54. }
  55. HRESULT
  56. ShStr :: Append(LPCTSTR pszStr, DWORD cchStr)
  57. {
  58. HRESULT hr = S_OK;
  59. if(pszStr)
  60. {
  61. DWORD cchLen = GetLen();
  62. if(cchStr == (DWORD) -1)
  63. cchStr = lstrlen(pszStr);
  64. //
  65. // StrCpyN automagically appends the null term,
  66. // so we need to give room for it
  67. //
  68. cchStr++;
  69. if(SUCCEEDED(SetSize(cchStr + cchLen)))
  70. StrCpyN(_pszStr + cchLen, pszStr, cchStr);
  71. else
  72. hr = E_OUTOFMEMORY;
  73. }
  74. else
  75. hr = E_INVALIDARG;
  76. return hr;
  77. }
  78. ShStr *
  79. ShStr :: Clone()
  80. {
  81. ShStr *pshstr = new ShStr;
  82. if (pshstr)
  83. {
  84. pshstr->SetStr(_pszStr);
  85. if(pshstr->IsValid())
  86. return pshstr;
  87. }
  88. if(pshstr)
  89. delete pshstr;
  90. return NULL;
  91. }
  92. LPSTR
  93. ShStr :: CloneStrA()
  94. #ifdef UNICODE
  95. {
  96. LPSTR pszStr = NULL;
  97. if(_pszStr)
  98. {
  99. DWORD cchStr;
  100. cchStr = WideCharToMultiByte(CP_ACP, 0,
  101. _pszStr, -1,
  102. NULL, 0,
  103. NULL, NULL);
  104. ASSERT(cchStr);
  105. if(cchStr)
  106. {
  107. pszStr = (LPSTR) MALLOC (CbFromCch(cchStr +1));
  108. if(pszStr)
  109. {
  110. cchStr = WideCharToMultiByte(CP_ACP, 0,
  111. _pszStr, -1,
  112. pszStr, cchStr,
  113. NULL, NULL);
  114. ASSERT (cchStr);
  115. }
  116. }
  117. }
  118. return pszStr;
  119. }
  120. #else //!UNICODE
  121. {return _pszStr ? StrDupA(_pszStr) : NULL;}
  122. #endif //UNICODE
  123. #ifdef UNICODE
  124. #endif
  125. LPWSTR
  126. ShStr :: CloneStrW()
  127. #ifdef UNICODE
  128. {return _pszStr ? StrDupW(_pszStr) : NULL;}
  129. #else //!UNICODE
  130. {
  131. LPWSTR pwsz;
  132. DWORD cch = lstrlenA(_pszStr) +1;
  133. pwsz = (LPWSTR) MALLOC (sizeof(WCHAR) * cch);
  134. if(pwsz)
  135. MultiByteToWideChar(CP_ACP, 0,
  136. _pszStr, -1,
  137. pwsz, cch);
  138. return pwsz;
  139. }
  140. #endif //UNICODE
  141. /**************
  142. ShStr Utility methods
  143. **************/
  144. /**************
  145. ShStr SetSize method
  146. Sets the size of the internal buffer if larger than default
  147. Return:
  148. Success - a pointer to the object
  149. Failure - NULL
  150. **************/
  151. HRESULT
  152. ShStr :: SetSize(DWORD cchSize)
  153. {
  154. HRESULT hr = S_OK;
  155. DWORD cchNewSize = _cchSize;
  156. ASSERT(!(_cchSize % DEFAULT_SHSTR_LENGTH));
  157. // so that we always allocate in increments
  158. while (cchSize > cchNewSize)
  159. cchNewSize <<= 2;
  160. if(cchNewSize != _cchSize)
  161. {
  162. if(cchNewSize > DEFAULT_SHSTR_LENGTH)
  163. {
  164. LPTSTR psz;
  165. psz = (LPTSTR) LocalAlloc(LPTR, CbFromCch(cchNewSize));
  166. if(psz)
  167. {
  168. StrCpyN(psz, _pszStr, cchSize);
  169. Reset();
  170. _cchSize = cchNewSize;
  171. _pszStr = psz;
  172. }
  173. else
  174. hr = E_OUTOFMEMORY;
  175. }
  176. else
  177. {
  178. if (_pszStr && _cchSize)
  179. StrCpyN(_szDefaultBuffer, _pszStr, ARRAYSIZE(_szDefaultBuffer));
  180. Reset();
  181. _pszStr = _szDefaultBuffer;
  182. }
  183. }
  184. return hr;
  185. }
  186. #ifdef DEBUG
  187. BOOL
  188. ShStr :: IsValid()
  189. {
  190. BOOL fRet = TRUE;
  191. if(!_pszStr)
  192. fRet = FALSE;
  193. ASSERT( ((_cchSize != ARRAYSIZE(_szDefaultBuffer)) && (_pszStr != _szDefaultBuffer)) ||
  194. ((_cchSize == ARRAYSIZE(_szDefaultBuffer)) && (_pszStr == _szDefaultBuffer)) );
  195. ASSERT(!(_cchSize % DEFAULT_SHSTR_LENGTH));
  196. return fRet;
  197. }
  198. #endif //DEBUG
  199. VOID
  200. ShStr :: Reset()
  201. {
  202. if (_pszStr && (_cchSize != ARRAYSIZE(_szDefaultBuffer)))
  203. LocalFree(_pszStr);
  204. _szDefaultBuffer[0] = TEXT('\0');
  205. _pszStr = _szDefaultBuffer;
  206. _cchSize = ARRAYSIZE(_szDefaultBuffer);
  207. }
  208. #define IsWhite(c) ((DWORD) (c) > 32 ? FALSE : TRUE)
  209. VOID
  210. ShStr :: Trim()
  211. {
  212. if(_pszStr)
  213. {
  214. // APPCOMPAT - NETSCAPE compatibility - zekel 29-JAN-97
  215. // we want to leave one space in the string
  216. TCHAR chFirst = *_pszStr;
  217. // first trim the backside
  218. TCHAR *pchLastWhite = NULL;
  219. LPTSTR pch = _pszStr;
  220. // the front side
  221. while (*pch && IsWhite(*pch))
  222. pch = CharNext(pch);
  223. if (pch > _pszStr)
  224. {
  225. LPTSTR pchDst = _pszStr;
  226. while (*pchDst = *pch)
  227. {
  228. pch = CharNext(pch);
  229. pchDst = CharNext(pchDst);
  230. }
  231. }
  232. // then the backside
  233. for (pch = _pszStr; *pch; pch = CharNext(pch))
  234. {
  235. if(pchLastWhite && !IsWhite(*pch))
  236. pchLastWhite = NULL;
  237. else if(!pchLastWhite && IsWhite(*pch))
  238. pchLastWhite = pch;
  239. }
  240. if(pchLastWhite)
  241. *pchLastWhite = TEXT('\0');
  242. if(TEXT(' ') == chFirst && !*_pszStr)
  243. {
  244. _pszStr[0] = TEXT(' ');
  245. _pszStr[1] = TEXT('\0');
  246. }
  247. }
  248. }
  249. //
  250. // ShStr Private Methods
  251. //
  252. /**************
  253. StrStr Set* methods
  254. Return:
  255. Success - a pointer to the object
  256. Failure - NULL
  257. **************/
  258. HRESULT
  259. ShStr :: _SetStr(LPCSTR pszStr)
  260. {
  261. HRESULT hr = S_FALSE;
  262. if(pszStr)
  263. {
  264. DWORD cchStr;
  265. cchStr = lstrlenA(pszStr);
  266. if(cchStr)
  267. {
  268. hr = SetSize(cchStr +1);
  269. if (SUCCEEDED(hr))
  270. #ifdef UNICODE
  271. MultiByteToWideChar(CP_ACP, 0,
  272. pszStr, -1,
  273. _pszStr, _cchSize);
  274. #else //!UNICODE
  275. lstrcpyA(_pszStr, pszStr);
  276. #endif //UNICODE
  277. }
  278. }
  279. return hr;
  280. }
  281. HRESULT
  282. ShStr :: _SetStr(LPCSTR pszStr, DWORD cchStr)
  283. {
  284. HRESULT hr = S_FALSE;
  285. if(pszStr && cchStr)
  286. {
  287. if (cchStr == (DWORD) -1)
  288. cchStr = lstrlenA(pszStr);
  289. hr = SetSize(cchStr +1);
  290. if(SUCCEEDED(hr))
  291. {
  292. #ifdef UNICODE
  293. MultiByteToWideChar(CP_ACP, 0,
  294. pszStr, cchStr,
  295. _pszStr, _cchSize);
  296. _pszStr[cchStr] = TEXT('\0');
  297. #else //!UNICODE
  298. StrCpyN(_pszStr, pszStr, (++cchStr < _cchSize ? cchStr : _cchSize) );
  299. #endif //UNICODE
  300. }
  301. }
  302. return hr;
  303. }
  304. HRESULT
  305. ShStr :: _SetStr (LPCWSTR pwszStr, DWORD cchStrIn)
  306. {
  307. DWORD cchStr = cchStrIn;
  308. HRESULT hr = S_FALSE;
  309. if(pwszStr && cchStr)
  310. {
  311. if (cchStr == (DWORD) -1)
  312. #ifdef UNICODE
  313. cchStr = lstrlen(pwszStr);
  314. #else //!UNICODE
  315. cchStr = WideCharToMultiByte(CP_ACP, 0,
  316. pwszStr, cchStrIn,
  317. NULL, 0,
  318. NULL, NULL);
  319. #endif //UNICODE
  320. if(cchStr)
  321. {
  322. hr = SetSize(cchStr +1);
  323. if(SUCCEEDED(hr))
  324. {
  325. #ifdef UNICODE
  326. StrCpyN(_pszStr, pwszStr, (cchStr + 1< _cchSize ? cchStr + 1: _cchSize));
  327. #else //!UNICODE
  328. cchStr = WideCharToMultiByte(CP_ACP, 0,
  329. pwszStr, cchStrIn,
  330. _pszStr, _cchSize,
  331. NULL, NULL);
  332. _pszStr[cchStr < _cchSize ? cchStr : _cchSize] = TEXT('\0');
  333. ASSERT (cchStr);
  334. #endif //UNICODE
  335. }
  336. }
  337. #ifdef DEBUG
  338. else
  339. {
  340. DWORD dw;
  341. dw = GetLastError();
  342. }
  343. #endif //DEBUG
  344. }
  345. #ifdef DEBUG
  346. else
  347. {
  348. DWORD dw;
  349. dw = GetLastError();
  350. }
  351. #endif //DEBUG
  352. return hr;
  353. }
  354. #if 0 //DISABLED until i have written the SHUrl* functions - zekel 7-Nov-96
  355. //
  356. // UrlStr Methods
  357. //
  358. UrlStr &
  359. UrlStr::SetUrl(LPCSTR pszUrl)
  360. {
  361. return SetUrl(pszUrl, (DWORD) -1);
  362. }
  363. UrlStr &
  364. UrlStr::SetUrl(LPCWSTR pwszUrl)
  365. {
  366. return SetUrl(pwszUrl, (DWORD) -1);
  367. }
  368. UrlStr &
  369. UrlStr::SetUrl(LPCSTR pszUrl, DWORD cchUrl)
  370. {
  371. _strUrl.SetStr(pszUrl, cchUrl);
  372. return *this;
  373. }
  374. UrlStr &
  375. UrlStr::SetUrl(LPCWSTR pwszUrl, DWORD cchUrl)
  376. {
  377. _strUrl.SetStr(pwszUrl, cchUrl);
  378. return *this;
  379. }
  380. UrlStr::operator LPCTSTR()
  381. {
  382. return _strUrl.GetStr();
  383. }
  384. UrlStr::operator SHSTR()
  385. {
  386. return _strUrl;
  387. }
  388. HRESULT
  389. UrlStr::Combine(LPCTSTR pszUrl, DWORD dwFlags)
  390. {
  391. SHSTR strRel;
  392. SHSTR strOut;
  393. HRESULT hr;
  394. strRel.SetStr(pszUrl);
  395. hr = UrlCombine(_strUrl.GetStr(),
  396. hr = SHUrlParse(&_strUrl, &strRel, &strOut, NULL, URL_PARSE_CREATE);
  397. if(SUCCEEDED(hr))
  398. _strUrl = strOut;
  399. return hr;
  400. }
  401. /*
  402. ShStr &GetLocation();
  403. ShStr &GetAnchor();
  404. ShStr &GetQuery();
  405. HRESULT Canonicalize(DWORD dwFlags);
  406. HRESULT Combine(LPCTSTR pszUrl, DWORD dwFlags);
  407. HRESULT Encode(DWORD dwFlags);
  408. HRESULT EncodeSpaces()
  409. {return Encode(URL_ENCODE_SPACES_ONLY)}
  410. HRESULT Decode(DWORD dwFlags)
  411. */
  412. #endif //DISABLED