source: branches/branch-1-0/src/helpers/nlscache.c@ 365

Last change on this file since 365 was 297, checked in by pr, 20 years ago

Update functions using exception handlers to force non-register variables

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 10.5 KB
Line 
1
2/*
3 *@@sourcefile nlscache.c:
4 *
5 * Usage: All OS/2 programs.
6 *
7 * Function prefixes (new with V0.81):
8 * -- stc*
9 *
10 * This file is new with V0.9.19, but contains functions
11 * formerly in nls.c.
12 *
13 * Note: Version numbering in this file relates to XWorkplace version
14 * numbering.
15 *
16 *@@header "helpers\nlscache.h"
17 *@@added V0.9.19 (2002-06-13) [umoeller]
18 */
19
20/*
21 * Copyright (C) 2001-2005 Ulrich M”ller.
22 * This file is part of the "XWorkplace helpers" source package.
23 * This is free software; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published
25 * by the Free Software Foundation, in version 2 as it comes in the
26 * "COPYING" file of the XWorkplace main distribution.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 */
32
33#define OS2EMX_PLAIN_CHAR
34 // this is needed for "os2emx.h"; if this is defined,
35 // emx will define PSZ as _signed_ char, otherwise
36 // as unsigned char
37
38#define INCL_DOSNLS
39#define INCL_DOSDATETIME
40#define INCL_DOSSEMAPHORES
41#define INCL_DOSEXCEPTIONS
42#define INCL_DOSPROCESS
43#define INCL_DOSERRORS
44#define INCL_WINSHELLDATA
45#include <os2.h>
46
47#include <stdlib.h>
48#include <stdio.h>
49#include <string.h>
50#include <math.h>
51#include <setjmp.h>
52
53// XWP's setup.h replaces strchr and the like, and
54// we want the originals in here
55#define DONT_REPLACE_FOR_DBCS
56#include "setup.h" // code generation and debugging options
57
58#include "helpers\except.h"
59#include "helpers\nls.h"
60#include "helpers\nlscache.h"
61#include "helpers\prfh.h"
62#include "helpers\standards.h"
63#include "helpers\stringh.h"
64#include "helpers\tree.h"
65#include "helpers\xstring.h"
66
67#pragma hdrstop
68
69/*
70 *@@category: Helpers\National Language Support\String cache
71 * See nls.c.
72 */
73
74/* ******************************************************************
75 *
76 * NLS string cache
77 *
78 ********************************************************************/
79
80static HAB G_hab = NULLHANDLE;
81static HMODULE G_hmod = NULLHANDLE;
82static PCSTRINGENTITY G_paEntities = NULL;
83static ULONG G_cEntities = 0;
84
85/*
86 *@@ ReplaceEntities:
87 *
88 *@@added V0.9.16 (2001-09-29) [umoeller]
89 */
90
91STATIC ULONG ReplaceEntities(PXSTRING pstr)
92{
93 ULONG ul,
94 rc = 0;
95
96 for (ul = 0;
97 ul < G_cEntities;
98 ul++)
99 {
100 ULONG ulOfs = 0;
101 PCSTRINGENTITY pThis = &G_paEntities[ul];
102 while (xstrFindReplaceC(pstr,
103 &ulOfs,
104 pThis->pcszEntity,
105 *(pThis->ppcszString)))
106 rc++;
107 }
108
109 return (rc);
110}
111
112/*
113 *@@ LoadString:
114 *
115 *@@added V0.9.18 (2002-03-08) [umoeller]
116 */
117
118STATIC void LoadString(ULONG ulID,
119 PSZ *ppsz,
120 PULONG pulLength) // out: length of new string (ptr can be NULL)
121{
122 CHAR szBuf[500];
123 XSTRING str;
124
125 if (*ppsz)
126 free(*ppsz);
127
128 if (!WinLoadString(G_hab,
129 G_hmod,
130 ulID,
131 sizeof(szBuf),
132 szBuf))
133 // loading failed:
134 sprintf(szBuf,
135 "LoadString error: string resource %d not found in module 0x%lX",
136 ulID,
137 G_hmod);
138
139 xstrInitCopy(&str, szBuf, 0);
140 ReplaceEntities(&str);
141 *ppsz = str.psz;
142 if (pulLength)
143 *pulLength = str.ulLength;
144 // do not free string
145}
146
147STATIC HMTX G_hmtxStringsCache = NULLHANDLE;
148STATIC TREE *G_StringsCache;
149STATIC LONG G_cStringsInCache = 0;
150
151/*
152 *@@ LockStrings:
153 *
154 *@@added V0.9.9 (2001-04-04) [umoeller]
155 */
156
157STATIC BOOL LockStrings(VOID)
158{
159 BOOL brc = FALSE;
160
161 if (G_hmtxStringsCache == NULLHANDLE)
162 {
163 brc = !DosCreateMutexSem(NULL,
164 &G_hmtxStringsCache,
165 0,
166 TRUE);
167 treeInit(&G_StringsCache,
168 &G_cStringsInCache);
169 }
170 else
171 brc = !DosRequestMutexSem(G_hmtxStringsCache, SEM_INDEFINITE_WAIT);
172
173 return brc;
174}
175
176/*
177 *@@ UnlockStrings:
178 *
179 *@@added V0.9.9 (2001-04-04) [umoeller]
180 */
181
182STATIC VOID UnlockStrings(VOID)
183{
184 DosReleaseMutexSem(G_hmtxStringsCache);
185}
186
187/*
188 *@@ STRINGTREENODE:
189 * internal string node structure for cmnGetString.
190 *
191 *@@added V0.9.9 (2001-04-04) [umoeller]
192 *@@changed V0.9.16 (2002-01-26) [umoeller]: no longer using malloc() for string
193 */
194
195typedef struct _STRINGTREENODE
196{
197 TREE Tree; // tree node (src\helpers\tree.c)
198 CHAR szLoaded[1]; // string that was loaded;
199 // the struct is dynamic in size now
200 // V0.9.16 (2002-01-26) [umoeller]
201} STRINGTREENODE, *PSTRINGTREENODE;
202
203/*
204 *@@ nlsInitStrings:
205 * initializes the NLS strings cache. Call this
206 * before calling nlsGetString for the first time.
207 *
208 *@@added V0.9.18 (2002-03-08) [umoeller]
209 */
210
211VOID nlsInitStrings(HAB hab, // in: anchor block
212 HMODULE hmod, // in: module handle to load strings from
213 PCSTRINGENTITY paEntities, // in: entities array or NULL
214 ULONG cEntities) // in: array item count of paEntities or 0
215{
216 G_hab = hab;
217 G_hmod = hmod;
218 G_paEntities = paEntities;
219 G_cEntities = cEntities;
220}
221
222/*
223 *@@ nlsGetString:
224 * returns a resource NLS string.
225 *
226 * Before calling this for the first time, initialize
227 * the engine with nlsInitStrings.
228 *
229 * After that, this function implements a fast string
230 * cache for various NLS strings. Compared to the
231 * standard method, this has the following advantages:
232 *
233 * -- Memory is only consumed for strings that are actually
234 * used. The NLSSTRINGS array had become terribly big,
235 * and lots of strings were loaded that were never used.
236 *
237 * -- Program startup should be a bit faster because we don't
238 * have to load a thousand strings at startup.
239 *
240 * -- The memory buffer holding the string is probably close
241 * to the rest of the heap data that the caller allocated,
242 * so this might lead to less memory page fragmentation.
243 *
244 * -- To add a new NLS string, before this mechanism existed,
245 * three files had to be changed (and kept in sync): common.h
246 * to add a field to the NLSSTRINGS structure, dlgids.h to
247 * add the string ID, and xfldrXXX.rc to add the resource.
248 * With the new mechanism, there's no need to change common.h
249 * any more, so the danger of forgetting something is a bit
250 * reduced. Anyway, fewer recompiles are needed (maybe),
251 * and sending in patches to the code is a bit easier.
252 *
253 * On input, specify a string resouce ID that exists
254 * in the hmod that was given to nlsInitStrings.
255 *
256 * The way this works is that the function maintains a
257 * fast cache of string IDs and only loads the string
258 * resources on demand from the given NLS DLL. If a
259 * string ID is queried for the first time, the string
260 * is loaded. Otherwise the cached copy is returned.
261 *
262 * There is a slight overhead to this function compared to
263 * simply getting a static string from an array, because
264 * the cache needs to be searched for the string ID. However,
265 * this uses a binary tree (balanced according to string IDs)
266 * internally, so this is quite fast still.
267 *
268 * This never releases the strings again.
269 *
270 * This never returns NULL. Even if loading the string failed,
271 * a string is returned; in that case, it's a meaningful error
272 * message specifying the ID that failed.
273 *
274 *@@added V0.9.9 (2001-04-04) [umoeller]
275 *@@changed V0.9.16 (2001-10-19) [umoeller]: fixed bad string count which was never set
276 *@@changed V0.9.16 (2002-01-26) [umoeller]: optimized heap locality
277 */
278
279PCSZ nlsGetString(ULONG ulStringID)
280{
281 volatile BOOL fLocked = FALSE; // XWP V1.0.4 (2005-10-09) [pr]
282 PSZ pszReturn = "Error";
283
284 TRY_LOUD(excpt1)
285 {
286 if (fLocked = LockStrings())
287 {
288 PSTRINGTREENODE pNode;
289
290 if (pNode = (PSTRINGTREENODE)treeFind(G_StringsCache,
291 ulStringID,
292 treeCompareKeys))
293 // already loaded:
294 pszReturn = pNode->szLoaded;
295 else
296 {
297 // not loaded: load now
298 PSZ psz = NULL;
299 ULONG ulLength = 0;
300
301 LoadString(ulStringID,
302 &psz,
303 &ulLength);
304
305 if ( (!psz)
306 || (!(pNode = (PSTRINGTREENODE)malloc( sizeof(STRINGTREENODE)
307 // has one byte for null
308 // terminator already
309 + ulLength)))
310 )
311 pszReturn = "malloc() failed.";
312 else
313 {
314 pNode->Tree.ulKey = ulStringID;
315 memcpy(pNode->szLoaded,
316 psz,
317 ulLength + 1);
318 treeInsert(&G_StringsCache,
319 &G_cStringsInCache, // fixed V0.9.16 (2001-10-19) [umoeller]
320 (TREE*)pNode,
321 treeCompareKeys);
322 pszReturn = pNode->szLoaded;
323 }
324
325 if (psz)
326 free(psz);
327 }
328 }
329 else
330 // we must always return a string, never NULL
331 pszReturn = "Cannot get strings lock.";
332 }
333 CATCH(excpt1)
334 {
335 pszReturn = "Error";
336 }
337 END_CATCH();
338
339 if (fLocked)
340 UnlockStrings();
341
342 return (pszReturn);
343}
344
345
Note: See TracBrowser for help on using the repository browser.