1 #ifdef WIN32 2 #define WIN32_LEAN_AND_MEAN 3 #include <windows.h> 4 #else 5 #include "wintypes.h" 6 #endif 7 #include <winnls.h> 8 9 #include <stdio.h> 10 #include <assert.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 #include "nls.h" 15 #include "nlstables.h" 16 17 #ifdef WIN32 18 #define NlsStrLenW lstrlenW // Hack 19 #else 20 #define NlsStrLenW wcslen 21 #endif 22 23 24 // 25 // Invalid weight value. 26 // 27 #define MAP_INVALID_UW 0xffff 28 29 #define NUM_BYTES_UW 2 30 #define NUM_BYTES_DW 1 31 #define NUM_BYTES_CW 1 32 #define NUM_BYTES_XW 4 33 34 #define NORM_DROP_CW (NORM_IGNORECASE | NORM_IGNOREWIDTH) 35 36 #define EXTRA_WEIGHT_POS(WtNum) (*(pPosXW + (WtNum * WeightLen))) 37 38 #define SPECIAL_CASE_HANDLER( SM, \ 39 pWeight, \ 40 pSortkey, \ 41 pExpand, \ 42 Position, \ 43 fStringSort, \ 44 fIgnoreSymbols, \ 45 pCur, \ 46 pBegin ) \ 47 { \ 48 PSORTKEY pExpWt; /* weight of 1 expansion char */ \ 49 BYTE AW; /* alphanumeric weight */ \ 50 BYTE XW; /* case weight value with extra bits */ \ 51 DWORD PrevWt; /* previous weight */ \ 52 BYTE PrevSM; /* previous script member */ \ 53 BYTE PrevAW; /* previuos alphanumeric weight */ \ 54 BYTE PrevCW; /* previuos case weight */ \ 55 LPWSTR pPrev; /* ptr to previous char */ \ 56 \ 57 \ 58 switch (SM) \ 59 { \ 60 case ( UNSORTABLE ) : \ 61 { \ 62 /* \ 63 * Character is unsortable, so skip it. \ 64 */ \ 65 break; \ 66 } \ 67 \ 68 case ( NONSPACE_MARK ) : \ 69 { \ 70 /* \ 71 * Character is a nonspace mark, so only store \ 72 * the diacritic weight. \ 73 */ \ 74 if (pPosDW > pDW) \ 75 { \ 76 (*(pPosDW - 1)) += GET_DIACRITIC(pWeight); \ 77 } \ 78 else \ 79 { \ 80 *pPosDW = GET_DIACRITIC(pWeight); \ 81 pPosDW++; \ 82 } \ 83 \ 84 break; \ 85 } \ 86 \ 87 case ( EXPANSION ) : \ 88 { \ 89 /* \ 90 * Expansion character - one character has 2 \ 91 * different weights. Store each weight separately. \ 92 */ \ 93 pExpWt = &(pSortkey[(pExpand[GET_EXPAND_INDEX(pWeight)]).UCP1]); \ 94 *pPosUW = GET_UNICODE(pExpWt); \ 95 *pPosDW = GET_DIACRITIC(pExpWt); \ 96 *pPosCW = GET_CASE(pExpWt) & CaseMask; \ 97 pPosUW++; \ 98 pPosDW++; \ 99 pPosCW++; \ 100 \ 101 pExpWt = &(pSortkey[(pExpand[GET_EXPAND_INDEX(pWeight)]).UCP2]); \ 102 *pPosUW = GET_UNICODE(pExpWt); \ 103 *pPosDW = GET_DIACRITIC(pExpWt); \ 104 *pPosCW = GET_CASE(pExpWt) & CaseMask; \ 105 pPosUW++; \ 106 pPosDW++; \ 107 pPosCW++; \ 108 \ 109 break; \ 110 } \ 111 \ 112 case ( PUNCTUATION ) : \ 113 { \ 114 if (!fStringSort) \ 115 { \ 116 /* \ 117 * Word Sort Method. \ 118 * \ 119 * Character is punctuation, so only store the special \ 120 * weight. \ 121 */ \ 122 *((LPBYTE)pPosSW) = HIBYTE(GET_POSITION_SW(Position)); \ 123 *(((LPBYTE)pPosSW) + 1) = LOBYTE(GET_POSITION_SW(Position)); \ 124 pPosSW++; \ 125 *pPosSW = GET_SPECIAL_WEIGHT(pWeight); \ 126 pPosSW++; \ 127 \ 128 break; \ 129 } \ 130 \ 131 /* \ 132 * If using STRING sort method, treat punctuation the same \ 133 * as symbol. So, FALL THROUGH to the symbol cases. \ 134 */ \ 135 } \ 136 \ 137 case ( SYMBOL_1 ) : \ 138 case ( SYMBOL_2 ) : \ 139 case ( SYMBOL_3 ) : \ 140 case ( SYMBOL_4 ) : \ 141 case ( SYMBOL_5 ) : \ 142 { \ 143 /* \ 144 * Character is a symbol. \ 145 * Store the Unicode weights ONLY if the NORM_IGNORESYMBOLS \ 146 * flag is NOT set. \ 147 */ \ 148 if (!fIgnoreSymbols) \ 149 { \ 150 *pPosUW = GET_UNICODE(pWeight); \ 151 *pPosDW = GET_DIACRITIC(pWeight); \ 152 *pPosCW = GET_CASE(pWeight) & CaseMask; \ 153 pPosUW++; \ 154 pPosDW++; \ 155 pPosCW++; \ 156 } \ 157 \ 158 break; \ 159 } \ 160 \ 161 case ( FAREAST_SPECIAL ) : \ 162 { \ 163 /* \ 164 * Get the alphanumeric weight and the case weight of the \ 165 * current code point. \ 166 */ \ 167 AW = GET_ALPHA_NUMERIC(pWeight); \ 168 XW = (GET_CASE(pWeight) & CaseMask) | CASE_XW_MASK; \ 169 \ 170 /* \ 171 * Special case Repeat and Cho-On. \ 172 * AW = 0 => Repeat \ 173 * AW = 1 => Cho-On \ 174 * AW = 2+ => Kana \ 175 */ \ 176 if (AW <= MAX_SPECIAL_AW) \ 177 { \ 178 /* \ 179 * If the script member of the previous character is \ 180 * invalid, then give the special character an \ 181 * invalid weight (highest possible weight) so that it \ 182 * will sort AFTER everything else. \ 183 */ \ 184 pPrev = pCur - 1; \ 185 *pPosUW = MAP_INVALID_UW; \ 186 while (pPrev >= pBegin) \ 187 { \ 188 PrevWt = GET_DWORD_WEIGHT(pHashN, *pPrev); \ 189 PrevSM = GET_SCRIPT_MEMBER(&PrevWt); \ 190 if (PrevSM < FAREAST_SPECIAL) \ 191 { \ 192 if (PrevSM != EXPANSION) \ 193 { \ 194 /* \ 195 * UNSORTABLE or NONSPACE_MARK. \ 196 * \ 197 * Just ignore these, since we only care \ 198 * about the previous UW value. \ 199 */ \ 200 pPrev--; \ 201 continue; \ 202 } \ 203 } \ 204 else if (PrevSM == FAREAST_SPECIAL) \ 205 { \ 206 PrevAW = GET_ALPHA_NUMERIC(&PrevWt); \ 207 if (PrevAW <= MAX_SPECIAL_AW) \ 208 { \ 209 /* \ 210 * Handle case where two special chars follow \ 211 * each other. Keep going back in the string. \ 212 */ \ 213 pPrev--; \ 214 continue; \ 215 } \ 216 \ 217 *pPosUW = MAKE_UNICODE_WT(KANA, PrevAW); \ 218 \ 219 /* \ 220 * Only build weights 4, 5, 6, and 7 if the \ 221 * previous character is KANA. \ 222 * \ 223 * Always: \ 224 * 4W = previous CW & ISOLATE_SMALL \ 225 * 6W = previous CW & ISOLATE_KANA \ 226 * \ 227 */ \ 228 PrevCW = (GET_CASE(&PrevWt) & CaseMask) | \ 229 CASE_XW_MASK; \ 230 EXTRA_WEIGHT_POS(0) = PrevCW & ISOLATE_SMALL; \ 231 EXTRA_WEIGHT_POS(2) = PrevCW & ISOLATE_KANA; \ 232 \ 233 if (AW == AW_REPEAT) \ 234 { \ 235 /* \ 236 * Repeat: \ 237 * UW = previous UW (set above) \ 238 * 5W = WT_FIVE_REPEAT \ 239 * 7W = previous CW & ISOLATE_WIDTH \ 240 */ \ 241 EXTRA_WEIGHT_POS(1) = WT_FIVE_REPEAT; \ 242 EXTRA_WEIGHT_POS(3) = PrevCW & ISOLATE_WIDTH; \ 243 } \ 244 else \ 245 { \ 246 /* \ 247 * Cho-On: \ 248 * UW = previous UW & CHO_ON_UW_MASK \ 249 * 5W = WT_FIVE_CHO_ON \ 250 * 7W = current CW & ISOLATE_WIDTH \ 251 */ \ 252 *pPosUW &= CHO_ON_UW_MASK; \ 253 EXTRA_WEIGHT_POS(1) = WT_FIVE_CHO_ON; \ 254 EXTRA_WEIGHT_POS(3) = XW & ISOLATE_WIDTH; \ 255 } \ 256 \ 257 pPosXW++; \ 258 } \ 259 else \ 260 { \ 261 *pPosUW = GET_UNICODE(&PrevWt); \ 262 } \ 263 \ 264 break; \ 265 } \ 266 \ 267 /* \ 268 * Make sure there is a valid UW. If not, quit out \ 269 * of switch case. \ 270 */ \ 271 if (*pPosUW == MAP_INVALID_UW) \ 272 { \ 273 pPosUW++; \ 274 break; \ 275 } \ 276 } \ 277 else \ 278 { \ 279 /* \ 280 * Kana: \ 281 * SM = KANA \ 282 * AW = current AW \ 283 * 4W = current CW & ISOLATE_SMALL \ 284 * 5W = WT_FIVE_KANA \ 285 * 6W = current CW & ISOLATE_KANA \ 286 * 7W = current CW & ISOLATE_WIDTH \ 287 */ \ 288 *pPosUW = MAKE_UNICODE_WT(KANA, AW); \ 289 EXTRA_WEIGHT_POS(0) = XW & ISOLATE_SMALL; \ 290 EXTRA_WEIGHT_POS(1) = WT_FIVE_KANA; \ 291 EXTRA_WEIGHT_POS(2) = XW & ISOLATE_KANA; \ 292 EXTRA_WEIGHT_POS(3) = XW & ISOLATE_WIDTH; \ 293 \ 294 pPosXW++; \ 295 } \ 296 \ 297 /* \ 298 * Always: \ 299 * DW = current DW \ 300 * CW = minimum CW \ 301 */ \ 302 *pPosDW = GET_DIACRITIC(pWeight); \ 303 *pPosCW = MIN_CW; \ 304 \ 305 pPosUW++; \ 306 pPosDW++; \ 307 pPosCW++; \ 308 \ 309 break; \ 310 } \ 311 \ 312 case ( RESERVED_2 ) : \ 313 case ( RESERVED_3 ) : \ 314 { \ 315 /* \ 316 * Fill out the case statement so the compiler \ 317 * will use a jump table. \ 318 */ \ 319 ; \ 320 } \ 321 } \ 322 } 323 324 325 BYTE pXWDrop[] = // values to drop from XW 326 { 327 0xc6, // weight 4 328 0x03, // weight 5 329 0xe4, // weight 6 330 0xc5 // weight 7 331 }; 332 BYTE pXWSeparator[] = // separator values for XW 333 { 334 0xff, // weight 4 335 0x02, // weight 5 336 0xff, // weight 6 337 0xff // weight 7 338 }; 339 340 BYTE pAllWSeparator[] = 341 { 342 0x01, 0x01, 0xFF, 0x02, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 344 }; 345 346 BOOL fBaseUsed = FALSE, fCBaseUsed = FALSE; 347 LOC_HASH *g_pLocale = NULL; 348 MAP_BUFF g_RootBuff={0}; 349 350 351 MAP_BUFF *GetMapBuff(DWORD cbBuff) 352 { 353 MAP_BUFF *pBuf; 354 355 //EnterCriticalSection(&g_CritSec); 356 for ( pBuf = &g_RootBuff; ; pBuf = pBuf->pNext ) 357 { 358 if ( cbBuff <= pBuf->cbBuff && !pBuf->bAllocated ) 359 { 360 pBuf->bAllocated = TRUE; 361 //LeaveCriticalSection(&g_CritSec); 362 return pBuf; 363 } 364 if (!pBuf->pNext) break; 365 } 366 cbBuff += 4095; 367 cbBuff &= 0xFFFFF000; 368 pBuf->pNext = malloc(cbBuff + sizeof(MAP_BUFF)); 369 pBuf = pBuf->pNext; 370 if (pBuf) 371 { 372 pBuf->pNext = NULL; 373 pBuf->cbBuff = cbBuff; 374 pBuf->bAllocated = TRUE; 375 } 376 //LeaveCriticalSection(&g_CritSec); 377 return pBuf; 378 } 379 380 MAP_BUFF *FreeMapBuff(MAP_BUFF *pPBuf) 381 { 382 MAP_BUFF *pBuf; 383 384 for (pBuf = &g_RootBuff; ; pBuf = pBuf->pNext) 385 { 386 if (pPBuf == pBuf) 387 { 388 pBuf->bAllocated = FALSE; 389 break; 390 } 391 } 392 return pBuf; 393 } 394 395 PLOC_HASH DBCreateTables(int Locale, int uFlags, SORTKEY *pSortKeys) 396 { 397 // TODO: Implement 398 return NULL; 399 } 400 401 PLOC_HASH SetSortInfo(LCID Locale, DWORD dwMapFlags) 402 { 403 LCID Loc = Locale; 404 PLOC_HASH pHashN; 405 406 if (dwMapFlags & LCMAP_LINGUISTIC_CASING) Loc*=-1; 407 for (pHashN = (PLOC_HASH)&g_pLocale; pHashN; pHashN=pHashN->pNext) 408 { 409 if (pHashN->Locale == Loc) return pHashN; 410 if (!pHashN->pNext) break; 411 } 412 413 #ifndef MDBTOOLS 414 if (!fBaseUsed && Loc == MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT)) 415 { 416 if (!(pHashN->pNext=calloc(sizeof(LOC_HASH), 1))) return NULL; 417 pHashN->pNext->Locale = Loc; 418 pHashN->pNext->pSortkey = (PSORTKEY)g_SortKeys; 419 pHashN->pNext->wUnk1 = 34; 420 fBaseUsed = TRUE; 421 return pHashN->pNext; 422 } 423 #endif 424 425 if (!fCBaseUsed && (int)Loc == (int)(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT))*-1) 426 { 427 if (!(pHashN->pNext=calloc(sizeof(LOC_HASH), 1))) return NULL; 428 pHashN->pNext->Locale = Loc; 429 pHashN->pNext->pSortkey = (PSORTKEY)g_SortCompKeys; 430 pHashN->pNext->wUnk1 = 127; 431 fCBaseUsed = TRUE; 432 return pHashN->pNext; 433 } 434 // MSWDAT10.DLL 435 pHashN->pNext = DBCreateTables(Locale, dwMapFlags, 436 #ifndef MDBTOOLS 437 fBaseUsed?NULL:(PSORTKEY)g_SortKeys 438 #else 439 NULL 440 #endif 441 ); 442 fBaseUsed = TRUE; 443 return pHashN->pNext; 444 } 445 446 447 int WINAPI DBLCMapStringW(LCID Locale, int dwFlags, WCHAR *lpSrcString, signed int cchSrc, LPBYTE pDest, int cchDest) 448 { 449 signed int cchExtra, cchSep; 450 BYTE CaseMask; 451 register int WeightLen; // Length of one Weight set 452 MAP_BUFF *pBuf; 453 LPWSTR pUW; // Unicode Weights 454 LPBYTE pDW; // ptr to Diacritic Weights 455 LPBYTE pCW; // ptr to Case Weights 456 LPBYTE pXW; // ptr to Extra Weights 457 LPWSTR pSW; // ptr to Special Weights 458 LPWSTR pPosUW; // pUW buf ptr 459 LPBYTE pPosCW; // pCW buf ptr 460 LPBYTE pPosDW; // pDW buf ptr 461 LPBYTE pPosXW; // ptr to position in pXW buffer 462 LPWSTR pPosSW; // ptr to position in pSW buffer 463 PSORTKEY pWeight; // weight of char ptr 464 LPBYTE pTmp; // ptr to go through UW, XW, and SW 465 LPBYTE pPosTmp, pPosOffset; // ptr to tmp position in XW 466 int PosCtr, ctr; 467 LPWSTR pPos; 468 PLOC_HASH pHashN; // Hash table 469 BYTE SM; // Script member 470 BOOL fStringSort; // if using string sort method 471 BOOL fIgnoreSymbols; // if ignore symbols flag is set 472 473 if (!lpSrcString || !(pHashN = SetSortInfo(Locale, dwFlags))) return 0; 474 if (cchSrc <= -1) cchSrc = NlsStrLenW(lpSrcString) + 1; 475 476 if (dwFlags & (LCMAP_LOWERCASE | LCMAP_UPPERCASE)) 477 { 478 PCASE pMapTable; 479 480 if (dwFlags & LCMAP_LOWERCASE) 481 { 482 if (dwFlags & LCMAP_LINGUISTIC_CASING) 483 { 484 pMapTable = g_LinguisticLowerCase; 485 for (PosCtr = 0; g_SpecialCase[PosCtr].Locale; PosCtr++) 486 { 487 if (g_SpecialCase[PosCtr].Locale == Locale) 488 { 489 pMapTable = g_SpecialCase[PosCtr].pLowerCase; 490 break; 491 } 492 } 493 } 494 else 495 { 496 pMapTable = g_LowerCase; 497 } 498 } 499 else 500 { 501 if (dwFlags & LCMAP_LINGUISTIC_CASING) 502 { 503 pMapTable = g_LinguisticUpperCase; 504 for (PosCtr = 0; g_SpecialCase[PosCtr].Locale; PosCtr++) 505 { 506 if (g_SpecialCase[PosCtr].Locale == Locale) 507 { 508 pMapTable = g_SpecialCase[PosCtr].pUpperCase; 509 break; 510 } 511 } 512 } 513 else 514 { 515 pMapTable = g_UpperCase; 516 } 517 } 518 if ( cchSrc > 0 ) 519 { 520 for (PosCtr = 0; PosCtr < cchSrc; PosCtr++) 521 { 522 pDest[PosCtr] = lpSrcString[PosCtr] + g_CasePages[pMapTable[lpSrcString[PosCtr]]][lpSrcString[PosCtr]]; 523 } 524 } 525 return PosCtr; 526 } 527 528 // TODO: Invalid Flags Check 529 WeightLen = cchSrc * MAX_EXPANSION; 530 if (!(dwFlags & LCMAP_SORTKEY) || !(pBuf = GetMapBuff(WeightLen * MAX_WEIGHTS * sizeof(WCHAR)))) 531 return 0; 532 533 pUW = (LPWSTR)((DWORD)pBuf + sizeof(MAP_BUFF)); 534 pDW = (LPBYTE)(pUW + (WeightLen * (NUM_BYTES_UW / sizeof(WCHAR)))); 535 pCW = (LPBYTE)(pDW + (WeightLen * NUM_BYTES_DW)); 536 pXW = (LPBYTE)(pCW + (WeightLen * NUM_BYTES_CW)); 537 pSW = (LPWSTR)(pXW + (WeightLen * NUM_BYTES_XW)); 538 pPosUW = pUW; 539 pPosDW = pDW; 540 pPosCW = pCW; 541 pPosXW = pXW; 542 pPosSW = pSW; 543 544 CaseMask = 0xFF; 545 if ( dwFlags & NORM_IGNORECASE ) 546 CaseMask = CASE_UPPER_MASK; 547 if ( dwFlags & NORM_IGNOREKANATYPE ) 548 CaseMask &= CASE_KANA_MASK; 549 if ( dwFlags & NORM_IGNOREWIDTH ) 550 CaseMask &= CASE_WIDTH_MASK; 551 552 fStringSort = dwFlags & SORT_STRINGSORT; 553 fIgnoreSymbols = dwFlags & NORM_IGNORESYMBOLS; 554 pPos = lpSrcString; 555 if ( cchSrc >= 1 ) 556 { 557 // TODO: JUMPOUT(pHashN[4], 0, &loc_10001DFF); // IfCompression? 558 for (PosCtr = 1; PosCtr <= cchSrc; PosCtr++, pPos++) 559 { 560 pWeight = (PSORTKEY)(&(pHashN->pSortkey)[*pPos]); 561 SM = GET_SCRIPT_MEMBER(pWeight); 562 563 if (SM > MAX_SPECIAL_CASE) 564 { 565 *pPosUW = UNICODE_WT(pWeight); 566 *pPosDW = GET_DIACRITIC(pWeight); 567 *pPosCW = GET_CASE(pWeight) & CaseMask; 568 pPosUW++; 569 pPosDW++; 570 pPosCW++; 571 } 572 else 573 { 574 SPECIAL_CASE_HANDLER( SM, 575 pWeight, 576 pHashN->pSortkey, 577 g_Expansion, 578 pPosUW - pUW + 1, 579 fStringSort, 580 fIgnoreSymbols, 581 pPos, 582 (LPWSTR)lpSrcString ); 583 } 584 } 585 } 586 PosCtr = 0; 587 if (cchDest == 0) 588 { 589 if ( dwFlags & LCMAP_LINGUISTIC_CASING ) 590 { 591 LPBYTE pUWTmp; 592 593 for (pUWTmp = (LPBYTE)pUW; pUWTmp != (LPBYTE)pPosUW; pUWTmp++) 594 if (*pUWTmp) ++PosCtr; 595 } 596 else 597 { 598 PosCtr += ((LPBYTE)pPosUW - (LPBYTE)pUW); 599 } 600 PosCtr++; 601 if (!(dwFlags & NORM_IGNORENONSPACE)) 602 { 603 pPosDW--; 604 if (pHashN->IfReverseDW == TRUE) 605 { 606 while ((pDW <= pPosDW) && (*pDW <= MIN_DW)) 607 { 608 pDW++; 609 } 610 PosCtr += (pPosDW - pDW + 1); 611 } 612 else 613 { 614 while ((pPosDW >= pDW) && (*pPosDW <= MIN_DW)) 615 { 616 pPosDW--; 617 } 618 PosCtr += (pPosDW - pDW + 1); 619 } 620 } 621 622 PosCtr++; 623 624 if ((dwFlags & NORM_DROP_CW) != NORM_DROP_CW) 625 { 626 pPosCW--; 627 while ((pPosCW >= pCW) && (*pPosCW <= MIN_CW)) 628 { 629 pPosCW--; 630 } 631 PosCtr += (pPosCW - pCW + 1); 632 } 633 634 PosCtr++; 635 636 637 if (pXW < pPosXW) 638 { 639 if (dwFlags & NORM_IGNORENONSPACE) 640 { 641 PosCtr += 2; 642 ctr = 2; 643 } 644 else 645 { 646 ctr = 0; 647 } 648 pPosXW--; 649 for (; ctr < NUM_BYTES_XW; ctr++) 650 { 651 pTmp = pXW + (WeightLen * ctr); 652 pPosTmp = pPosXW + (WeightLen * ctr); 653 while ((pPosTmp >= pTmp) && (*pPosTmp == pXWDrop[ctr])) 654 { 655 pPosTmp--; 656 } 657 if ( dwFlags & LCMAP_LINGUISTIC_CASING ) 658 { 659 PosCtr += (pPosTmp - pTmp + 1 + gXW_comp[ctr][3]) / (gXW_comp[ctr][3]+1); 660 } 661 else 662 { 663 PosCtr += (pPosTmp - pTmp + 1); 664 } 665 PosCtr++; 666 } 667 } 668 669 PosCtr++; 670 671 if (!fIgnoreSymbols) 672 { 673 PosCtr += ((LPBYTE)pPosSW - (LPBYTE)pSW); 674 } 675 676 PosCtr++; 677 } 678 else 679 { 680 if (dwFlags & LOCALE_NOUSEROVERRIDE) 681 { 682 // TODO: JUMPOUT(dwFlags & LOCALE_NOUSEROVERRIDE, 0, &loc_10002502); 683 684 } 685 686 cchExtra = 0; 687 cchSep = 0; 688 if ( pPosUW != pUW ) 689 { 690 if (dwFlags & LCMAP_LINGUISTIC_CASING) 691 { 692 LPBYTE pUWTmp; 693 694 for (pUWTmp = (LPBYTE)pUW; pUWTmp != (LPBYTE)pPosUW; pUWTmp++) 695 if (*pUWTmp) pDest[PosCtr++]=*pUWTmp; 696 } 697 else 698 { 699 PosCtr = ((LPBYTE)pPosUW - (LPBYTE)pUW); 700 if (cchDest < PosCtr) 701 { 702 FreeMapBuff(pBuf); 703 return 0; 704 } 705 memcpy (pDest, pUW, PosCtr); 706 707 } 708 } 709 if (cchDest < (PosCtr + 1)) 710 { 711 FreeMapBuff(pBuf); 712 return 0; 713 } 714 pDest[PosCtr] = SORTKEY_SEPARATOR; 715 PosCtr++; 716 717 718 if (!(dwFlags & NORM_IGNORENONSPACE)) 719 { 720 pPosDW--; 721 if (pHashN->IfReverseDW == TRUE) 722 { 723 while ((pDW <= pPosDW) && (*pDW <= MIN_DW)) 724 { 725 pDW++; 726 } 727 if ((cchDest - PosCtr) <= (pPosDW - pDW + 1)) 728 { 729 FreeMapBuff(pBuf); 730 return (0); 731 } 732 while (pPosDW >= pDW) 733 { 734 pDest[PosCtr] = *pPosDW; 735 PosCtr++; 736 pPosDW--; 737 } 738 } 739 else 740 { 741 while ((pPosDW >= pDW) && (*pPosDW <= MIN_DW)) 742 { 743 pPosDW--; 744 } 745 if ((cchDest - PosCtr) <= (pPosDW - pDW + 1)) 746 { 747 FreeMapBuff(pBuf); 748 return (0); 749 } 750 memcpy(&pDest[PosCtr], pDW, pPosDW - pDW + 1); 751 PosCtr += pPosDW - pDW + 1; 752 } 753 } 754 755 756 if ( PosCtr >= cchDest ) 757 { 758 if (dwFlags & LCMAP_LINGUISTIC_CASING) 759 { 760 FreeMapBuff(pBuf); 761 return (0); 762 } 763 } 764 else 765 { 766 pDest[PosCtr] = SORTKEY_SEPARATOR; 767 PosCtr++; 768 769 if ( PosCtr < cchDest ) 770 cchExtra = 1; 771 } 772 773 if ((dwFlags & NORM_DROP_CW) != NORM_DROP_CW) 774 { 775 pPosCW--; 776 while ((pPosCW >= pCW) && (*pPosCW <= MIN_CW)) 777 { 778 pPosCW--; 779 } 780 if ((cchDest - PosCtr) <= (pPosCW - pCW + 1)) 781 { 782 FreeMapBuff(pBuf); 783 return (0); 784 } 785 memcpy(&pDest[PosCtr], pCW, pPosCW - pCW); 786 PosCtr += pPosCW - pCW; 787 } 788 if ( PosCtr >= cchDest ) 789 { 790 if (dwFlags & LCMAP_LINGUISTIC_CASING) 791 { 792 FreeMapBuff(pBuf); 793 return (0); 794 } 795 } 796 else 797 { 798 pDest[PosCtr] = SORTKEY_SEPARATOR; 799 PosCtr++; 800 if ( PosCtr < cchDest ) ++cchExtra; 801 } 802 803 //JUMPOUT(pXW, pPosXW, sub_1000262D); 804 if (pXW < pPosXW) 805 { 806 if (dwFlags & NORM_IGNORENONSPACE) 807 { 808 if ( PosCtr >= cchDest ) 809 { 810 if (dwFlags & LCMAP_LINGUISTIC_CASING) 811 { 812 FreeMapBuff(pBuf); 813 return (0); 814 } 815 } 816 else 817 { 818 pDest[PosCtr++] = pXWSeparator[0]; 819 if ( PosCtr >= cchDest ) 820 { 821 if (dwFlags & LCMAP_LINGUISTIC_CASING) 822 { 823 FreeMapBuff(pBuf); 824 return (0); 825 } 826 } 827 else 828 { 829 cchSep = 1; 830 ++cchExtra; 831 pDest[PosCtr++] = pXWSeparator[1]; 832 if ( PosCtr < cchDest ) ++cchExtra; 833 } 834 ctr = 2; 835 } 836 } 837 else 838 { 839 ctr = 0; 840 } 841 842 for (; ctr < NUM_BYTES_XW; ctr++) 843 { 844 if ( pPosXW - pXW ) 845 { 846 pTmp = pXW + (WeightLen * ctr); 847 pPosTmp = pPosXW + (WeightLen * ctr); 848 pPosOffset = (LPBYTE)(pPosXW - pXW); 849 850 while ((pPosTmp >= pTmp) && (*pPosTmp == pXWDrop[ctr])) 851 { 852 pPosTmp--; 853 } 854 if ( (dwFlags & LCMAP_LINGUISTIC_CASING) ) 855 { 856 BYTE pNumOffs, c; 857 858 for (c = 0x80, pNumOffs=(BYTE)gXW_comp[ctr][3]; pPosTmp > pTmp; pTmp++) 859 { 860 c |= (BYTE)((ctr==1?((*pTmp>>1)|*pTmp&1):*pTmp) & gXW_comp[ctr][0]) >> 861 gXW_comp[ctr][1] << pNumOffs * gXW_comp[ctr][2]; 862 if (pNumOffs) 863 { 864 pNumOffs--; 865 continue; 866 } 867 if ( cchDest - PosCtr < 2) 868 { 869 FreeMapBuff(pBuf); 870 return (0); 871 } 872 pDest[PosCtr++] = c; 873 pNumOffs = gXW_comp[ctr][3]; 874 c = 0x80; 875 } 876 if (pNumOffs != gXW_comp[ctr][3] && cchDest - PosCtr >= 2) pDest[PosCtr++] = c; 877 } 878 else 879 { 880 if ((cchDest - PosCtr) <= (pPosTmp - pTmp + 1)) 881 { 882 FreeMapBuff(pBuf); 883 return (0); 884 } 885 memcpy(&pDest[PosCtr], pTmp, pPosTmp - pTmp); 886 PosCtr += pPosTmp - pTmp; 887 } 888 } 889 if ( PosCtr >= cchDest ) 890 { 891 if (dwFlags & LCMAP_LINGUISTIC_CASING) 892 { 893 FreeMapBuff(pBuf); 894 return (0); 895 } 896 } 897 else 898 { 899 pDest[PosCtr] = pXWSeparator[ctr]; 900 PosCtr++; 901 if ( PosCtr < cchDest ) 902 { 903 ++cchExtra; 904 ++cchSep; 905 } 906 } 907 } 908 909 if ( PosCtr >= cchDest ) 910 { 911 if (dwFlags & LCMAP_LINGUISTIC_CASING) 912 { 913 FreeMapBuff(pBuf); 914 return (0); 915 } 916 } 917 } 918 919 pDest[PosCtr] = SORTKEY_SEPARATOR; 920 PosCtr++; 921 922 if ( PosCtr < cchDest ) cchExtra++; 923 if (!fIgnoreSymbols) 924 { 925 if ((cchDest - PosCtr) <= ((LPBYTE)pPosSW - (LPBYTE)pSW)) 926 { 927 FreeMapBuff(pBuf); 928 return (0); 929 } 930 memcpy(&pDest[PosCtr], pSW, (LPBYTE)pPosSW - (LPBYTE)pSW); 931 PosCtr += (LPBYTE)pPosSW - (LPBYTE)pSW; 932 } 933 934 if ( PosCtr >= cchDest ) 935 { 936 if (dwFlags & LCMAP_LINGUISTIC_CASING) 937 { 938 FreeMapBuff(pBuf); 939 return (0); 940 } 941 } 942 943 pDest[PosCtr] = SORTKEY_TERMINATOR; 944 if ( cchExtra && (dwFlags & LCMAP_LINGUISTIC_CASING) ) 945 { 946 do 947 { 948 --cchExtra; 949 if ( (cchSep && pDest[PosCtr - 2] != pAllWSeparator[cchExtra]) || pDest[PosCtr - 2] != SORTKEY_SEPARATOR ) 950 break; 951 pDest[PosCtr - 1] = SORTKEY_TERMINATOR; 952 PosCtr--; 953 } 954 while ( cchExtra ); 955 } 956 957 } 958 FreeMapBuff(pBuf); 959 return PosCtr; 960 } 961