Changeset 174
- Timestamp:
- Jun 14, 2002, 2:20:11 PM (23 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/helpers/linklist.h
r147 r174 33 33 #endif 34 34 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] 49 37 50 38 /* LISTITEM was used before V0.9.0 */ -
trunk/include/helpers/nls.h
r147 r174 32 32 #define NLS_HEADER_INCLUDED 33 33 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] 39 36 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 ********************************************************************/ 61 42 62 VOID XWPENTRY nlsQueryCountrySettings(PCOUNTRYSETTINGS pcs); 43 #define TYPE_SBCS 0x0000 44 #define TYPE_DBCS_1ST 0x0001 45 #define TYPE_DBCS_2ND 0x0002 63 46 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); 67 48 68 PSZ XWPENTRY nlsThousandsDouble(PSZ pszTarget, double dbl, CHAR cThousands); 49 ULONG XWPENTRY nlsQueryDBCSChar(PCSZ pcszString, 50 ULONG ulOfs); 69 51 70 PSZ XWPENTRY nlsVariableDouble(PSZ pszTarget, double dbl, PSZ pszUnits, 71 CHAR cThousands); 52 PSZ XWPENTRY nlschr(PCSZ p, char c); 72 53 73 VOID XWPENTRY nlsFileDate(PSZ pszBuf, 74 FDATE *pfDate, 75 ULONG ulDateFormat, 76 CHAR cDateSep); 54 PSZ XWPENTRY nlsrchr(PCSZ p, char c); 77 55 78 VOID XWPENTRY nlsFileTime(PSZ pszBuf, 79 FTIME *pfTime, 80 ULONG ulTimeFormat, 81 CHAR cTimeSep); 56 /* ****************************************************************** 57 * 58 * Country-dependent formatting 59 * 60 ********************************************************************/ 82 61 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 98 63 99 APIRET XWPENTRY nlsUpper(PSZ psz, ULONG ulLength); 64 /* 65 *@@ COUNTRYSETTINGS: 66 * structure used for returning country settings 67 * with nlsQueryCountrySettings. 68 */ 100 69 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; 106 91 107 typedef struct _STRINGENTITY 108 { 109 PCSZ pcszEntity; 110 PCSZ *ppcszString; 111 } STRINGENTITY, *PSTRINGENTITY; 92 VOID XWPENTRY nlsQueryCountrySettings(PCOUNTRYSETTINGS pcs); 112 93 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; 114 97 115 VOID nlsInitStrings(HAB hab, 116 HMODULE hmod, 117 PCSTRINGENTITY paEntities, 118 ULONG cEntities); 98 PSZ XWPENTRY nlsThousandsDouble(PSZ pszTarget, double dbl, CHAR cThousands); 119 99 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 121 134 122 135 #endif -
trunk/include/helpers/tree.h
r113 r174 13 13 #define XWPTREE_INCLUDED 14 14 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] 28 17 29 18 typedef enum { BLACK, RED } nodeColor; -
trunk/src/helpers/helpers_pre.in
r155 r174 64 64 $(OUTPUTDIR)\level.obj \ 65 65 $(OUTPUTDIR)\nls.obj \ 66 $(OUTPUTDIR)\nlscache.obj \ 66 67 $(OUTPUTDIR)\procstat.obj \ 67 68 $(OUTPUTDIR)\prfh.obj \ -
trunk/src/helpers/math.c
r88 r174 67 67 68 68 } 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 that74 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 efficiently76 implemented as shift-left 1 and shift-right 1 resp.77 78 Found at http://remus.rutgers.edu/~rhoads/Code/int_gcd.c79 */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); */106 69 107 70 /* … … 393 356 } 394 357 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 40 40 41 41 #define INCL_DOSNLS 42 #define INCL_DOSSEMAPHORES 43 #define INCL_DOSEXCEPTIONS 44 #define INCL_DOSPROCESS 42 #define INCL_DOSDATETIME 45 43 #define INCL_DOSERRORS 46 44 #define INCL_WINSHELLDATA … … 51 49 #include <string.h> 52 50 #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 55 55 #include "setup.h" // code generation and debugging options 56 56 57 #include "helpers\except.h"58 57 #include "helpers\nls.h" 59 58 #include "helpers\prfh.h" 60 59 #include "helpers\standards.h" 61 #include "helpers\stringh.h"62 #include "helpers\tree.h"63 #include "helpers\xstring.h"64 60 65 61 #pragma hdrstop … … 69 65 * See nls.c. 70 66 */ 67 68 /* ****************************************************************** 69 * 70 * DBCS support 71 * 72 ********************************************************************/ 73 74 #define MAX_LEADBYTE 256 75 76 #pragma pack(1) 77 78 typedef struct _DBCSVECTOR 79 { 80 BYTE bLow; 81 BYTE bHigh; 82 } DBCSVECTOR; 83 84 #pragma pack() 85 86 BOOL G_afLeadByte[MAX_LEADBYTE] = {0}; 87 ULONG G_fDBCS = -1; // not queried yet 88 COUNTRYCODE G_cc = { 0, 0 }; 89 DBCSVECTOR 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 98 BOOL 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 157 ULONG 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 194 PSZ 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 236 PSZ 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 ********************************************************************/ 71 275 72 276 /* … … 505 709 } 506 710 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 104 104 memcpy(*ppszTarget, pcszSource, ulLength + 1); 105 105 else 106 return (ERROR_NOT_ENOUGH_MEMORY);106 return ERROR_NOT_ENOUGH_MEMORY; 107 107 } 108 108 else … … 149 149 memcpy(*ppszTarget, pcszSource, ulLength + 1); 150 150 else 151 return (ERROR_NOT_ENOUGH_MEMORY);151 return ERROR_NOT_ENOUGH_MEMORY; 152 152 } 153 153 else … … 155 155 } 156 156 else 157 return (ERROR_INVALID_PARAMETER);157 return ERROR_INVALID_PARAMETER; 158 158 159 159 if (pulLength) … … 174 174 { 175 175 if (string2) 176 return (strcpy(string1, string2));176 return strcpy(string1, string2); 177 177 178 178 *string1 = '\0'; 179 return (string1);179 return string1; 180 180 } 181 181 … … 212 212 *pulLength = ulLength; 213 213 214 return (pszReturn);214 return pszReturn; 215 215 } 216 216 … … 244 244 *pulLength = ulLength; 245 245 246 return (pszReturn);246 return pszReturn; 247 247 } 248 248 … … 266 266 { 267 267 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; 270 270 } 271 271 else if (p1) 272 272 // but p2 is NULL: p1 greater than p2 then 273 return (+1);273 return +1; 274 274 else if (p2) 275 275 // but p1 is NULL: p1 less than p2 then 276 return (-1);276 return -1; 277 277 278 278 // return 0 if strcmp returned 0 above or both strings are NULL 279 return (0);279 return 0; 280 280 } 281 281 … … 293 293 { 294 294 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; 297 297 } 298 298 else if (p1) 299 299 // but p2 is NULL: p1 greater than p2 then 300 return (+1);300 return +1; 301 301 else if (p2) 302 302 // but p1 is NULL: p1 less than p2 then 303 return (-1);303 return -1; 304 304 305 305 // return 0 if strcmp returned 0 above or both strings are NULL 306 return (0);306 return 0; 307 307 } 308 308 … … 342 342 free(pszSrchIn); 343 343 } 344 return (prc); 344 345 return prc; 345 346 } 346 347 … … 371 372 *pTarget = 0; 372 373 373 return (ul);374 return ul; 374 375 } 375 376 … … 385 386 { 386 387 if (pcsz) 387 return (strlen(pcsz));388 return strlen(pcsz); 388 389 389 390 return 0; … … 408 409 return (strlen(pcsz) + 1); 409 410 410 return (0);411 return 0; 411 412 } 412 413 … … 432 433 break; 433 434 } 434 return (ulCount);435 return ulCount; 435 436 } 436 437 … … 446 447 { 447 448 if (isdigit(*p) == 0) 448 return (FALSE);449 return FALSE; 449 450 p++; 450 451 } 451 452 452 return (TRUE);453 return TRUE; 453 454 } 454 455 … … 484 485 } 485 486 486 return (pszSubstr);487 return pszSubstr; 487 488 } 488 489 … … 522 523 } 523 524 524 return (pszSubstr);525 return pszSubstr; 525 526 } 526 527 … … 619 620 } 620 621 621 return (pszReturn);622 return pszReturn; 622 623 } 623 624 … … 651 652 } 652 653 653 return (pszReturn);654 return pszReturn; 654 655 } 655 656 … … 690 691 } 691 692 } 692 return (ulrc);693 return ulrc; 693 694 } 694 695 … … 742 743 } 743 744 744 return (pszNew);745 return pszNew; 745 746 } 746 747 … … 785 786 *ppszBuf = xstrBuf.psz; 786 787 787 return (ulrc);788 return ulrc; 788 789 } 789 790 … … 809 810 ulWords++; 810 811 } 811 return (ulWords);812 return ulWords; 812 813 } 813 814 … … 874 875 *ppszStart = pStart; 875 876 *ppszEnd = pEndOfWord; 876 return (TRUE);877 } 878 } 879 880 return (FALSE);877 return TRUE; 878 } 879 } 880 881 return FALSE; 881 882 } 882 883 … … 995 996 996 997 } 997 return (pszReturn);998 return pszReturn; 998 999 } 999 1000 … … 1049 1050 if (pulOffset) 1050 1051 *pulOffset = pNextLine - pszSearchIn; 1051 return (pNextLine);1052 return pNextLine; 1052 1053 } 1053 1054 … … 1080 1081 p++; 1081 1082 1082 return (rc);1083 return rc; 1083 1084 } 1084 1085 … … 1143 1144 } 1144 1145 1145 return (prc);1146 return prc; 1146 1147 } 1147 1148 … … 1196 1197 pszSearchIn2++; 1197 1198 } 1198 return (prc);1199 return prc; 1199 1200 } */ 1200 1201 … … 1231 1232 } 1232 1233 1233 return (pParam);1234 return pParam; 1234 1235 } 1235 1236 … … 1314 1315 } 1315 1316 } 1316 return (prc);1317 return prc; 1317 1318 } 1318 1319 … … 1362 1363 } 1363 1364 1364 return (prc);1365 return prc; 1365 1366 } 1366 1367 … … 1548 1549 } 1549 1550 1550 return (ulrc);1551 return ulrc; 1551 1552 } 1552 1553 … … 1705 1706 pszReturn = strReturn.psz; 1706 1707 1707 return (pszReturn);1708 return pszReturn; 1708 1709 } 1709 1710
Note:
See TracChangeset
for help on using the changeset viewer.