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.

508 lines
13 KiB

  1. /*****************************************************************************
  2. *
  3. * STR.C
  4. *
  5. * Copyright (C) Microsoft Corporation 1990 - 1994.
  6. * All Rights reserved.
  7. *
  8. ******************************************************************************
  9. *
  10. * Module Intent
  11. * String abstraction layer for WIN/PM
  12. *
  13. ******************************************************************************
  14. *
  15. * Testing Notes
  16. *
  17. ******************************************************************************
  18. *
  19. * Current Owner: UNDONE
  20. *
  21. ******************************************************************************
  22. *
  23. * Released by Development: (date)
  24. *
  25. ******************************************************************************
  26. *
  27. * Revision History:
  28. * -- Mar 92. Adapted from WinHelps STR.C. DAVIDJES
  29. *
  30. *****************************************************************************/
  31. static char s_aszModule[] = __FILE__; /* For error report */
  32. #include <mvopsys.h>
  33. #include <orkin.h>
  34. #include <string.h>
  35. #include <misc.h>
  36. #include <iterror.h>
  37. #include <wrapstor.h>
  38. #include <_mvutil.h>
  39. /* Put all functions into the same segment to avoid memory fragmentation
  40. * and load time surplus for the MAC
  41. */
  42. // #pragma code_seg ("MVFS")
  43. /***************************************************************************
  44. *
  45. - Name: SzNzCat(szDest, szSrc, cch)
  46. -
  47. * Purpose:
  48. * concatenation of szSrc to szDest up to cch characters. make sure
  49. * the destination is still \000 terminated. will copy up to cch-1
  50. * characters. this means that cch should account for the \000 when
  51. * passed in.
  52. *
  53. * Arguments:
  54. * szDest - the SZ to append onto
  55. * szSrc - the SZ which will be appended to szDest
  56. * cch - the max count of characters to copy and space for the \000
  57. *
  58. * Returns:
  59. * szDest
  60. *
  61. * Globals Used:
  62. *
  63. * +++
  64. *
  65. * Notes:
  66. *
  67. ***************************************************************************/
  68. SZ FAR PASCAL SzNzCat(SZ szDest, SZ szSrc, WORD cch)
  69. {
  70. SZ sz = szDest+lstrlen(szDest);
  71. STRNCPY(sz, szSrc, cch);
  72. *(sz + cch) = '\000';
  73. return szDest;
  74. }
  75. /***************************************************************************
  76. *
  77. - Function: WCmpSt(st1, st2)
  78. -
  79. * Purpose: Compare two STs for equality.
  80. *
  81. * ASSUMES
  82. *
  83. * args IN: st1, st2 - the STs to compare
  84. *
  85. * PROMISES
  86. *
  87. * returns: -1 for st1 < st2; 0 for st1 == st2; 1 for st1 > st2
  88. *
  89. ***************************************************************************/
  90. SHORT FAR PASCAL WCmpSt(st1, st2)
  91. ST st1, st2;
  92. {
  93. unsigned char cb;
  94. char dcb = *st1 - *st2, dch = 0;
  95. for (cb = min( *st1, *st2), st1++, st2++; cb > 0; cb++, st1++, st2++ )
  96. {
  97. if (dch = *st1 - *st2) break;
  98. }
  99. if (dch)
  100. return dch < 0 ? -1 : 1;
  101. return dcb < 0 ? -1 : (dcb > 0 ? 1 : 0);
  102. }
  103. /*******************************************************************
  104. *
  105. * The following stuff is for international string comparisons.
  106. * These functions are insensitive to case and accents. For a
  107. * function that distinguishes between all char values, we use
  108. * _fstrcmp(), which behaves just like strcmp().
  109. *
  110. * The tables in maps.h were generated from the ones used in help 2.5
  111. * which were stolen from Opus international stuff.
  112. *
  113. * There are two loops for speed. These should be redone in assembly.
  114. *
  115. *******************************************************************/
  116. #include "maps.h" /* the two mapping tables */
  117. /*------------------------------------ WCmpiSz -----------------------------*/
  118. SHORT FAR PASCAL WCmpiSz(SZ lpstrOne, SZ lpstrTwo, BYTE far *qbLigatures)
  119. /**************************************************
  120. OWNER: Matthew W. Smith (MATTSMI)
  121. DATE DOCUMENTED: March 5, 1992
  122. @doc INTERNAL
  123. @api int FAR PASCAL | WCmpiSz | compares two LPSTRs
  124. without case sensitivity.
  125. @parm LPSTR | lpstrOne | first string for comparison.
  126. @parm LPSTR | lpstrTwo | other string for comparison.
  127. @parm BYTE far * | qbLigatures | ligature table loaded from the
  128. file system or from hardwiring (by default).
  129. @comm
  130. This routine is analogous to strcmpi() except it
  131. uses long pointers. It is unlike lstrcmpi() in
  132. that it is truly case insensitive.
  133. This routine is unlike CompareLPSTRi in that it works
  134. off of Microsoft's standard internal international
  135. character set table.
  136. The return value is:
  137. 0 if lpstrOne = lpstrTwo
  138. 1 if lpstrOne > lpstrTwo
  139. -1 if lpstrOne < lpstrTwo
  140. NOTE: this version differs from CompareTableLPSTRi() in that
  141. ligature expansion (which is viewer-compiler specific is undertaken).
  142. This is done by drawing on a ligature table (LPSTR) kept globally
  143. during compilation -- see LoadLigatureTable().
  144. This routine draws on the standard Help character sort order
  145. table in utilib.c -- it is an extern global here.
  146. NOTE: this routine assumes that the ligature table available
  147. to it (rgchLigatureSortTableGlobal) uses the OEM and not ANSI character
  148. set.
  149. ***************************************************/
  150. /*-----------------------------------------------------------------------*/
  151. { /*** WCmpiSz ***/
  152. int i=0, j=0;
  153. unsigned char ch1, ch2, ch;
  154. BYTE cLigs, c;
  155. unsigned char ch1Next='\0';
  156. unsigned char ch2Next='\0';
  157. BOOL fDontExpandCh1=FALSE;
  158. BOOL fDontExpandCh2=FALSE;
  159. if (!qbLigatures)
  160. cLigs=0;
  161. else
  162. cLigs=qbLigatures[0];
  163. ch1=lpstrOne[0];
  164. ch2=lpstrTwo[0];
  165. while (ch1 && ch2)
  166. {
  167. /***************************
  168. CHECK FOR LIGATURE EXPANSION
  169. ****************************/
  170. for (c=1; c<=cLigs; c++)
  171. {
  172. ch=qbLigatures[(c-1)*3+1];
  173. if (!fDontExpandCh1 && (ch1 == ch))
  174. {
  175. ch1=qbLigatures[(c-1)*3+2];
  176. ch1Next=qbLigatures[(c-1)*3+3];
  177. }
  178. if (!fDontExpandCh2 && (ch2 == ch))
  179. {
  180. ch2=qbLigatures[(c-1)*3+2];
  181. ch2Next=qbLigatures[(c-1)*3+3];
  182. }
  183. }
  184. ch1=mpchordNorm[ch1];
  185. ch2=mpchordNorm[ch2];
  186. fDontExpandCh1=FALSE;
  187. fDontExpandCh2=FALSE;
  188. /*************************************************
  189. EITHER BREAK BECAUSE THE CHARACTERS WERE DIFFERENT
  190. OR GET THE NEXT CHARACTER FOR COMPARISION
  191. **************************************************/
  192. if (ch1 != ch2)
  193. break;
  194. else
  195. {
  196. if (ch1Next)
  197. {
  198. ch1=ch1Next;
  199. ch1Next='\0';
  200. fDontExpandCh1=TRUE; // SETTING THIS FLAG PREVENTS ENDLESS RECURSION
  201. }
  202. else ch1=lpstrOne[++i];
  203. if (ch2Next)
  204. {
  205. ch2=ch2Next;
  206. ch2Next='\0';
  207. fDontExpandCh2=TRUE; // SETTING THIS FLAG PREVENTS ENDLESS RECURSION
  208. }
  209. else ch2=lpstrTwo[++j];
  210. }
  211. }
  212. /**********************************
  213. IF STRINGS BOTH TERMINATED AT THE
  214. SAME TIME WITHOUT DIFF BEING FOUND
  215. THEY ARE THE SAME
  216. ***********************************/
  217. if (!ch1 && !ch2)
  218. return(0);
  219. /**************************************
  220. IF ONE TERMINATED AND NO DIFF WAS
  221. FOUND WHEN IT DID, THEN THE TERMINATING
  222. STRING COMES FIRST . . .
  223. ***************************************/
  224. if (!ch1)
  225. return(-1);
  226. else if (!ch2)
  227. return(1);
  228. /*********************************
  229. DIFF WAS FOUND; RETURN ACCORDINGLY
  230. **********************************/
  231. if (ch1 < ch2)
  232. return(-1);
  233. else
  234. return(1);
  235. } /*** WCmpiSz ***/
  236. /*-----------------------------------------------------------------------*/
  237. SHORT FAR PASCAL WCmpiSnn(SZ lpstrOne, SZ lpstrTwo, BYTE far *qbLigatures, SHORT iLen1, SHORT iLen2)
  238. /**************************************************
  239. OWNER: Matthew W. Smith (MATTSMI)
  240. DATE DOCUMENTED: March 5, 1992
  241. @doc INTERNAL
  242. @api int FAR PASCAL | WCmpiSnn | compares two LPSTRs
  243. without case sensitivity, given lengths of strings
  244. @parm LPSTR | lpstrOne | first string for comparison.
  245. @parm LPSTR | lpstrTwo | other string for comparison.
  246. @parm BYTE far * | qbLigatures | ligature table loaded from the
  247. file system or from hardwiring (by default).
  248. @parm SHORT | iLenOne |
  249. Length of first string
  250. @parm SHORT | iLenTwo |
  251. Length of second string
  252. @comm
  253. This routine is analogous to strcmpi() except it
  254. uses long pointers. It is unlike lstrcmpi() in
  255. that it is truly case insensitive.
  256. This routine is unlike CompareLPSTRi in that it works
  257. off of Microsoft's standard internal international
  258. character set table.
  259. The return value is:
  260. 0 if lpstrOne = lpstrTwo
  261. 1 if lpstrOne > lpstrTwo
  262. -1 if lpstrOne < lpstrTwo
  263. NOTE: this version differs from CompareTableLPSTRi() in that
  264. ligature expansion (which is viewer-compiler specific is undertaken).
  265. This is done by drawing on a ligature table (LPSTR) kept globally
  266. during compilation -- see LoadLigatureTable().
  267. This routine draws on the standard Help character sort order
  268. table in utilib.c -- it is an extern global here.
  269. NOTE: this routine assumes that the ligature table available
  270. to it (rgchLigatureSortTableGlobal) uses the OEM and not ANSI character
  271. set.
  272. ***************************************************/
  273. /*-----------------------------------------------------------------------*/
  274. { /*** WCmpiSz ***/
  275. int i=0, j=0;
  276. unsigned char ch1, ch2, ch;
  277. BYTE cLigs, c;
  278. unsigned char ch1Next='\0';
  279. unsigned char ch2Next='\0';
  280. BOOL fDontExpandCh1=FALSE;
  281. BOOL fDontExpandCh2=FALSE;
  282. if (!qbLigatures)
  283. cLigs=0;
  284. else
  285. cLigs=qbLigatures[0];
  286. ch1=(iLen1)?lpstrOne[0]:0;
  287. ch2=(iLen2)?lpstrTwo[0]:0;
  288. while (ch1 && ch2)
  289. {
  290. /***************************
  291. CHECK FOR LIGATURE EXPANSION
  292. ****************************/
  293. for (c=1; c<=cLigs; c++)
  294. {
  295. ch=qbLigatures[(c-1)*3+1];
  296. if (!fDontExpandCh1 && (ch1 == ch))
  297. {
  298. ch1=qbLigatures[(c-1)*3+2];
  299. ch1Next=qbLigatures[(c-1)*3+3];
  300. }
  301. if (!fDontExpandCh2 && (ch2 == ch))
  302. {
  303. ch2=qbLigatures[(c-1)*3+2];
  304. ch2Next=qbLigatures[(c-1)*3+3];
  305. }
  306. }
  307. ch1=mpchordNorm[ch1];
  308. ch2=mpchordNorm[ch2];
  309. fDontExpandCh1=FALSE;
  310. fDontExpandCh2=FALSE;
  311. /*************************************************
  312. EITHER BREAK BECAUSE THE CHARACTERS WERE DIFFERENT
  313. OR GET THE NEXT CHARACTER FOR COMPARISION
  314. **************************************************/
  315. if (ch1 != ch2)
  316. break;
  317. else
  318. {
  319. if (ch1Next)
  320. {
  321. ch1=ch1Next;
  322. ch1Next='\0';
  323. fDontExpandCh1=TRUE; // SETTING THIS FLAG PREVENTS ENDLESS RECURSION
  324. }
  325. else
  326. ch1=((++i)==iLen1)?0:lpstrOne[i];
  327. //ch1=lpstrOne[++i];
  328. if (ch2Next)
  329. {
  330. ch2=ch2Next;
  331. ch2Next='\0';
  332. fDontExpandCh2=TRUE; // SETTING THIS FLAG PREVENTS ENDLESS RECURSION
  333. }
  334. else
  335. ch2=((++j)==iLen2)?0:lpstrTwo[j];
  336. //ch2=lpstrTwo[++j];
  337. }
  338. }
  339. /**********************************
  340. IF STRINGS BOTH TERMINATED AT THE
  341. SAME TIME WITHOUT DIFF BEING FOUND
  342. THEY ARE THE SAME
  343. ***********************************/
  344. if (!ch1 && !ch2)
  345. return(0);
  346. /**************************************
  347. IF ONE TERMINATED AND NO DIFF WAS
  348. FOUND WHEN IT DID, THEN THE TERMINATING
  349. STRING COMES FIRST . . .
  350. ***************************************/
  351. if (!ch1)
  352. return(-1);
  353. else if (!ch2)
  354. return(1);
  355. /*********************************
  356. DIFF WAS FOUND; RETURN ACCORDINGLY
  357. **********************************/
  358. if (ch1 < ch2)
  359. return(-1);
  360. else
  361. return(1);
  362. } /*** WCmpiSz ***/
  363. /*-----------------------------------------------------------------------*/
  364. /***************************************************************************
  365. *
  366. - Function: WCmpiScandSz(sz1, sz2)
  367. -
  368. * Purpose: Compare two SZs, case insensitive. Scandinavian
  369. * international characters are OK.
  370. *
  371. * ASSUMES
  372. *
  373. * args IN: sz1, sz2 - the SZs to compare
  374. *
  375. * globals IN: mpchordScan[] - the pch -> ordinal mapping table for
  376. * the Scandinavian character set
  377. *
  378. * PROMISES
  379. *
  380. * returns: <0 for sz1 < sz2; =0 for sz1 == sz2; >0 for sz1 > sz2
  381. *
  382. * Bugs: Doesn't deal with composed ae, oe.
  383. *
  384. ***************************************************************************/
  385. SHORT FAR PASCAL WCmpiScandSz(sz1, sz2)
  386. SZ sz1, sz2;
  387. {
  388. while (0 == (int)( (unsigned char)*sz1 - (unsigned char)*sz2) )
  389. {
  390. if ('\0' == *sz1) return 0;
  391. sz1++; sz2++;
  392. }
  393. while (0 == ( mpchordScan[(unsigned char)*sz1] - mpchordScan[(unsigned char)*sz2]) )
  394. {
  395. if ('\0' == *sz1) return 0;
  396. sz1++; sz2++;
  397. }
  398. return mpchordScan[(unsigned char)*sz1] - mpchordScan[(unsigned char)*sz2];
  399. }