source: trunk/dll/strutil.c@ 1394

Last change on this file since 1394 was 1394, checked in by Steven Levine, 17 years ago

Ticket 340: Convert GetPString to use STRINGTABLE.

Drop fm3dll.str and mkstr.exe from makefiles and wpi builders

Convert many functions to expect PCSZ arguments.
Correct walk, compare and dirsizes dialog setups to ignore saved dialog size
Drop copyright.c logic from makefile

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.0 KB
Line 
1
2/***********************************************************************
3
4 $Id: strutil.c 1394 2009-02-05 04:17:25Z stevenhl $
5
6 External strings support - stored in STRINGTABLE
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2006, 2009 Steven H. Levine
10
11 22 Jul 06 SHL Comments
12 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
13 05 Jan 08 SHL Rename from string.c to avoid string.h conflict
14 03 Feb 09 SHL Switch to STRINGTABLE and const return
15
16***********************************************************************/
17
18#include <stdio.h>
19#include <share.h>
20#include <string.h>
21
22#define INCL_DOSPROCESS // DosSleep
23
24#include "fm3dll.h"
25#include "fm3str.h"
26#include "init.h" // Data declaration(s)
27#include "mainwnd.h" // FM3ModHandle
28#include "wrappers.h"
29#include "errutil.h"
30#include "strutil.h"
31#include "version.h"
32
33static PSZ pszSrcFile = __FILE__;
34
35//== GetPString() return a readonly pointer to the requested string in memory ==
36
37PCSZ GetPString(ULONG id)
38{
39 PSZ psz;
40 LONG l;
41 CHAR sz[257];
42 ULONG ulNewFirstId;
43 ULONG ulNewLastId;
44
45 static PSZ *pLoadedStrings;
46 static ULONG ulFirstId;
47 static ULONG ulLastId;
48
49 // Strings that must be combined because stringtable items limited to 256
50 static struct LongString {
51 ULONG id;
52 ULONG sub_id;
53 } LongStrings[] = {
54 {IDS_SUGGEST1TEXT, IDS_SUGGEST1TEXT1},
55 {IDS_SUGGEST1TEXT, IDS_SUGGEST1TEXT2},
56 {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT1},
57 {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT2},
58 {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT3},
59 {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT4},
60 {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT5},
61 {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT6},
62 {IDS_ARCHIVERBB2TEXT, IDS_ARCHIVERBB2TEXT7},
63 {IDS_INIBINARYDATASKIPTEXT, IDS_INIBINARYDATASKIPTEXT1},
64 {IDS_INIBINARYDATASKIPTEXT, IDS_INIBINARYDATASKIPTEXT2},
65 {IDS_INSTANTHELPTEXT, IDS_INSTANTHELPTEXT1},
66 {IDS_INSTANTHELPTEXT, IDS_INSTANTHELPTEXT2},
67 {IDS_FSDERRORTEXT, IDS_FSDERRORTEXT1},
68 {IDS_FSDERRORTEXT, IDS_FSDERRORTEXT2},
69 {IDS_LANERRORTEXT, IDS_LANERRORTEXT1},
70 {IDS_LANERRORTEXT, IDS_LANERRORTEXT2},
71 {IDS_MAKESHADOWHELPTEXT, IDS_MAKESHADOWHELPTEXT1},
72 {IDS_MAKESHADOWHELPTEXT, IDS_MAKESHADOWHELPTEXT2},
73 {IDS_UNDELETEHELPTEXT, IDS_UNDELETEHELPTEXT1},
74 {IDS_UNDELETEHELPTEXT, IDS_UNDELETEHELPTEXT2},
75 {IDS_KILLPROCHELPTEXT, IDS_KILLPROCHELPTEXT1},
76 {IDS_KILLPROCHELPTEXT, IDS_KILLPROCHELPTEXT2},
77 {IDS_ARCNOTTHERETEXT, IDS_ARCNOTTHERETEXT1},
78 {IDS_ARCNOTTHERETEXT, IDS_ARCNOTTHERETEXT2},
79 {IDS_FM2CMDHELPTEXT, IDS_FM2CMDHELPTEXT1},
80 {IDS_FM2CMDHELPTEXT, IDS_FM2CMDHELPTEXT2},
81 {IDS_FM2CMDHELPTEXT, IDS_FM2CMDHELPTEXT3}
82 };
83
84 static UINT cLongStrings = sizeof(LongStrings) / sizeof(struct LongString);
85
86 static volatile INT cBusy; // Need to be MT-safe
87 static ULONG ulDbgId; // 13 Jan 09 SHL fixme to be gone?
88 static UINT uDbgState; // 03 Feb 09 SHL fixme to be gone?
89 static ULONG ulDbgTid; // 13 Jan 09 SHL fixme to be gone?
90
91 UINT c;
92 // 23 Jan 09 SHL fixme to use SMP safe inc/dec?
93 extern void SMPSafeInc(void);
94 extern void SMPSafeDec(void);
95 #pragma aux SMPSafeInc = "lock inc cBusy" modify exact [];
96 #pragma aux SMPSafeDec = "lock dec cBusy" modify exact [];
97 // SMPSafeInc();
98 for (c = 0; ; c++) {
99 if (++cBusy == 1)
100 break;
101 cBusy--;
102 // Hold off 1 cycle before reporting since some contention expected
103 if (c == 1)
104 DbgMsg(pszSrcFile, __LINE__, "GetPString(%lu) waiting for tid %lu GetPString(%lu), state=%u", id, ulDbgTid, ulDbgId, uDbgState);
105 DosSleep(1); // Let current owner finish
106 }
107 if (c > 1)
108 DbgMsg(pszSrcFile, __LINE__, "continuing with GetPString(%lu) after tid %lu GetPString(%lu), state=%u", id, ulDbgTid, ulDbgId, uDbgState);
109
110 // Remember id and thread ordinal for diagnosing MT hangs
111 // Use fast DosGetInfoBlocks to ensure debug logic does not change timing
112 {
113 extern PTIB2 GetPTIB2(void);
114 #pragma aux GetPTIB2 = "mov eax,fs:[12]" value [eax];
115 // PIB *ppib;
116 // TIB *ptib;
117 TIB2 *ptib2 = GetPTIB2();
118 // APIRET apiret = DosGetInfoBlocks(&ptib, &ppib);
119 ulDbgId = id;
120 // ulDbgTid = apiret == 0 ? ptib->tib_ptib2->tib2_ultid : 0;
121 ulDbgTid = ptib2->tib2_ultid;
122 }
123
124 // DbgMsg(pszSrcFile, __LINE__, "Fetching %lu", id);
125
126 // If string already loaded, return it now
127 if (id >= ulFirstId &&
128 id <= ulLastId &&
129 pLoadedStrings &&
130 (psz = pLoadedStrings[id - ulFirstId]) != NULL) {
131 cBusy--;
132 if (((ULONG)psz & 0xffff0000) == 0)
133 DbgMsg(pszSrcFile, __LINE__, "id %lu corrupted %p", id, psz);
134 // DbgMsg(pszSrcFile, __LINE__, "id %lu \"%s\"", id, psz ? psz : "(null)");
135 return psz;
136 }
137
138 // Try to load
139 // 11 Jan 09 SHL fixme to use global HAB?
140 uDbgState = 1;
141 l = WinLoadString((HAB)NULL, FM3ModHandle, id, sizeof(sz), sz);
142 uDbgState = 2;
143
144 if (l != 0) {
145 psz = xstrdup(sz, pszSrcFile, __LINE__);
146 if (!psz) {
147 cBusy--;
148 return NullStr;
149 }
150 }
151 else {
152 // Assume string must be built from multiple strings - find first
153 UINT i;
154 psz = NULL;
155 for (i = 0; i < cLongStrings && LongStrings[i].id != id; i++); // Scan
156
157 if (i < cLongStrings) {
158 // Combine stringtable items to build long string
159 // DbgMsg(pszSrcFile, __LINE__, "Building long string %lu", id);
160 for (; LongStrings[i].id == id; i++) {
161 uDbgState = 3;
162 l = WinLoadString((HAB)NULL, FM3ModHandle, LongStrings[i].sub_id, sizeof(sz), sz);
163 uDbgState = 4;
164 if (l == 0) {
165 cBusy--;
166 Runtime_Error(pszSrcFile, __LINE__, "string %lu missing", LongStrings[i].sub_id);
167 xfree(psz, pszSrcFile, __LINE__);
168 return NullStr;
169 }
170 if (!psz) {
171 // Remember 1st string
172 psz = strdup(sz);
173 if (!psz) {
174 cBusy--;
175 return NullStr;
176 }
177 }
178 else {
179 // Append string
180 UINT curLen = strlen(psz);
181 PSZ psz2 = xrealloc(psz, curLen + l + 1, pszSrcFile, __LINE__);
182 if (!psz2) {
183 xfree(psz, pszSrcFile, __LINE__);
184 cBusy--;
185 return NullStr;
186 }
187 memcpy(psz2 + curLen, sz, l); // Append
188 *(psz2 + curLen + l) = 0; // Terminate
189 psz = psz2; // Remember
190 l += curLen;
191 }
192 } // while
193 } // if long
194 } // if loaded
195
196 if (l == 0) {
197 DbgMsg(pszSrcFile, __LINE__, "Error loading %lu", id);
198 sprintf(sz, "** Error loading id %lu **", id);
199 psz = xstrdup(sz, pszSrcFile, __LINE__);
200 if (psz)
201 l = strlen(sz);
202 else
203 psz = NullStr; // Oh heck
204 }
205
206 uDbgState = 5;
207 // Add to cache
208 // DbgMsg(pszSrcFile, __LINE__, "Caching %lu", id);
209
210 // Calculate new array limits
211 if (!pLoadedStrings) {
212 ulNewFirstId = id;
213 ulNewLastId = id;
214 ulFirstId = id;
215 ulLastId = id;
216 }
217 else {
218 ulNewFirstId = id < ulFirstId ? id : ulFirstId;
219 ulNewLastId = id > ulLastId ? id : ulLastId;
220 }
221
222 if (ulNewFirstId != ulFirstId ||
223 ulNewLastId != ulLastId ||
224 !pLoadedStrings) {
225 PSZ *pNewLoadedStrings;
226 // DbgMsg(pszSrcFile, __LINE__, "Reallocating for %lu", id);
227 pNewLoadedStrings = xrealloc(pLoadedStrings,
228 (ulNewLastId - ulNewFirstId + 1) * sizeof(PSZ),
229 pszSrcFile, __LINE__);
230 if (!pNewLoadedStrings) {
231 cBusy--;
232 Runtime_Error(pszSrcFile, __LINE__, "realloc failed");
233 xfree(psz, pszSrcFile, __LINE__);
234 return NullStr;
235 }
236 // Align existing entries and zero fill unused entries as needed
237 if (ulNewFirstId < ulFirstId) {
238 // Move room for new entries at head of array
239 memmove(pNewLoadedStrings + (ulFirstId - ulNewFirstId),
240 pNewLoadedStrings,
241 (ulLastId - ulFirstId + 1) * sizeof(PSZ));
242 // Null unused placeholder entries
243 if (ulFirstId - ulNewFirstId > 1)
244 memset(pNewLoadedStrings + 1, 0, (ulFirstId - ulNewFirstId - 1) * sizeof(PSZ));
245 }
246 if (ulNewLastId - ulLastId > 1) {
247 // Null unused placeholder entries
248 memset(pNewLoadedStrings + (ulLastId - ulNewFirstId + 1),
249 0,
250 (ulNewLastId - ulLastId - 1) * sizeof(PSZ));
251 }
252 pLoadedStrings = pNewLoadedStrings;
253 ulFirstId = ulNewFirstId;
254 ulLastId = ulNewLastId;
255 }
256
257 uDbgState = 6;
258 pLoadedStrings[id - ulFirstId] = psz;
259 cBusy--;
260 // DbgMsg(pszSrcFile, __LINE__, "id %lu \"%s\"", id, psz ? psz : "(null)");
261 return psz;
262}
263
264#pragma alloc_text(STRINGS,LoadStrings,GetPString)
Note: See TracBrowser for help on using the repository browser.