add casts to zune macros to silence some warnings
[tangerine.git] / workbench / libs / locale / opencataloga.c
bloba079e927554bdfb494455e0e84d4d6f78c66fe81
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
4 */
5 #define AROS_ALMOST_COMPATIBLE
7 #include <exec/types.h>
8 #include <exec/memory.h>
9 #include <exec/lists.h>
10 #include <proto/exec.h>
11 #include <proto/dos.h>
12 #include <libraries/iffparse.h>
13 #include <proto/iffparse.h>
14 #include <proto/utility.h>
15 #include <string.h>
16 #include "locale_intern.h"
18 #include <aros/debug.h>
20 #define DEBUG_OPENCATALOG(x) ;
22 struct header
24 unsigned char id[4];
25 unsigned char len[4];
28 /*****************************************************************************
30 NAME */
31 #include <proto/locale.h>
33 AROS_LH3(struct Catalog *, OpenCatalogA,
35 /* SYNOPSIS */
36 AROS_LHA(struct Locale *, locale, A0),
37 AROS_LHA(STRPTR , name, A1),
38 AROS_LHA(struct TagItem *, tags, A2),
40 /* LOCATION */
41 struct LocaleBase *, LocaleBase, 25, Locale)
43 /* FUNCTION
45 INPUTS
47 RESULT
49 NOTES
51 EXAMPLE
53 BUGS
55 SEE ALSO
57 INTERNALS
59 HISTORY
60 27-11-96 digulla automatically created from
61 locale_lib.fd and clib/locale_protos.h
63 *****************************************************************************/
65 AROS_LIBFUNC_INIT
67 struct Locale * def_locale = NULL;
68 struct IntCatalog * catalog = NULL;
69 char * language;
70 char * app_language;
71 char * specific_language;
72 struct Process * MyProcess;
73 #define FILENAMESIZE 256
75 char filename[FILENAMESIZE];
76 char buf[100];
77 LONG chars;
78 ULONG version;
79 ULONG catversion,catrevision;
80 WORD pref_language;
81 UWORD i;
83 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: locale 0x%lx name <%s> Tags 0x%lx localebase 0x%lx\n",
84 locale,
85 name,
86 tags,
87 LocaleBase));
89 SetIoErr(0);
91 if (!locale)
93 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: no locale\n"));
94 locale = def_locale = OpenLocale(NULL);
95 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: def_locale 0x%lx\n",
96 def_locale));
99 if (!locale)
101 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: nolocale..done\n"));
102 return NULL;
105 MyProcess=(struct Process *)FindTask(NULL);
107 specific_language = (char *)GetTagData(OC_Language, (IPTR)0, tags);
109 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: specific lang 0x%lx\n",specific_language));
110 if (specific_language)
112 language = specific_language;
113 pref_language = -1;
114 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: language 0x%lx\n",language));
116 else
118 language = locale->loc_PrefLanguages[0];
119 pref_language = 0;
120 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: language 0x%lx\n",language));
123 if (language == NULL)
125 if (def_locale) CloseLocale(def_locale);
126 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: nolanguage..done\n"));
127 return NULL;
131 ** Check whether the built in language of the application matches
132 ** the language of the default locale. If it matches, then I
133 ** don't need to load anything.
136 app_language = "english";
137 app_language = (char *)GetTagData(OC_BuiltInLanguage,
138 (IPTR)app_language,
139 tags);
141 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: app_language 0x%lx\n",
142 app_language));
144 if (NULL != app_language && 0 == strcmp(app_language, language))
146 if (def_locale) CloseLocale(def_locale);
147 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: failure..done\n"));
148 return NULL;
151 version = GetTagData(OC_Version,
153 tags);
155 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: version %ld\n",version));
157 if (NULL != name)
159 struct IFFHandle * iff = NULL;
162 ** The wanted catalog might be in the list of catalogs that are
163 ** already loaded. So check that list first.
166 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: CatalogLock 0x%lx\n",
167 &IntLB(LocaleBase)->lb_CatalogLock));
169 ObtainSemaphore(&IntLB(LocaleBase)->lb_CatalogLock);
171 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: search cached Catalog\n"));
173 ForeachNode(&IntLB(LocaleBase)->lb_CatalogList, catalog)
175 if (catalog->ic_Name &&
176 0 == strcmp(catalog->ic_Name, name) &&
177 catalog->ic_Catalog.cat_Language &&
178 0 == strcmp(catalog->ic_Catalog.cat_Language, language))
180 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: found Catalog 0x%lx\n",catalog));
181 catalog->ic_UseCount++;
182 ReleaseSemaphore(&IntLB(LocaleBase)->lb_CatalogLock);
184 if (def_locale)
186 CloseLocale(def_locale);
189 SetIoErr(ERROR_ACTION_NOT_KNOWN);
191 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: return Catalog 0x%lx\n",catalog));
192 return (struct Catalog *)catalog;
195 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: found none\n"));
197 ReleaseSemaphore(&IntLB(LocaleBase)->lb_CatalogLock);
200 /* Clear error condition before we start. */
201 SetIoErr(0);
203 iff = AllocIFF();
205 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: iff 0x%lx\n",iff));
206 if (NULL == iff)
208 if (def_locale) CloseLocale(def_locale);
209 SetIoErr(ERROR_NO_FREE_STORE);
211 return NULL;
214 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: pref_language %ld language 0x%lx\n",
215 pref_language,
216 language));
218 while ((pref_language < 10) && language)
220 if (app_language && (strcmp(language, app_language) == 0))
222 FreeIFF(iff);
223 if (def_locale) CloseLocale(def_locale);
224 SetIoErr(0);
225 return NULL;
228 if ((MyProcess->pr_HomeDir) != NULL)
230 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: HomeDir !=NULL..try progdir\n"));
231 strcpy(filename, "PROGDIR:Catalogs");
232 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename));
233 AddPart(filename, language, FILENAMESIZE);
234 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename));
235 AddPart(filename, name , FILENAMESIZE);
237 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename));
238 iff->iff_Stream = (IPTR)Open(filename, MODE_OLDFILE);
239 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: iffstream 0x%lx\n",
240 iff->iff_Stream));
242 if (iff->iff_Stream) break;
244 #ifdef __MORPHOS__
245 strcpy(filename, "MOSSYS:LOCALE/Catalogs");
247 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename));
248 AddPart(filename, language, FILENAMESIZE);
249 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename));
250 AddPart(filename, name , FILENAMESIZE);
252 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: try filename <%s>\n",filename));
254 { APTR oldwinptr=MyProcess->pr_WindowPtr;
255 MyProcess->pr_WindowPtr=(APTR)-1;
256 iff->iff_Stream = (IPTR)Open(filename, MODE_OLDFILE);
257 MyProcess->pr_WindowPtr=oldwinptr;
260 if (iff->iff_Stream) break;
261 #endif
262 strcpy(filename, "LOCALE:Catalogs");
264 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename));
265 AddPart(filename, language, FILENAMESIZE);
266 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename));
267 AddPart(filename, name , FILENAMESIZE);
269 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: try filename <%s>\n",filename));
271 iff->iff_Stream = (IPTR)Open(filename, MODE_OLDFILE);
272 if (iff->iff_Stream) break;
274 pref_language++;
275 language = locale->loc_PrefLanguages[pref_language];
278 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: language 0x%lx\n",language));
280 /* I no longer need the locale. So close it if we opened it */
282 if (def_locale)
284 CloseLocale(def_locale);
285 def_locale = NULL;
288 #undef FILENAMESIZE
290 if (iff->iff_Stream == 0)
292 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: end..nostream\n"));
293 FreeIFF(iff);
294 SetIoErr(ERROR_OBJECT_NOT_FOUND);
295 return NULL;
298 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog name <%s>\n",name));
299 catalog = AllocVec(sizeof(struct IntCatalog) + strlen(name) + 1, MEMF_CLEAR | MEMF_PUBLIC);
300 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog 0x%lx\n",catalog));
301 if (NULL == catalog)
303 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: end..no catalog\n"));
304 Close((BPTR)iff->iff_Stream);
305 FreeIFF(iff);
306 SetIoErr(ERROR_NO_FREE_STORE);
307 return NULL;
310 catalog->ic_UseCount = 1;
311 catalog->ic_Catalog.cat_Language = catalog->ic_LanguageName;
312 strcpy(catalog->ic_Name, name);
314 InitIFFasDOS(iff);
316 if (!OpenIFF(iff, IFFF_READ))
318 while (1)
320 LONG error = ParseIFF(iff, IFFPARSE_STEP);
322 if (IFFERR_EOF == error)
324 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: parsed catalog\n"));
325 /* Did everything go fine? */
327 if (!(catalog->ic_LanguageName[0]))
329 /* No ID_LANG chunk found. So setup languagename ourselves.
330 Hmm ... maybe this should be done anyway always. Because
331 if the catalog file *does* contain an ID_LANG chunk then
332 this should be the same as "language" anyway. And if it
333 is not, then maybe OpenCatalogA() should fail :-\ */
335 strcpy(catalog->ic_LanguageName, language);
338 /* Connect this catalog to the list of catalogs */
339 ObtainSemaphore (&IntLB(LocaleBase)->lb_CatalogLock);
340 AddHead((struct List *)&IntLB(LocaleBase)->lb_CatalogList,
341 &catalog->ic_Catalog.cat_Link);
342 ReleaseSemaphore(&IntLB(LocaleBase)->lb_CatalogLock);
344 CloseIFF(iff);
345 Close((BPTR)iff->iff_Stream);
346 FreeIFF(iff);
348 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: return catalog 0x%lx\n",catalog));
350 return &catalog->ic_Catalog;
353 if (IFFERR_EOC == error) /* end of chunk */
354 continue;
356 if (0 == error)
358 struct ContextNode * top = CurrentChunk(iff);
360 switch (top->cn_ID)
362 case ID_FORM:
363 break;
365 case ID_FVER:
367 if (top->cn_Size > 100) break; /*max 100 bytes*/
369 error = ReadChunkBytes(iff, buf, top->cn_Size);
370 if (error == top->cn_Size)
372 error = 0;
374 else
376 break;
379 buf[99] = 0;
381 /*Ok now we want to get the version and the revision.
382 They are separated by a blank space*/
384 i = 0;
385 while (buf[i] && (buf[i] != ' '))
386 i++;
387 while (buf[i] && (buf[i] == ' '))
388 i++;
389 while (buf[i] && (buf[i] != ' '))
390 i++;
392 if (buf[i])
394 if ((chars = StrToLong(&buf[i],(LONG *)&catversion)) < 0)
395 break;
397 i += chars;
398 if (buf[i++])
400 if (StrToLong(&buf[i],(LONG *)&catrevision) < 0)
401 break;
404 catalog->ic_Catalog.cat_Version = catversion;
405 catalog->ic_Catalog.cat_Revision = catrevision;
407 if (version && (catversion != version))
409 error = RETURN_ERROR;
412 break;
416 case ID_LANG:
417 /* The IntCatalog structure has only 30 bytes reserved for
418 the language name. So make sure the chunk is not bigger. */
420 if (top->cn_Size > 30) break;
422 error = ReadChunkBytes(iff, catalog->ic_LanguageName, top->cn_Size);
423 if (error == top->cn_Size)
425 error = 0;
427 break;
429 case ID_CSET:
430 if (top->cn_Size != sizeof(struct CodeSet)) break;
431 if (top->cn_Size == ReadChunkBytes(iff,
432 &catalog->ic_CodeSet,
433 top->cn_Size))
435 /* Who cares: codeset is not used at the moment */
437 break;
439 case ID_STRS:
440 if (!(catalog->ic_StringChunk = AllocVec(top->cn_Size, MEMF_PUBLIC | MEMF_CLEAR)))
442 error = ERROR_NO_FREE_STORE;
443 SetIoErr(error);
444 break;
447 error = ReadChunkBytes(iff, catalog->ic_StringChunk, top->cn_Size);
448 if (error == top->cn_Size)
450 error = 0;
452 else
454 break;
457 /* Count the number of strings */
460 UBYTE *buffer = catalog->ic_StringChunk;
461 LONG c = 0, strlen;
463 catalog->ic_NumStrings = 0;
465 while(c < top->cn_Size)
467 catalog->ic_NumStrings++;
469 strlen = (buffer[4] << 24) +
470 (buffer[5] << 16) +
471 (buffer[6] << 8) +
472 (buffer[7]);
474 strlen = 8 + strlen + (strlen & 1);
475 if (strlen & 3) strlen += 4 - (strlen & 3);
477 c += strlen; buffer += strlen;
482 if (catalog->ic_NumStrings == 0) break; /* Paranoia? */
484 if (!(catalog->ic_CatStrings = AllocVec(catalog->ic_NumStrings * sizeof(struct CatStr), MEMF_PUBLIC | MEMF_CLEAR)))
486 error = ERROR_NO_FREE_STORE;
487 SetIoErr(error);
488 break;
491 /* Fill out catalog->ic_CatStrings array */
494 UBYTE *buffer = catalog->ic_StringChunk;
495 ULONG i, strlen, id, previd = 0;
496 BOOL inorder = TRUE;
498 for(i = 0; i < catalog->ic_NumStrings; i++)
500 id = (buffer[0] << 24) +
501 (buffer[1] << 16) +
502 (buffer[2] << 8) +
503 (buffer[3]);
505 strlen = (buffer[4] << 24) +
506 (buffer[5] << 16) +
507 (buffer[6] << 8) +
508 (buffer[7]);
510 catalog->ic_CatStrings[i].cs_String = &buffer[8];
511 catalog->ic_CatStrings[i].cs_Id = id;
513 //kprintf("Catalog String #%d id=%d string=\"%s\"\n", i, id, catalog->ic_CatStrings[i].cs_String);
515 strlen = 8 + strlen + (strlen & 1);
516 if (strlen & 3) strlen += 4 - (strlen & 3);
518 if (id < previd) inorder = FALSE;
520 buffer += strlen;
521 previd = id;
524 if (inorder) catalog->ic_Flags |= ICF_INORDER;
526 break;
528 } /* switch (top->cn_ID) */
530 } /* if (0 == error) */
532 if (error)
534 dispose_catalog(catalog, LocaleBase);
536 ** An error with the file occurred
538 break;
541 } /* while (1) */
543 CloseIFF(iff);
545 } /* if (!OpenIFF(iff, IFFF_READ)) */
548 Close((BPTR)iff->iff_Stream);
549 FreeIFF(iff);
550 FreeVec(catalog);
552 } /* if (NULL != name) */
554 if (def_locale) CloseLocale(def_locale);
556 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog not loaded\n"));
557 return NULL;
559 AROS_LIBFUNC_EXIT
561 } /* OpenCatalogA */