Changeset 147 for trunk/src/helpers/nls.c
- Timestamp:
- Mar 16, 2002, 8:53:47 AM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/nls.c
r142 r147 40 40 41 41 #define INCL_DOSNLS 42 #define INCL_DOSSEMAPHORES 43 #define INCL_DOSEXCEPTIONS 44 #define INCL_DOSPROCESS 42 45 #define INCL_DOSERRORS 43 46 #define INCL_WINSHELLDATA … … 48 51 #include <string.h> 49 52 #include <math.h> 53 #include <setjmp.h> 50 54 51 55 #include "setup.h" // code generation and debugging options 52 56 57 #include "helpers\except.h" 58 #include "helpers\nls.h" 53 59 #include "helpers\prfh.h" 54 #include "helpers\nls.h" 60 #include "helpers\standards.h" 61 #include "helpers\stringh.h" 62 #include "helpers\tree.h" 63 #include "helpers\xstring.h" 55 64 56 65 #pragma hdrstop … … 495 504 return (ERROR_INVALID_PARAMETER); 496 505 } 506 507 /* ****************************************************************** 508 * 509 * NLS strings 510 * 511 ********************************************************************/ 512 513 static HAB G_hab = NULLHANDLE; 514 static HMODULE G_hmod = NULLHANDLE; 515 static PCSTRINGENTITY G_paEntities = NULL; 516 static ULONG G_cEntities = 0; 517 518 /* 519 *@@ ReplaceEntities: 520 * 521 *@@added V0.9.16 (2001-09-29) [umoeller] 522 */ 523 524 static ULONG ReplaceEntities(PXSTRING pstr) 525 { 526 ULONG ul, 527 rc = 0; 528 529 for (ul = 0; 530 ul < G_cEntities; 531 ul++) 532 { 533 ULONG ulOfs = 0; 534 PCSTRINGENTITY pThis = &G_paEntities[ul]; 535 while (xstrFindReplaceC(pstr, 536 &ulOfs, 537 pThis->pcszEntity, 538 *(pThis->ppcszString))) 539 rc++; 540 } 541 542 return (rc); 543 } 544 545 /* 546 *@@ LoadString: 547 * 548 *@@added V0.9.18 (2002-03-08) [umoeller] 549 */ 550 551 static void LoadString(ULONG ulID, 552 PSZ *ppsz, 553 PULONG pulLength) // out: length of new string (ptr can be NULL) 554 { 555 CHAR szBuf[500]; 556 XSTRING str; 557 558 if (*ppsz) 559 free(*ppsz); 560 561 if (!WinLoadString(G_hab, 562 G_hmod, 563 ulID, 564 sizeof(szBuf), 565 szBuf)) 566 // loading failed: 567 sprintf(szBuf, 568 "LoadString error: string resource %d not found in module 0x%lX", 569 ulID, 570 G_hmod); 571 572 xstrInitCopy(&str, szBuf, 0); 573 ReplaceEntities(&str); 574 *ppsz = str.psz; 575 if (pulLength) 576 *pulLength = str.ulLength; 577 // do not free string 578 } 579 580 static HMTX G_hmtxStringsCache = NULLHANDLE; 581 static TREE *G_StringsCache; 582 static LONG G_cStringsInCache = 0; 583 584 /* 585 *@@ LockStrings: 586 * 587 *@@added V0.9.9 (2001-04-04) [umoeller] 588 */ 589 590 static BOOL LockStrings(VOID) 591 { 592 BOOL brc = FALSE; 593 594 if (G_hmtxStringsCache == NULLHANDLE) 595 { 596 brc = !DosCreateMutexSem(NULL, 597 &G_hmtxStringsCache, 598 0, 599 TRUE); 600 treeInit(&G_StringsCache, 601 &G_cStringsInCache); 602 } 603 else 604 brc = !DosRequestMutexSem(G_hmtxStringsCache, SEM_INDEFINITE_WAIT); 605 606 return (brc); 607 } 608 609 /* 610 *@@ UnlockStrings: 611 * 612 *@@added V0.9.9 (2001-04-04) [umoeller] 613 */ 614 615 static VOID UnlockStrings(VOID) 616 { 617 DosReleaseMutexSem(G_hmtxStringsCache); 618 } 619 620 /* 621 *@@ STRINGTREENODE: 622 * internal string node structure for cmnGetString. 623 * 624 *@@added V0.9.9 (2001-04-04) [umoeller] 625 *@@changed V0.9.16 (2002-01-26) [umoeller]: no longer using malloc() for string 626 */ 627 628 typedef struct _STRINGTREENODE 629 { 630 TREE Tree; // tree node (src\helpers\tree.c) 631 CHAR szLoaded[1]; // string that was loaded; 632 // the struct is dynamic in size now 633 // V0.9.16 (2002-01-26) [umoeller] 634 } STRINGTREENODE, *PSTRINGTREENODE; 635 636 /* 637 *@@ nlsInitStrings: 638 * initializes the NLS strings cache. Call this 639 * before calling nlsGetString for the first time. 640 * 641 *@@added V0.9.18 (2002-03-08) [umoeller] 642 */ 643 644 VOID nlsInitStrings(HAB hab, // in: anchor block 645 HMODULE hmod, // in: module handle to load strings from 646 PCSTRINGENTITY paEntities, // in: entities array or NULL 647 ULONG cEntities) // in: array item count of paEntities or 0 648 { 649 G_hab = hab; 650 G_hmod = hmod; 651 G_paEntities = paEntities; 652 G_cEntities = cEntities; 653 } 654 655 /* 656 *@@ nlsGetString: 657 * returns a resource NLS string. 658 * 659 * Before calling this for the first time, initialize 660 * the engine with nlsInitStrings. 661 * 662 * After that, this function implements a fast string 663 * cache for various NLS strings. Compared to the 664 * standard method, this has the following advantages: 665 * 666 * -- Memory is only consumed for strings that are actually 667 * used. The NLSSTRINGS array had become terribly big, 668 * and lots of strings were loaded that were never used. 669 * 670 * -- Program startup should be a bit faster because we don't 671 * have to load a thousand strings at startup. 672 * 673 * -- The memory buffer holding the string is probably close 674 * to the rest of the heap data that the caller allocated, 675 * so this might lead to less memory page fragmentation. 676 * 677 * -- To add a new NLS string, before this mechanism existed, 678 * three files had to be changed (and kept in sync): common.h 679 * to add a field to the NLSSTRINGS structure, dlgids.h to 680 * add the string ID, and xfldrXXX.rc to add the resource. 681 * With the new mechanism, there's no need to change common.h 682 * any more, so the danger of forgetting something is a bit 683 * reduced. Anyway, fewer recompiles are needed (maybe), 684 * and sending in patches to the code is a bit easier. 685 * 686 * On input, specify a string resouce ID that exists 687 * in the hmod that was given to nlsInitStrings. 688 * 689 * The way this works is that the function maintains a 690 * fast cache of string IDs and only loads the string 691 * resources on demand from the given NLS DLL. If a 692 * string ID is queried for the first time, the string 693 * is loaded. Otherwise the cached copy is returned. 694 * 695 * There is a slight overhead to this function compared to 696 * simply getting a static string from an array, because 697 * the cache needs to be searched for the string ID. However, 698 * this uses a binary tree (balanced according to string IDs) 699 * internally, so this is quite fast still. 700 * 701 * This never releases the strings again. 702 * 703 * This never returns NULL. Even if loading the string failed, 704 * a string is returned; in that case, it's a meaningful error 705 * message specifying the ID that failed. 706 * 707 *@@added V0.9.9 (2001-04-04) [umoeller] 708 *@@changed V0.9.16 (2001-10-19) [umoeller]: fixed bad string count which was never set 709 *@@changed V0.9.16 (2002-01-26) [umoeller]: optimized heap locality 710 */ 711 712 PCSZ nlsGetString(ULONG ulStringID) 713 { 714 BOOL fLocked = FALSE; 715 PSZ pszReturn = "Error"; 716 717 TRY_LOUD(excpt1) 718 { 719 if (fLocked = LockStrings()) 720 { 721 PSTRINGTREENODE pNode; 722 723 if (pNode = (PSTRINGTREENODE)treeFind(G_StringsCache, 724 ulStringID, 725 treeCompareKeys)) 726 // already loaded: 727 pszReturn = pNode->szLoaded; 728 else 729 { 730 // not loaded: load now 731 PSZ psz = NULL; 732 ULONG ulLength = 0; 733 734 LoadString(ulStringID, 735 &psz, 736 &ulLength); 737 738 if ( (!psz) 739 || (!(pNode = (PSTRINGTREENODE)malloc( sizeof(STRINGTREENODE) 740 // has one byte for null 741 // terminator already 742 + ulLength))) 743 ) 744 pszReturn = "malloc() failed."; 745 else 746 { 747 pNode->Tree.ulKey = ulStringID; 748 memcpy(pNode->szLoaded, 749 psz, 750 ulLength + 1); 751 treeInsert(&G_StringsCache, 752 &G_cStringsInCache, // fixed V0.9.16 (2001-10-19) [umoeller] 753 (TREE*)pNode, 754 treeCompareKeys); 755 pszReturn = pNode->szLoaded; 756 } 757 758 if (psz) 759 free(psz); 760 } 761 } 762 else 763 // we must always return a string, never NULL 764 pszReturn = "Cannot get strings lock."; 765 } 766 CATCH(excpt1) {} END_CATCH(); 767 768 if (fLocked) 769 UnlockStrings(); 770 771 return (pszReturn); 772 } 773
Note:
See TracChangeset
for help on using the changeset viewer.