Ignore:
Timestamp:
Mar 16, 2002, 8:53:47 AM (23 years ago)
Author:
umoeller
Message:

Misc updates for Unicode.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/helpers/nls.c

    r142 r147  
    4040
    4141#define INCL_DOSNLS
     42#define INCL_DOSSEMAPHORES
     43#define INCL_DOSEXCEPTIONS
     44#define INCL_DOSPROCESS
    4245#define INCL_DOSERRORS
    4346#define INCL_WINSHELLDATA
     
    4851#include <string.h>
    4952#include <math.h>
     53#include <setjmp.h>
    5054
    5155#include "setup.h"                      // code generation and debugging options
    5256
     57#include "helpers\except.h"
     58#include "helpers\nls.h"
    5359#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"
    5564
    5665#pragma hdrstop
     
    495504    return (ERROR_INVALID_PARAMETER);
    496505}
     506
     507/* ******************************************************************
     508 *
     509 *   NLS strings
     510 *
     511 ********************************************************************/
     512
     513static HAB                 G_hab = NULLHANDLE;
     514static HMODULE             G_hmod = NULLHANDLE;
     515static PCSTRINGENTITY      G_paEntities = NULL;
     516static ULONG               G_cEntities = 0;
     517
     518/*
     519 *@@ ReplaceEntities:
     520 *
     521 *@@added V0.9.16 (2001-09-29) [umoeller]
     522 */
     523
     524static 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
     551static 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
     580static HMTX        G_hmtxStringsCache = NULLHANDLE;
     581static TREE        *G_StringsCache;
     582static LONG        G_cStringsInCache = 0;
     583
     584/*
     585 *@@ LockStrings:
     586 *
     587 *@@added V0.9.9 (2001-04-04) [umoeller]
     588 */
     589
     590static 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
     615static 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
     628typedef 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
     644VOID 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
     712PCSZ 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.