OSDN Git Service

- Use case insensitive search when checking for existing script names, since they...
[zandronum/zandronum-acc.git] / strlist.c
1 \r
2 //**************************************************************************\r
3 //**\r
4 //** strlist.c\r
5 //**\r
6 //**************************************************************************\r
7 \r
8 // HEADER FILES ------------------------------------------------------------\r
9 \r
10 #include <string.h>\r
11 #include <malloc.h>\r
12 #include "common.h"\r
13 #include "strlist.h"\r
14 #include "error.h"\r
15 #include "misc.h"\r
16 #include "pcode.h"\r
17 \r
18 // MACROS ------------------------------------------------------------------\r
19 \r
20 #ifdef _WIN32\r
21 #define strcasecmp stricmp\r
22 #endif\r
23 \r
24 // TYPES -------------------------------------------------------------------\r
25 \r
26 typedef struct\r
27 {\r
28         char *name;\r
29         int address;\r
30 } stringInfo_t;\r
31 \r
32 typedef struct\r
33 {\r
34         int stringCount;\r
35         stringInfo_t strings[MAX_STRINGS];\r
36 } stringList_t;\r
37 \r
38 typedef struct\r
39 {\r
40         char name[4];\r
41         stringList_t list;\r
42 } languageInfo_t;\r
43 \r
44 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------\r
45 \r
46 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------\r
47 \r
48 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------\r
49 \r
50 static int STR_PutStringInSomeList(stringList_t *list, int index, char *name);\r
51 static int STR_FindInSomeList(stringList_t *list, char *name);\r
52 static int STR_FindInSomeListInsensitive(stringList_t *list, char *name);\r
53 static void DumpStrings(stringList_t *list, int lenadr, boolean quad, boolean crypt);\r
54 static void Encrypt(void *data, int key, int len);\r
55 \r
56 // EXTERNAL DATA DECLARATIONS ----------------------------------------------\r
57 \r
58 // PUBLIC DATA DEFINITIONS -------------------------------------------------\r
59 \r
60 int NumLanguages, NumStringLists;\r
61 \r
62 // PRIVATE DATA DEFINITIONS ------------------------------------------------\r
63 \r
64 static languageInfo_t *LanguageInfo[MAX_LANGUAGES];\r
65 static stringList_t *StringLists[NUM_STRLISTS];\r
66 \r
67 // CODE --------------------------------------------------------------------\r
68 \r
69 //==========================================================================\r
70 //\r
71 // STR_Init\r
72 //\r
73 //==========================================================================\r
74 \r
75 void STR_Init(void)\r
76 {\r
77         NumLanguages = NumStringLists = 0;\r
78         STR_FindLanguage(NULL); // Default language is always number 0\r
79 }\r
80 \r
81 //==========================================================================\r
82 //\r
83 // STR_FindLanguage\r
84 //\r
85 //==========================================================================\r
86 \r
87 int STR_FindLanguage(char *name)\r
88 {\r
89         int i;\r
90 \r
91         if (name == NULL)\r
92         {\r
93                 if (NumLanguages > 0)\r
94                 {\r
95                         return 0;\r
96                 }\r
97                 i = 0;\r
98         }\r
99         else\r
100         {\r
101                 for(i = 0; i < NumLanguages; i++)\r
102                 {\r
103                         if (strcmp (name, LanguageInfo[i]->name) == 0)\r
104                         {\r
105                                 return i;\r
106                         }\r
107                 }\r
108         }\r
109         if(i == NumLanguages)\r
110         {\r
111                 LanguageInfo[i] = MS_Alloc(sizeof(languageInfo_t), ERR_OUT_OF_MEMORY);\r
112                 memset(LanguageInfo[i]->name, 0, 4);\r
113                 if(name != NULL)\r
114                 {\r
115                         strncpy(LanguageInfo[i]->name, name, 3);\r
116                 }\r
117                 LanguageInfo[i]->list.stringCount = 0;\r
118                 NumLanguages++;\r
119         }\r
120         return i;\r
121 }\r
122  \r
123 //==========================================================================\r
124 //\r
125 // STR_Find\r
126 //\r
127 //==========================================================================\r
128 \r
129 int STR_Find(char *name)\r
130 {\r
131         return STR_FindInLanguage(0, name);\r
132 }\r
133 \r
134 //==========================================================================\r
135 //\r
136 // STR_FindInLanguage\r
137 //\r
138 //==========================================================================\r
139 \r
140 int STR_FindInLanguage(int language, char *name)\r
141 {\r
142         return STR_FindInSomeList (&LanguageInfo[language]->list, name);\r
143 }\r
144 \r
145 //==========================================================================\r
146 //\r
147 // STR_FindInList\r
148 //\r
149 //==========================================================================\r
150 \r
151 int STR_FindInList(int list, char *name)\r
152 {\r
153         if (StringLists[list] == NULL)\r
154         {\r
155                 StringLists[list] = MS_Alloc(sizeof(stringList_t), ERR_OUT_OF_MEMORY);\r
156                 StringLists[list]->stringCount = 0;\r
157                 NumStringLists++;\r
158         }\r
159         return STR_FindInSomeList (StringLists[list], name);\r
160 }\r
161 \r
162 //==========================================================================\r
163 //\r
164 // STR_FindInSomeList\r
165 //\r
166 //==========================================================================\r
167 \r
168 static int STR_FindInSomeList(stringList_t *list, char *name)\r
169 {\r
170         int i;\r
171 \r
172         for(i = 0; i < list->stringCount; i++)\r
173         {\r
174                 if(strcmp(list->strings[i].name, name) == 0)\r
175                 {\r
176                         return i;\r
177                 }\r
178         }\r
179         // Add to list\r
180         return STR_PutStringInSomeList(list, i, name);\r
181 }\r
182 \r
183 //==========================================================================\r
184 //\r
185 // STR_FindInListInsensitive\r
186 //\r
187 //==========================================================================\r
188 \r
189 int STR_FindInListInsensitive(int list, char *name)\r
190 {\r
191         if (StringLists[list] == NULL)\r
192         {\r
193                 StringLists[list] = MS_Alloc(sizeof(stringList_t), ERR_OUT_OF_MEMORY);\r
194                 StringLists[list]->stringCount = 0;\r
195                 NumStringLists++;\r
196         }\r
197         return STR_FindInSomeListInsensitive (StringLists[list], name);\r
198 }\r
199 \r
200 //==========================================================================\r
201 //\r
202 // STR_FindInSomeListInsensitive\r
203 //\r
204 //==========================================================================\r
205 \r
206 static int STR_FindInSomeListInsensitive(stringList_t *list, char *name)\r
207 {\r
208         int i;\r
209 \r
210         for(i = 0; i < list->stringCount; i++)\r
211         {\r
212                 if(strcasecmp(list->strings[i].name, name) == 0)\r
213                 {\r
214                         return i;\r
215                 }\r
216         }\r
217         // Add to list\r
218         return STR_PutStringInSomeList(list, i, name);\r
219 }\r
220 \r
221 //==========================================================================\r
222 //\r
223 // STR_GetString\r
224 //\r
225 //==========================================================================\r
226 \r
227 const char *STR_GetString(int list, int index)\r
228 {\r
229         if (StringLists[list] == NULL)\r
230         {\r
231                 return NULL;\r
232         }\r
233         if (index < 0 || index >= StringLists[list]->stringCount)\r
234         {\r
235                 return NULL;\r
236         }\r
237         return StringLists[list]->strings[index].name;\r
238 }\r
239 \r
240 //==========================================================================\r
241 //\r
242 // STR_AppendToList\r
243 //\r
244 //==========================================================================\r
245 \r
246 int STR_AppendToList(int list, char *name)\r
247 {\r
248         if (StringLists[list] == NULL)\r
249         {\r
250                 StringLists[list] = MS_Alloc(sizeof(stringList_t), ERR_OUT_OF_MEMORY);\r
251                 StringLists[list]->stringCount = 0;\r
252                 NumStringLists++;\r
253         }\r
254         return STR_PutStringInSomeList(StringLists[list], StringLists[list]->stringCount, name);\r
255 }\r
256 \r
257 //==========================================================================\r
258 //\r
259 // STR_PutStringInSomeList\r
260 //\r
261 //==========================================================================\r
262 \r
263 static int STR_PutStringInSomeList(stringList_t *list, int index, char *name)\r
264 {\r
265         int i;\r
266 \r
267         if(index >= MAX_STRINGS)\r
268         {\r
269                 ERR_Error(ERR_TOO_MANY_STRINGS, YES, MAX_STRINGS);\r
270                 return 0;\r
271         }\r
272         MS_Message(MSG_DEBUG, "Adding string %d:\n  \"%s\"\n",\r
273                 list->stringCount, name);\r
274         if(index >= list->stringCount)\r
275         {\r
276                 for(i = list->stringCount; i <= index; i++)\r
277                 {\r
278                         list->strings[i].name = NULL;\r
279                 }\r
280                 list->stringCount = index + 1;\r
281         }\r
282         if(list->strings[index].name != NULL)\r
283         {\r
284                 free(list->strings[index].name);\r
285         }\r
286         if(name != NULL)\r
287         {\r
288                 list->strings[index].name = MS_Alloc(strlen(name)+1, ERR_OUT_OF_MEMORY);\r
289                 strcpy(list->strings[index].name, name);\r
290         }\r
291         else\r
292         {\r
293                 list->strings[index].name = NULL;\r
294         }\r
295         return index;\r
296 }\r
297 \r
298 //==========================================================================\r
299 //\r
300 // STR_ListSize\r
301 //\r
302 //==========================================================================\r
303 \r
304 int STR_ListSize(int list)\r
305 {\r
306         return LanguageInfo[list]->list.stringCount;\r
307 }\r
308 \r
309 //==========================================================================\r
310 //\r
311 // STR_WriteStrings\r
312 //\r
313 // Writes all the strings to the p-code buffer.\r
314 //\r
315 //==========================================================================\r
316 \r
317 void STR_WriteStrings(void)\r
318 {\r
319         int i;\r
320         U_INT pad;\r
321 \r
322         MS_Message(MSG_DEBUG, "---- STR_WriteStrings ----\n");\r
323         for(i = 0; i < LanguageInfo[0]->list.stringCount; i++)\r
324         {\r
325                 LanguageInfo[0]->list.strings[i].address = pc_Address;\r
326                 PC_AppendString(LanguageInfo[0]->list.strings[i].name);\r
327         }\r
328         if(pc_Address%4 != 0)\r
329         { // Need to align\r
330                 pad = 0;\r
331                 PC_Append((void *)&pad, 4-(pc_Address%4));\r
332         }\r
333 }\r
334 \r
335 //==========================================================================\r
336 //\r
337 // STR_WriteList\r
338 //\r
339 //==========================================================================\r
340 \r
341 void STR_WriteList(void)\r
342 {\r
343         int i;\r
344 \r
345         MS_Message(MSG_DEBUG, "---- STR_WriteList ----\n");\r
346         PC_AppendInt((U_INT)LanguageInfo[0]->list.stringCount);\r
347         for(i = 0; i < LanguageInfo[0]->list.stringCount; i++)\r
348         {\r
349                 PC_AppendInt((U_INT)LanguageInfo[0]->list.strings[i].address);\r
350         }\r
351 }\r
352 \r
353 //==========================================================================\r
354 //\r
355 // STR_WriteChunk\r
356 //\r
357 //==========================================================================\r
358 \r
359 void STR_WriteChunk(int language, boolean encrypt)\r
360 {\r
361         languageInfo_t *lang = LanguageInfo[language];\r
362         int lenadr;\r
363 \r
364         MS_Message(MSG_DEBUG, "---- STR_WriteChunk %d ----\n", language);\r
365         PC_Append(encrypt ? "STRE" : "STRL", 4);\r
366         lenadr = pc_Address;\r
367         PC_SkipInt();\r
368         PC_Append(&lang->name, 4);\r
369         PC_AppendInt(lang->list.stringCount);\r
370         PC_AppendInt(0);        // Used in-game for stringing lists together\r
371 \r
372         DumpStrings (&lang->list, lenadr, NO, encrypt);\r
373 }\r
374 \r
375 //==========================================================================\r
376 //\r
377 // STR_WriteListChunk\r
378 //\r
379 //==========================================================================\r
380 \r
381 void STR_WriteListChunk(int list, int id, boolean quad)\r
382 {\r
383         int lenadr;\r
384 \r
385         if (StringLists[list] != NULL && StringLists[list]->stringCount > 0)\r
386         {\r
387                 MS_Message(MSG_DEBUG, "---- STR_WriteListChunk %d %c%c%c%c----\n", list,\r
388                         id&255, (id>>8)&255, (id>>16)&255, (id>>24)&255);\r
389                 PC_AppendInt((U_INT)id);\r
390                 lenadr = pc_Address;\r
391                 PC_SkipInt();\r
392                 PC_AppendInt(StringLists[list]->stringCount);\r
393                 if (quad && pc_Address%8 != 0)\r
394                 { // If writing quadword indices, align the indices to an\r
395                   // 8-byte boundary.\r
396                         U_INT pad = 0;\r
397                         PC_Append (&pad, 4);\r
398                 }\r
399                 DumpStrings(StringLists[list], lenadr, quad, NO);\r
400         }\r
401 }\r
402 \r
403 //==========================================================================\r
404 //\r
405 // DumpStrings\r
406 //\r
407 //==========================================================================\r
408 \r
409 static void DumpStrings(stringList_t *list, int lenadr, boolean quad, boolean crypt)\r
410 {\r
411         int i, ofs, startofs;\r
412 \r
413         startofs = ofs = pc_Address - lenadr - 4 + list->stringCount*(quad?8:4);\r
414 \r
415         for(i = 0; i < list->stringCount; i++)\r
416         {\r
417                 if (list->strings[i].name != NULL)\r
418                 {\r
419                         PC_AppendInt((U_INT)ofs);\r
420                         ofs += strlen(list->strings[i].name) + 1;\r
421                 }\r
422                 else\r
423                 {\r
424                         PC_AppendInt(0);\r
425                 }\r
426                 if (quad)\r
427                 {\r
428                         PC_AppendInt(0);\r
429                 }\r
430         }\r
431 \r
432         ofs = startofs;\r
433 \r
434         for(i = 0; i < list->stringCount; i++)\r
435         {\r
436                 if(list->strings[i].name != NULL)\r
437                 {\r
438                         int stringlen = strlen(list->strings[i].name) + 1;\r
439                         if(crypt)\r
440                         {\r
441                                 int cryptkey = ofs*157135;\r
442 \r
443                                 Encrypt(list->strings[i].name, cryptkey, stringlen);\r
444                                 PC_Append(list->strings[i].name, stringlen);\r
445                                 ofs += stringlen;\r
446                                 Encrypt(list->strings[i].name, cryptkey, stringlen);\r
447                         }\r
448                         else\r
449                         {\r
450                                 PC_AppendString(list->strings[i].name);\r
451                         }\r
452                 }\r
453         }\r
454         if(pc_Address%4 != 0)\r
455         { // Need to align\r
456                 U_INT pad = 0;\r
457                 PC_Append((void *)&pad, 4-(pc_Address%4));\r
458         }\r
459 \r
460         PC_WriteInt(pc_Address - lenadr - 4, lenadr);\r
461 }\r
462 \r
463 static void Encrypt(void *data, int key, int len)\r
464 {\r
465         int p = (byte)key, i;\r
466 \r
467         for(i = 0; i < len; ++i)\r
468         {\r
469                 ((byte *)data)[i] ^= (byte)(p+(i>>1));\r
470         }\r
471 }\r