Changeset 174


Ignore:
Timestamp:
Jun 14, 2002, 2:20:11 PM (23 years ago)
Author:
umoeller
Message:

Misc updates.

Location:
trunk
Files:
3 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/helpers/linklist.h

    r147 r174  
    3333    #endif
    3434
    35     // define some basic things to make this work even with standard C
    36     #if (!defined OS2_INCLUDED) && (!defined _OS2_H) && (!defined __SIMPLES_DEFINED)   // changed V0.9.0 (99-10-22) [umoeller]
    37         typedef unsigned long BOOL;
    38         typedef unsigned long ULONG;
    39         typedef unsigned char *PSZ;
    40         #define TRUE (BOOL)1
    41         #define FALSE (BOOL)0
    42 
    43         #ifdef __IBMCPP__               // added V0.9.0 (99-10-22) [umoeller]
    44             #define APIENTRY _System
    45         #endif
    46 
    47         #define __SIMPLES_DEFINED
    48     #endif
     35    #include "helpers\simples.h"
     36            // V0.9.19 (2002-06-13) [umoeller]
    4937
    5038    /* LISTITEM was used before V0.9.0 */
  • trunk/include/helpers/nls.h

    r147 r174  
    3232    #define NLS_HEADER_INCLUDED
    3333
    34     /*
    35      *@@ COUNTRYSETTINGS:
    36      *      structure used for returning country settings
    37      *      with nlsQueryCountrySettings.
    38      */
     34    #include "helpers\simples.h"
     35            // V0.9.19 (2002-06-13) [umoeller]
    3936
    40     typedef struct _COUNTRYSETTINGS
    41     {
    42         ULONG   ulDateFormat,
    43                         // date format:
    44                         // --  0   mm.dd.yyyy  (English)
    45                         // --  1   dd.mm.yyyy  (e.g. German)
    46                         // --  2   yyyy.mm.dd  (Japanese)
    47                         // --  3   yyyy.dd.mm
    48                 ulTimeFormat;
    49                         // time format:
    50                         // --  0   12-hour clock
    51                         // --  >0  24-hour clock
    52         CHAR    cDateSep,
    53                         // date separator (e.g. '/')
    54                 cTimeSep,
    55                         // time separator (e.g. ':')
    56                 cDecimal,
    57                         // decimal separator (e.g. '.')
    58                 cThousands;
    59                         // thousands separator (e.g. ',')
    60     } COUNTRYSETTINGS, *PCOUNTRYSETTINGS;
     37    /* ******************************************************************
     38     *
     39     *   DBCS support
     40     *
     41     ********************************************************************/
    6142
    62     VOID XWPENTRY nlsQueryCountrySettings(PCOUNTRYSETTINGS pcs);
     43    #define TYPE_SBCS           0x0000
     44    #define TYPE_DBCS_1ST       0x0001
     45    #define TYPE_DBCS_2ND       0x0002
    6346
    64     PSZ XWPENTRY nlsThousandsULong(PSZ pszTarget, ULONG ul, CHAR cThousands);
    65     typedef PSZ XWPENTRY NLSTHOUSANDSULONG(PSZ pszTarget, ULONG ul, CHAR cThousands);
    66     typedef NLSTHOUSANDSULONG *PNLSTHOUSANDSULONG;
     47    BOOL XWPENTRY nlsDBCS(VOID);
    6748
    68     PSZ XWPENTRY nlsThousandsDouble(PSZ pszTarget, double dbl, CHAR cThousands);
     49    ULONG XWPENTRY nlsQueryDBCSChar(PCSZ pcszString,
     50                                    ULONG ulOfs);
    6951
    70     PSZ XWPENTRY nlsVariableDouble(PSZ pszTarget, double dbl, PSZ pszUnits,
    71                            CHAR cThousands);
     52    PSZ XWPENTRY nlschr(PCSZ p, char c);
    7253
    73     VOID XWPENTRY nlsFileDate(PSZ pszBuf,
    74                       FDATE *pfDate,
    75                       ULONG ulDateFormat,
    76                       CHAR cDateSep);
     54    PSZ XWPENTRY nlsrchr(PCSZ p, char c);
    7755
    78     VOID XWPENTRY nlsFileTime(PSZ pszBuf,
    79                       FTIME *pfTime,
    80                       ULONG ulTimeFormat,
    81                       CHAR cTimeSep);
     56    /* ******************************************************************
     57     *
     58     *   Country-dependent formatting
     59     *
     60     ********************************************************************/
    8261
    83     VOID XWPENTRY nlsDateTime(PSZ pszDate,
    84                                PSZ pszTime,
    85                                DATETIME *pDateTime,
    86                                ULONG ulDateFormat,
    87                                CHAR cDateSep,
    88                                ULONG ulTimeFormat,
    89                                CHAR cTimeSep);
    90     typedef VOID XWPENTRY NLSDATETIME(PSZ pszDate,
    91                                PSZ pszTime,
    92                                DATETIME *pDateTime,
    93                                ULONG ulDateFormat,
    94                                CHAR cDateSep,
    95                                ULONG ulTimeFormat,
    96                                CHAR cTimeSep);
    97     typedef NLSDATETIME *PNLSDATETIME;
     62    #ifdef OS2_INCLUDED
    9863
    99     APIRET XWPENTRY nlsUpper(PSZ psz, ULONG ulLength);
     64        /*
     65         *@@ COUNTRYSETTINGS:
     66         *      structure used for returning country settings
     67         *      with nlsQueryCountrySettings.
     68         */
    10069
    101     /*
    102      *@@ STRINGENTITY:
    103      *
    104      *@@added V0.9.16 (2001-09-29) [umoeller]
    105      */
     70        typedef struct _COUNTRYSETTINGS
     71        {
     72            ULONG   ulDateFormat,
     73                            // date format:
     74                            // --  0   mm.dd.yyyy  (English)
     75                            // --  1   dd.mm.yyyy  (e.g. German)
     76                            // --  2   yyyy.mm.dd  (Japanese)
     77                            // --  3   yyyy.dd.mm
     78                    ulTimeFormat;
     79                            // time format:
     80                            // --  0   12-hour clock
     81                            // --  >0  24-hour clock
     82            CHAR    cDateSep,
     83                            // date separator (e.g. '/')
     84                    cTimeSep,
     85                            // time separator (e.g. ':')
     86                    cDecimal,
     87                            // decimal separator (e.g. '.')
     88                    cThousands;
     89                            // thousands separator (e.g. ',')
     90        } COUNTRYSETTINGS, *PCOUNTRYSETTINGS;
    10691
    107     typedef struct _STRINGENTITY
    108     {
    109         PCSZ    pcszEntity;
    110         PCSZ    *ppcszString;
    111     } STRINGENTITY, *PSTRINGENTITY;
     92        VOID XWPENTRY nlsQueryCountrySettings(PCOUNTRYSETTINGS pcs);
    11293
    113     typedef const struct _STRINGENTITY *PCSTRINGENTITY;
     94        PSZ XWPENTRY nlsThousandsULong(PSZ pszTarget, ULONG ul, CHAR cThousands);
     95        typedef PSZ XWPENTRY NLSTHOUSANDSULONG(PSZ pszTarget, ULONG ul, CHAR cThousands);
     96        typedef NLSTHOUSANDSULONG *PNLSTHOUSANDSULONG;
    11497
    115     VOID nlsInitStrings(HAB hab,
    116                         HMODULE hmod,
    117                         PCSTRINGENTITY paEntities,
    118                         ULONG cEntities);
     98        PSZ XWPENTRY nlsThousandsDouble(PSZ pszTarget, double dbl, CHAR cThousands);
    11999
    120     PCSZ nlsGetString(ULONG ulStringID);
     100        PSZ XWPENTRY nlsVariableDouble(PSZ pszTarget,
     101                                       double dbl,
     102                                       PSZ pszUnits,
     103                                       CHAR cThousands);
     104
     105        VOID XWPENTRY nlsFileDate(PSZ pszBuf,
     106                                  FDATE *pfDate,
     107                                  ULONG ulDateFormat,
     108                                  CHAR cDateSep);
     109
     110        VOID XWPENTRY nlsFileTime(PSZ pszBuf,
     111                                  FTIME *pfTime,
     112                                  ULONG ulTimeFormat,
     113                                  CHAR cTimeSep);
     114
     115        VOID XWPENTRY nlsDateTime(PSZ pszDate,
     116                                  PSZ pszTime,
     117                                  DATETIME *pDateTime,
     118                                  ULONG ulDateFormat,
     119                                  CHAR cDateSep,
     120                                  ULONG ulTimeFormat,
     121                                  CHAR cTimeSep);
     122        typedef VOID XWPENTRY NLSDATETIME(PSZ pszDate,
     123                                          PSZ pszTime,
     124                                          DATETIME *pDateTime,
     125                                          ULONG ulDateFormat,
     126                                          CHAR cDateSep,
     127                                          ULONG ulTimeFormat,
     128                                          CHAR cTimeSep);
     129        typedef NLSDATETIME *PNLSDATETIME;
     130
     131        APIRET XWPENTRY nlsUpper(PSZ psz, ULONG ulLength);
     132
     133    #endif
    121134
    122135#endif
  • trunk/include/helpers/tree.h

    r113 r174  
    1313    #define XWPTREE_INCLUDED
    1414
    15     #if (!defined OS2_INCLUDED) && (!defined _OS2_H) && (!defined __SIMPLES_DEFINED)   // changed V0.9.0 (99-10-22) [umoeller]
    16         typedef unsigned long BOOL;
    17         typedef unsigned long ULONG;
    18         typedef long *PLONG;
    19         #define TRUE (BOOL)1
    20         #define FALSE (BOOL)0
    21 
    22         #ifdef __IBMCPP__               // added V0.9.0 (99-10-22) [umoeller]
    23             #define APIENTRY _System
    24         #endif
    25 
    26         #define __SIMPLES_DEFINED
    27     #endif
     15    #include "helpers\simples.h"
     16            // V0.9.19 (2002-06-13) [umoeller]
    2817
    2918    typedef enum { BLACK, RED } nodeColor;
  • trunk/src/helpers/helpers_pre.in

    r155 r174  
    6464$(OUTPUTDIR)\level.obj \
    6565$(OUTPUTDIR)\nls.obj \
     66$(OUTPUTDIR)\nlscache.obj \
    6667$(OUTPUTDIR)\procstat.obj \
    6768$(OUTPUTDIR)\prfh.obj \
  • trunk/src/helpers/math.c

    r88 r174  
    6767
    6868}
    69 
    70 /* binary GCD alg. Based on following facts.
    71    If N and M are even, then gcd(N,M) = 2 * gcd (N/2, M/2)
    72    If N even and M odd, then gcd(N,M) = gcd(N/2, M)
    73    If N,M odd, then |N-M|<max(N,M) thus guaranteeing that
    74              we can use gcd(N,M) = gcd(N-M,M) to reduce.
    75    fact: a&1 is 1 iff a is odd. Mult. and Div. by 2 more efficiently
    76    implemented as shift-left 1 and shift-right 1 resp.
    77 
    78     Found at http://remus.rutgers.edu/~rhoads/Code/int_gcd.c
    79 */
    80 
    81 /* long gcd( long a, long b)
    82 {
    83   int t;
    84 
    85   if (a < 0) a = -a;
    86   if (!b) return a;
    87   if (b < 0) b = -b;
    88   if (!a) return b;
    89   t = 0;
    90   while (! ((a|b) & 1)) {a >>= 1; b >>= 1; ++t;}
    91   while (! (a&1)) a >>= 1;
    92   while (! (b&1)) b >>= 1;
    93   while (a != b)
    94      {
    95      if (a > b)
    96          {
    97          a -= b;
    98          do {a >>= 1;} while (! (a&1));
    99          }
    100      else {
    101          b -= a;
    102          do {b >>= 1;} while (! (b&1));
    103          }
    104      }
    105   return(a<<t); */
    10669
    10770/*
     
    393356}
    394357
    395 /* typedef struct _PRIMEDATA
    396 {
    397     LINKLIST    llPrimes;
    398     int         iCurrentInt;
    399 } PRIMEDATA, *PPRIMEDATA;
    400 
    401 
    402 typedef struct _PRIMEENTRY
    403 {
    404     int         iPrime;
    405     int         iLowestPowerFound;
    406                 // lowest power that was found for this prime number;
    407                 // if 0, a prime was previously present and then not
    408                 // for a later prime
    409     int         iLastInt;
    410 } PRIMEENTRY, *PPRIMEENTRY; */
    411 
    412 /*
    413  *@@ GCDMultiCallbackCreate:
    414  *      first callback for mathGCDMulti.
    415  */
    416 
    417 /* int XWPENTRY GCDMultiCallbackCreate(int n,             // in: prime
    418                                     int p,             // in: power
    419                                     void *pUser)       // in: user param, here root of tree
    420 {
    421     // see if we had this
    422     PPRIMEDATA pData = (PPRIMEDATA)pUser;
    423     PLISTNODE pNode;
    424     PPRIMEENTRY pEntry;
    425     for (pNode = lstQueryFirstNode(&pData->llPrimes);
    426          pNode;
    427          pNode = pNode->pNext)
    428     {
    429         pEntry = (PPRIMEENTRY)pNode->pItemData;
    430         if (pEntry->iPrime == n)
    431         {
    432             // mark this as processed so we can later see
    433             // if the current integer had this prime factor
    434             // at all
    435             pEntry->iLastInt = pData->iCurrentInt;
    436 
    437             // printf(" %d^%d", n, p);
    438 
    439             // and stop
    440             return 0;
    441         }
    442     }
    443 
    444     // no entry for this yet:
    445     // printf(" %d^%d", n, p);
    446     pEntry = NEW(PRIMEENTRY);
    447     pEntry->iPrime = n;
    448     pEntry->iLowestPowerFound = p;
    449     pEntry->iLastInt = pData->iCurrentInt;
    450     lstAppendItem(&pData->llPrimes, pEntry);
    451 
    452     return (0);
    453 } */
    454 
    455 /*
    456  *@@ GCDMultiCallbackLowest:
    457  *      second callback for mathGCDMulti.
    458  */
    459 
    460 /* int XWPENTRY GCDMultiCallbackLowest(int n,             // in: prime
    461                                     int p,             // in: power
    462                                     void *pUser)       // in: user param, here root of tree
    463 {
    464     // see if we had this
    465     PPRIMEDATA pData = (PPRIMEDATA)pUser;
    466     PLISTNODE pNode;
    467     PPRIMEENTRY pEntry;
    468     for (pNode = lstQueryFirstNode(&pData->llPrimes);
    469          pNode;
    470          pNode = pNode->pNext)
    471     {
    472         pEntry = (PPRIMEENTRY)pNode->pItemData;
    473         if (pEntry->iPrime == n)
    474         {
    475             if (p < pEntry->iLowestPowerFound)
    476             {
    477                 pEntry->iLowestPowerFound = p;
    478                 // printf(" %d^%d", n, p);
    479             }
    480             pEntry->iLastInt = pData->iCurrentInt;
    481 
    482             // and stop
    483             return 0;
    484         }
    485     }
    486 
    487     exit(1);
    488 
    489     return (0);
    490 } */
    491 
    492 /* int mathGCDMulti(int *paNs,             // in: array of integers
    493                  int cNs)               // in: array item count (NOT array size)
    494 {
    495     int i;
    496     double dGCD;
    497 
    498     PLISTNODE pNode;
    499     PPRIMEENTRY pEntry;
    500 
    501     PRIMEDATA Data;
    502     lstInit(&Data.llPrimes, TRUE);
    503 
    504     // this is done by prime-factoring each frequency
    505     // and then multiplying all primes with the lowest
    506     // common power that we found:
    507 
    508     // Example 1: If we have two timers with freq.
    509     // 1000 and 1500, obviously, the master timer
    510     // should run at 500 ms.
    511 
    512     // With prime factorization, we end up like this:
    513 
    514     // 1000 = 2^3 *       5^3
    515     // 1500 = 2^2 * 3^1 * 5^3
    516 
    517     // so the highest power for factor 2 is 2;
    518     //    the highest power for factor 3 is 0;
    519     //    the highest power for factor 5 is 3;
    520 
    521     // freq = 2^2 *       5^3 = 500
    522 
    523     // Example 2: If we have three timers with freq.
    524     // 1000 and 1500 and 1800:
    525 
    526     // 1000 = 2^3 *       5^3
    527     // 1500 = 2^2 * 3^1 * 5^3
    528     // 1800 = 2^3 * 3^2 * 5^2
    529 
    530     // so the highest power for factor 2 is 2;
    531     //    the highest power for factor 3 is 0;
    532     //    the highest power for factor 5 is 2;
    533 
    534     // freq = 2^2 *     * 5^2 = 100
    535 
    536     // Example 3: If we have four timers with freq.
    537     // 1200 and 1500 and 1800 and 60:
    538 
    539     // 1200 = 2^4 * 3^1 * 5^2
    540     // 1500 = 2^2 * 3^1 * 5^3
    541     // 1800 = 2^3 * 3^2 * 5^2
    542     //   60 = 2^2 * 3^1 * 5^1
    543 
    544     // so the highest power for factor 2 is 2;
    545     //    the highest power for factor 3 is 1;
    546     //    the highest power for factor 5 is 1;
    547 
    548     // freq = 2^2 * 3^1 * 5^1 = 60
    549 
    550     // go thru the ints array to create
    551     // an entry for each prime there is
    552     for (i = 0;
    553          i < cNs;
    554          i++)
    555     {
    556         // printf("\nFactoring %d\n", paNs[i]);
    557         Data.iCurrentInt = paNs[i];
    558         mathFactorPrime(paNs[i],
    559                         GCDMultiCallbackCreate,
    560                         &Data);
    561     }
    562 
    563     // now run this a second time to find the
    564     // lowest prime for each
    565     for (i = 0;
    566          i < cNs;
    567          i++)
    568     {
    569         // printf("\nTouching %d\n", paNs[i]);
    570         Data.iCurrentInt = paNs[i];
    571         mathFactorPrime(paNs[i],
    572                         GCDMultiCallbackLowest,
    573                         &Data);
    574 
    575         // all list items that were just touched
    576         // now have iLastInt set to the current
    577         // integer; so go thru the list and set
    578         // all items which do NOT have that set
    579         // to power 0 because we must not use them
    580         // in factoring
    581         for (pNode = lstQueryFirstNode(&Data.llPrimes);
    582              pNode;
    583              pNode = pNode->pNext)
    584         {
    585             pEntry = (PPRIMEENTRY)pNode->pItemData;
    586             if (pEntry->iLastInt != paNs[i])
    587             {
    588                 pEntry->iLowestPowerFound = 0;
    589                 // printf(" ###%d^%d", pEntry->iPrime, 0);
    590             }
    591         }
    592     }
    593 
    594     // printf("\nNew:\n");
    595 
    596     // now compose the GCD
    597     dGCD = 1;
    598     for (pNode = lstQueryFirstNode(&Data.llPrimes);
    599          pNode;
    600          pNode = pNode->pNext)
    601     {
    602         pEntry = (PPRIMEENTRY)pNode->pItemData;
    603 
    604         // printf(" %d^%d", pEntry->iPrime, pEntry->iLowestPowerFound);
    605 
    606         if (pEntry->iLowestPowerFound)
    607             dGCD *= pow(pEntry->iPrime, pEntry->iLowestPowerFound);
    608     }
    609 
    610     lstClear(&Data.llPrimes);
    611 
    612     return dGCD;
    613 } */
    614 
    615 // testcase
    616 
    617 #ifdef BUILD_MAIN
    618 
    619 #define INCL_DOSMISC
    620 #include <os2.h>
    621 
    622 int callback(int n,
    623              int p,
    624              void *pUser)
    625 {
    626     if (p > 1)
    627         printf("%d^%d ", n, p);
    628     else
    629         printf("%d ", n);
    630     fflush(stdout);
    631 
    632     return (0);
    633 }
    634 
    635 int main (int argc, char *argv[])
    636 {
    637     if (argc > 1)
    638     {
    639         int i,
    640             c,
    641             cInts = argc - 1;
    642         ULONG ulms, ulms2;
    643         int *aInts = malloc(sizeof(int) * cInts);
    644 
    645         for (c = 0;
    646              c < cInts;
    647              c++)
    648         {
    649             aInts[c] = atoi(argv[c + 1]);
    650         }
    651 
    652         DosQuerySysInfo(QSV_MS_COUNT,
    653                         QSV_MS_COUNT,
    654                         &ulms,
    655                         sizeof(ulms));
    656 
    657         c = mathGCDMulti(aInts,
    658                          cInts);
    659 
    660         DosQuerySysInfo(QSV_MS_COUNT,
    661                         QSV_MS_COUNT,
    662                         &ulms2,
    663                         sizeof(ulms2));
    664 
    665         printf("\nGCD is %d, %d ms time.\n",
    666                c,
    667                ulms2 - ulms);
    668 
    669         for (i = 0;
    670              i < cInts;
    671              i++)
    672         {
    673             printf("  %d / %d = %d rem. %d\n",
    674                    aInts[i], c, aInts[i] / c, aInts[i] % c);
    675         }
    676 
    677         /* c = mathFactorBrute(atoi(argv[1]),
    678                             callback,
    679                             0);
    680         printf("\n%d factors found.\n", c); */
    681     }
    682 
    683     return (0);
    684 }
    685 
    686 #endif
     358
  • trunk/src/helpers/nls.c

    r167 r174  
    4040
    4141#define INCL_DOSNLS
    42 #define INCL_DOSSEMAPHORES
    43 #define INCL_DOSEXCEPTIONS
    44 #define INCL_DOSPROCESS
     42#define INCL_DOSDATETIME
    4543#define INCL_DOSERRORS
    4644#define INCL_WINSHELLDATA
     
    5149#include <string.h>
    5250#include <math.h>
    53 #include <setjmp.h>
    54 
     51
     52// XWP's setup.h replaces strchr and the like, and
     53// we want the originals in here
     54#define DONT_REPLACE_FOR_DBCS
    5555#include "setup.h"                      // code generation and debugging options
    5656
    57 #include "helpers\except.h"
    5857#include "helpers\nls.h"
    5958#include "helpers\prfh.h"
    6059#include "helpers\standards.h"
    61 #include "helpers\stringh.h"
    62 #include "helpers\tree.h"
    63 #include "helpers\xstring.h"
    6460
    6561#pragma hdrstop
     
    6965 *      See nls.c.
    7066 */
     67
     68/* ******************************************************************
     69 *
     70 *   DBCS support
     71 *
     72 ********************************************************************/
     73
     74#define MAX_LEADBYTE        256
     75
     76#pragma pack(1)
     77
     78typedef struct _DBCSVECTOR
     79{
     80   BYTE bLow;
     81   BYTE bHigh;
     82} DBCSVECTOR;
     83
     84#pragma pack()
     85
     86BOOL        G_afLeadByte[MAX_LEADBYTE] = {0};
     87ULONG       G_fDBCS = -1;       // not queried yet
     88COUNTRYCODE G_cc = { 0, 0 };
     89DBCSVECTOR  G_aDBCSVector[8];
     90
     91/*
     92 *@@ nlsDBCS:
     93 *      returns TRUE if the system is currently using DBCS.
     94 *
     95 *@@added V0.9.19 (2002-06-13) [umoeller]
     96 */
     97
     98BOOL nlsDBCS(VOID)
     99{
     100    int i;
     101
     102    if (G_fDBCS != -1)
     103        // already queried:
     104        return G_fDBCS;
     105
     106    if (DosQueryDBCSEnv(8 * sizeof(DBCSVECTOR),
     107                        &G_cc,
     108                        (PCHAR)G_aDBCSVector))
     109        // not DBCS:
     110        return (G_fDBCS = FALSE);
     111
     112    for (i = 0;
     113         i < 8;
     114         ++i)
     115    {
     116        if (    (G_aDBCSVector[i].bLow)
     117             && (G_aDBCSVector[i].bHigh)
     118           )
     119        {
     120            int n;
     121            for (n = G_aDBCSVector[i].bLow;
     122                 n <= G_aDBCSVector[i].bHigh;
     123                 ++n)
     124                G_afLeadByte[n] = TRUE;
     125            G_fDBCS = TRUE;
     126        }
     127        else
     128            break;
     129    }
     130
     131    return G_fDBCS;
     132}
     133
     134/*
     135 *@@ nlsQueryDBCSChar:
     136 *      returns the type of the DBCS character with
     137 *      the given index. Note that the index is the
     138 *      DBCS character index, not just the array
     139 *      index into the CHAR array.
     140 *
     141 *      Returns:
     142 *
     143 *      --  TYPE_SBCS: ulOfs is single byte.
     144 *
     145 *      --  TYPE_DBCS_1ST: ulOfs is a double-byte lead char.
     146 *
     147 *      --  TYPE_DBCS_2ND: ulOfs is a double-byte trail char.
     148 *
     149 *      Preconditions:
     150 *
     151 *      --  nlsDBCS must have been called to initialize our
     152 *          globals, and must have returned TRUE.
     153 *
     154 *@@added V0.9.19 (2002-06-13) [umoeller]
     155 */
     156
     157ULONG nlsQueryDBCSChar(PCSZ pcszString,
     158                       ULONG ulOfs)
     159
     160{
     161    ULONG ulDBCSType = TYPE_SBCS;
     162    ULONG i;
     163
     164    for (i = 0;
     165         i <= ulOfs;
     166         ++i)
     167    {
     168        switch (ulDBCSType)
     169        {
     170            case TYPE_SBCS:
     171            case TYPE_DBCS_2ND:
     172                ulDBCSType = G_afLeadByte[pcszString[i]];
     173            break;
     174
     175            case TYPE_DBCS_1ST :
     176                ulDBCSType = TYPE_DBCS_2ND;
     177            break;
     178        }
     179    }
     180
     181    return ulDBCSType;
     182}
     183
     184/*
     185 *@@ nlschr:
     186 *      replacement for strchr with DBCS support.
     187 *
     188 *      If the system is not running with DBCS,
     189 *      this calls plain strchr automatically.
     190 *
     191 *@@added V0.9.19 (2002-06-13) [umoeller]
     192 */
     193
     194PSZ nlschr(PCSZ p, char c)
     195{
     196    PCSZ    p2;
     197    ULONG   ulDBCS;
     198
     199    if (!nlsDBCS())
     200        // not DBCS:
     201        return strchr(p, c);
     202
     203    // we're on DBCS:
     204    for (p2 = p;
     205         *p2;
     206         ++p2)
     207    {
     208        if (*p2 == c)
     209        {
     210            // match: return this only if it's SBCS;
     211            // if it's a DBCS lead char, skip it
     212            switch (ulDBCS = nlsQueryDBCSChar(p, p2 - p))
     213            {
     214                case TYPE_SBCS:
     215                    return (PSZ)p2;
     216
     217                case TYPE_DBCS_1ST:
     218                    ++p2;
     219            }
     220        }
     221    }
     222
     223    return NULL;
     224}
     225
     226/*
     227 *@@ nlsrchr:
     228 *      replacement for strrchr with DBCS support.
     229 *
     230 *      If the system is not running with DBCS,
     231 *      this calls plain strrchr automatically.
     232 *
     233 *@@added V0.9.19 (2002-06-13) [umoeller]
     234 */
     235
     236PSZ nlsrchr(PCSZ p, char c)
     237{
     238    PCSZ    p2;
     239    ULONG   ulDBCS,
     240            ulLength;
     241
     242    if (!nlsDBCS())
     243        // not DBCS:
     244        return strrchr(p, c);
     245
     246    // we're on DBCS:
     247    ulLength = strlen(p);
     248    for (p2 = p + ulLength - 1;
     249         p2 >= p;
     250         --p2)
     251    {
     252        if (*p2 == c)
     253        {
     254            // match: return this only if it's SBCS;
     255            // if it's a DBCS trail char, skip it
     256            switch (ulDBCS = nlsQueryDBCSChar(p, p2 - p))
     257            {
     258                case TYPE_SBCS:
     259                    return (PSZ)p2;
     260
     261                case TYPE_DBCS_2ND:
     262                    --p2;
     263            }
     264        }
     265    }
     266
     267    return NULL;
     268}
     269
     270/* ******************************************************************
     271 *
     272 *   Country-dependent formatting
     273 *
     274 ********************************************************************/
    71275
    72276/*
     
    505709}
    506710
    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 
     711
  • trunk/src/helpers/stringh.c

    r169 r174  
    104104                memcpy(*ppszTarget, pcszSource, ulLength + 1);
    105105            else
    106                 return (ERROR_NOT_ENOUGH_MEMORY);
     106                return ERROR_NOT_ENOUGH_MEMORY;
    107107        }
    108108        else
     
    149149                memcpy(*ppszTarget, pcszSource, ulLength + 1);
    150150            else
    151                 return (ERROR_NOT_ENOUGH_MEMORY);
     151                return ERROR_NOT_ENOUGH_MEMORY;
    152152        }
    153153        else
     
    155155    }
    156156    else
    157         return (ERROR_INVALID_PARAMETER);
     157        return ERROR_INVALID_PARAMETER;
    158158
    159159    if (pulLength)
     
    174174{
    175175    if (string2)
    176         return (strcpy(string1, string2));
     176        return strcpy(string1, string2);
    177177
    178178    *string1 = '\0';
    179     return (string1);
     179    return string1;
    180180}
    181181
     
    212212        *pulLength = ulLength;
    213213
    214     return (pszReturn);
     214    return pszReturn;
    215215}
    216216
     
    244244        *pulLength = ulLength;
    245245
    246     return (pszReturn);
     246    return pszReturn;
    247247}
    248248
     
    266266    {
    267267        int i = strcmp(p1, p2);
    268         if (i < 0) return (-1);
    269         if (i > 0) return (+1);
     268        if (i < 0) return -1;
     269        if (i > 0) return +1;
    270270    }
    271271    else if (p1)
    272272        // but p2 is NULL: p1 greater than p2 then
    273         return (+1);
     273        return +1;
    274274    else if (p2)
    275275        // but p1 is NULL: p1 less than p2 then
    276         return (-1);
     276        return -1;
    277277
    278278    // return 0 if strcmp returned 0 above or both strings are NULL
    279     return (0);
     279    return 0;
    280280}
    281281
     
    293293    {
    294294        int i = stricmp(p1, p2);
    295         if (i < 0) return (-1);
    296         if (i > 0) return (+1);
     295        if (i < 0) return -1;
     296        if (i > 0) return +1;
    297297    }
    298298    else if (p1)
    299299        // but p2 is NULL: p1 greater than p2 then
    300         return (+1);
     300        return +1;
    301301    else if (p2)
    302302        // but p1 is NULL: p1 less than p2 then
    303         return (-1);
     303        return -1;
    304304
    305305    // return 0 if strcmp returned 0 above or both strings are NULL
    306     return (0);
     306    return 0;
    307307}
    308308
     
    342342            free(pszSrchIn);
    343343    }
    344     return (prc);
     344
     345    return prc;
    345346}
    346347
     
    371372    *pTarget = 0;
    372373
    373     return (ul);
     374    return ul;
    374375}
    375376
     
    385386{
    386387    if (pcsz)
    387         return (strlen(pcsz));
     388        return strlen(pcsz);
    388389
    389390    return 0;
     
    408409        return (strlen(pcsz) + 1);
    409410
    410     return (0);
     411    return 0;
    411412}
    412413
     
    432433            break;
    433434    }
    434     return (ulCount);
     435    return ulCount;
    435436}
    436437
     
    446447    {
    447448        if (isdigit(*p) == 0)
    448             return (FALSE);
     449            return FALSE;
    449450        p++;
    450451    }
    451452
    452     return (TRUE);
     453    return TRUE;
    453454}
    454455
     
    484485    }
    485486
    486     return (pszSubstr);
     487    return pszSubstr;
    487488}
    488489
     
    522523    }
    523524
    524     return (pszSubstr);
     525    return pszSubstr;
    525526}
    526527
     
    619620    }
    620621
    621     return (pszReturn);
     622    return pszReturn;
    622623}
    623624
     
    651652    }
    652653
    653     return (pszReturn);
     654    return pszReturn;
    654655}
    655656
     
    690691        }
    691692    }
    692     return (ulrc);
     693    return ulrc;
    693694}
    694695
     
    742743    }
    743744
    744     return (pszNew);
     745    return pszNew;
    745746}
    746747
     
    785786        *ppszBuf = xstrBuf.psz;
    786787
    787     return (ulrc);
     788    return ulrc;
    788789}
    789790
     
    809810                ulWords++;
    810811    }
    811     return (ulWords);
     812    return ulWords;
    812813}
    813814
     
    874875            *ppszStart = pStart;
    875876            *ppszEnd = pEndOfWord;
    876             return (TRUE);
    877         }
    878     }
    879 
    880     return (FALSE);
     877            return TRUE;
     878        }
     879    }
     880
     881    return FALSE;
    881882}
    882883
     
    995996
    996997    }
    997     return (pszReturn);
     998    return pszReturn;
    998999}
    9991000
     
    10491050    if (pulOffset)
    10501051        *pulOffset = pNextLine - pszSearchIn;
    1051     return (pNextLine);
     1052    return pNextLine;
    10521053}
    10531054
     
    10801081            p++;
    10811082
    1082     return (rc);
     1083    return rc;
    10831084}
    10841085
     
    11431144   }
    11441145
    1145    return (prc);
     1146   return prc;
    11461147}
    11471148
     
    11961197        pszSearchIn2++;
    11971198    }
    1198     return (prc);
     1199    return prc;
    11991200} */
    12001201
     
    12311232    }
    12321233
    1233     return (pParam);
     1234    return pParam;
    12341235}
    12351236
     
    13141315        }
    13151316    }
    1316     return (prc);
     1317    return prc;
    13171318}
    13181319
     
    13621363    }
    13631364
    1364     return (prc);
     1365    return prc;
    13651366}
    13661367
     
    15481549    }
    15491550
    1550     return (ulrc);
     1551    return ulrc;
    15511552}
    15521553
     
    17051706        pszReturn = strReturn.psz;
    17061707
    1707     return (pszReturn);
     1708    return pszReturn;
    17081709}
    17091710
Note: See TracChangeset for help on using the changeset viewer.