2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
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>
16 #include "locale_intern.h"
18 #include <aros/debug.h>
20 #define DEBUG_OPENCATALOG(x) ;
28 static IPTR
_OpenCatalog(const struct Locale
* locale
, CONST_STRPTR name
, STRPTR language
);
30 /*****************************************************************************
33 #include <proto/locale.h>
35 AROS_LH3(struct Catalog
*, OpenCatalogA
,
38 AROS_LHA(const struct Locale
*, locale
, A0
),
39 AROS_LHA(CONST_STRPTR
, name
, A1
),
40 AROS_LHA(const struct TagItem
*, tags
, A2
),
43 struct LocaleBase
*, LocaleBase
, 25, Locale
)
61 *****************************************************************************/
65 struct IntLocaleBase
*_localeBase
= IntLB(LocaleBase
);
66 struct Locale
*def_locale
= NULL
;
67 struct IntCatalog
*catalog
= NULL
;
69 char *app_language
; /* Language given with tag OC_BuiltInLanguage */
70 char *specific_language
; /* Language given with tag OC_Language */
75 ULONG catversion
, catrevision
;
79 DEBUG_OPENCATALOG(dprintf
80 ("OpenCatalogA: locale 0x%lx name <%s> Tags 0x%lx localebase 0x%lx\n",
81 locale
, name
, tags
, LocaleBase
));
87 if (!(locale
= OpenLocale(NULL
)))
89 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: no locale to use? ..done\n"));
92 def_locale
= (struct Locale
*)locale
;
93 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: default locale @ 0x%lx\n", def_locale
));
96 if ((specific_language
= (char *)GetTagData(OC_Language
, (IPTR
) 0, tags
)))
98 language
= specific_language
;
100 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: requested language '%s' @ 0x%lx\n", language
, language
));
104 if ((language
= locale
->loc_PrefLanguages
[0]) == NULL
)
107 CloseLocale(def_locale
);
108 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: no language to use? ..done\n"));
112 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: default language '%s' @ 0x%lx\n", language
, language
));
116 ** Check whether the built in language of the application matches
117 ** the language of the default locale. If it matches, then we
118 ** don't need to load anything.
121 app_language
= (char *)GetTagData(OC_BuiltInLanguage
,
122 (IPTR
) "english", tags
);
124 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: app_language '%s' @ 0x%lx\n", app_language
, app_language
));
126 if (app_language
&& (0 == strcasecmp(app_language
, language
)))
129 CloseLocale(def_locale
);
130 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: failure..done\n"));
134 version
= GetTagData(OC_Version
, 0, tags
);
136 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: version %ld\n", version
));
140 struct IFFHandle
*iff
= NULL
;
143 ** The wanted catalog might be in the list of catalogs that are
144 ** already loaded. So check that list first.
147 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: CatalogLock 0x%lx\n",
148 &_localeBase
->lb_CatalogLock
));
150 ObtainSemaphore(&_localeBase
->lb_CatalogLock
);
152 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: search cached Catalog\n"));
154 ForeachNode(&_localeBase
->lb_CatalogList
, catalog
)
156 if (catalog
->ic_Name
&&
157 catalog
->ic_Catalog
.cat_Language
&&
158 (0 == strcmp(catalog
->ic_Name
, name
)) &&
159 (0 == strcmp(catalog
->ic_Catalog
.cat_Language
, language
)))
161 DEBUG_OPENCATALOG(dprintf
162 ("OpenCatalogA: found Catalog 0x%lx\n", catalog
));
163 catalog
->ic_UseCount
++;
164 ReleaseSemaphore(&_localeBase
->lb_CatalogLock
);
168 CloseLocale(def_locale
);
171 SetIoErr(ERROR_ACTION_NOT_KNOWN
);
173 DEBUG_OPENCATALOG(dprintf
174 ("OpenCatalogA: return Catalog 0x%lx\n", catalog
));
175 return (struct Catalog
*)catalog
;
178 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: found none\n"));
180 ReleaseSemaphore(&_localeBase
->lb_CatalogLock
);
182 /* Clear error condition before we start. */
187 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: iff 0x%lx\n", iff
));
191 CloseLocale(def_locale
);
192 SetIoErr(ERROR_NO_FREE_STORE
);
197 DEBUG_OPENCATALOG(dprintf
198 ("OpenCatalogA: pref_language %ld language 0x%lx\n",
199 pref_language
, language
));
201 while ((pref_language
< 10) && language
)
203 if (app_language
&& (strcmp(language
, app_language
) == 0))
207 CloseLocale(def_locale
);
212 iff
->iff_Stream
= _OpenCatalog(locale
, name
, language
);
218 language
= locale
->loc_PrefLanguages
[pref_language
];
221 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: language 0x%lx\n",
224 /* I no longer need the locale. So close it if we opened it */
228 CloseLocale(def_locale
);
232 if (iff
->iff_Stream
== 0)
234 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: end... no stream\n"));
236 SetIoErr(ERROR_OBJECT_NOT_FOUND
);
240 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog name <%s>\n",
243 AllocVec(sizeof(struct IntCatalog
) + strlen(name
) + 1,
244 MEMF_CLEAR
| MEMF_PUBLIC
);
245 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog 0x%lx\n",
249 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: end..no catalog\n"));
250 Close((BPTR
) iff
->iff_Stream
);
252 SetIoErr(ERROR_NO_FREE_STORE
);
256 catalog
->ic_UseCount
= 1;
257 catalog
->ic_Catalog
.cat_Language
= catalog
->ic_LanguageName
;
258 strcpy(catalog
->ic_Name
, name
);
259 catalog
->ic_Catalog
.cat_Link
.ln_Name
= catalog
->ic_Name
; /* Scout expects this */
263 if (!OpenIFF(iff
, IFFF_READ
))
267 LONG error
= ParseIFF(iff
, IFFPARSE_STEP
);
269 if (IFFERR_EOF
== error
)
271 DEBUG_OPENCATALOG(dprintf
272 ("OpenCatalogA: parsed catalog\n"));
273 /* Did everything go fine? */
275 if (!(catalog
->ic_LanguageName
[0]))
277 /* No ID_LANG chunk found. So setup languagename ourselves.
278 Hmm ... maybe this should be done anyway always. Because
279 if the catalog file *does* contain an ID_LANG chunk then
280 this should be the same as "language" anyway. And if it
281 is not, then maybe OpenCatalogA() should fail :-\ */
283 strcpy(catalog
->ic_LanguageName
, language
);
286 /* Connect this catalog to the list of catalogs */
287 ObtainSemaphore(&_localeBase
->lb_CatalogLock
);
288 AddHead((struct List
*)&_localeBase
->
289 lb_CatalogList
, &catalog
->ic_Catalog
.cat_Link
);
290 ReleaseSemaphore(&_localeBase
->lb_CatalogLock
);
293 Close((BPTR
) iff
->iff_Stream
);
296 DEBUG_OPENCATALOG(dprintf
297 ("OpenCatalogA: return catalog 0x%lx\n", catalog
));
299 return &catalog
->ic_Catalog
;
302 if (IFFERR_EOC
== error
) /* end of chunk */
307 struct ContextNode
*top
= CurrentChunk(iff
);
316 if (top
->cn_Size
> 100)
317 break; /*max 100 bytes */
319 error
= ReadChunkBytes(iff
, buf
, top
->cn_Size
);
320 if (error
== top
->cn_Size
)
331 /*Ok now we want to get the version and the revision.
332 They are separated by a blank space */
335 while (buf
[i
] && (buf
[i
] != ' '))
337 while (buf
[i
] && (buf
[i
] == ' '))
339 while (buf
[i
] && (buf
[i
] != ' '))
346 (LONG
*) & catversion
)) < 0)
352 if (StrToLong(&buf
[i
],
353 (LONG
*) & catrevision
) < 0)
357 catalog
->ic_Catalog
.cat_Version
= catversion
;
358 catalog
->ic_Catalog
.cat_Revision
= catrevision
;
360 if (version
&& (catversion
!= version
))
362 error
= RETURN_ERROR
;
370 /* The IntCatalog structure has only 30 bytes reserved for
371 the language name. So make sure the chunk is not bigger. */
373 if (top
->cn_Size
> 30)
377 ReadChunkBytes(iff
, catalog
->ic_LanguageName
,
379 if (error
== top
->cn_Size
)
386 if (top
->cn_Size
!= sizeof(struct CodeSet
))
388 if (top
->cn_Size
== ReadChunkBytes(iff
,
389 &catalog
->ic_CodeSet
, top
->cn_Size
))
391 /* Who cares: codeset is not used at the moment */
396 if (!(catalog
->ic_StringChunk
=
397 AllocVec(top
->cn_Size
,
398 MEMF_PUBLIC
| MEMF_CLEAR
)))
400 error
= ERROR_NO_FREE_STORE
;
406 ReadChunkBytes(iff
, catalog
->ic_StringChunk
,
408 if (error
== top
->cn_Size
)
417 /* Count the number of strings */
420 UBYTE
*buffer
= catalog
->ic_StringChunk
;
423 catalog
->ic_NumStrings
= 0;
425 while (c
< top
->cn_Size
)
427 catalog
->ic_NumStrings
++;
429 strlen
= (buffer
[4] << 24) +
431 (buffer
[6] << 8) + (buffer
[7]);
433 strlen
= 8 + strlen
+ (strlen
& 1);
435 strlen
+= 4 - (strlen
& 3);
443 if (catalog
->ic_NumStrings
== 0)
444 break; /* Paranoia? */
446 if (!(catalog
->ic_CatStrings
=
447 AllocVec(catalog
->ic_NumStrings
*
448 sizeof(struct CatStr
),
449 MEMF_PUBLIC
| MEMF_CLEAR
)))
451 error
= ERROR_NO_FREE_STORE
;
456 /* Fill out catalog->ic_CatStrings array */
459 UBYTE
*buffer
= catalog
->ic_StringChunk
;
460 ULONG i
, strlen
, id
, previd
= 0;
463 for (i
= 0; i
< catalog
->ic_NumStrings
; i
++)
465 id
= (buffer
[0] << 24) +
467 (buffer
[2] << 8) + (buffer
[3]);
469 strlen
= (buffer
[4] << 24) +
471 (buffer
[6] << 8) + (buffer
[7]);
473 catalog
->ic_CatStrings
[i
].cs_String
=
475 catalog
->ic_CatStrings
[i
].cs_Id
= id
;
477 //kprintf("Catalog String #%d id=%d string=\"%s\"\n", i, id, catalog->ic_CatStrings[i].cs_String);
479 strlen
= 8 + strlen
+ (strlen
& 1);
481 strlen
+= 4 - (strlen
& 3);
491 catalog
->ic_Flags
|= ICF_INORDER
;
495 } /* switch (top->cn_ID) */
497 } /* if (0 == error) */
501 dispose_catalog(catalog
, LocaleBase
);
503 ** An error with the file occurred
512 } /* if (!OpenIFF(iff, IFFF_READ)) */
515 Close((BPTR
) iff
->iff_Stream
);
519 } /* if (NULL != name) */
522 CloseLocale(def_locale
);
524 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog not loaded\n"));
530 static STRPTR
Preferred2OnDisk(struct IntLocale
* locale
, STRPTR language
)
535 if (locale
->il_Locale
.loc_PrefLanguages
[i
] &&
536 strcmp(locale
->il_Locale
.loc_PrefLanguages
[i
], language
) == 0)
537 return locale
->LanguagesOnDiskNames
[i
];
544 static IPTR
_OpenFile(const struct Locale
* locale
, STRPTR root
, CONST_STRPTR name
, STRPTR language
)
546 #define FILENAMESIZE 256
547 TEXT filename
[FILENAMESIZE
];
548 IPTR iff_Stream
= (IPTR
)NULL
;
550 strcpy(filename
, root
);
551 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",
553 AddPart(filename
, language
, FILENAMESIZE
);
554 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",
556 AddPart(filename
, name
, FILENAMESIZE
);
558 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",
560 iff_Stream
= (IPTR
) Open(filename
, MODE_OLDFILE
);
561 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: iffstream 0x%lx\n",
564 if (!iff_Stream
&& locale
)
566 STRPTR altname
= Preferred2OnDisk((struct IntLocale
*)locale
, language
);
568 iff_Stream
= _OpenFile(NULL
, root
, name
, altname
);
576 static IPTR
_OpenCatalog(const struct Locale
* locale
, CONST_STRPTR name
, STRPTR language
)
578 struct Process
* MyProcess
= (struct Process
*)FindTask(NULL
);
580 IPTR iff_Stream
= (IPTR
)NULL
;
582 if ((MyProcess
->pr_HomeDir
) != BNULL
)
584 DEBUG_OPENCATALOG(dprintf
585 ("OpenCatalogA: HomeDir != BNULL..try progdir\n"));
586 iff_Stream
= _OpenFile(locale
, "PROGDIR:Catalogs", name
, language
);
595 APTR oldwinptr
= MyProcess
->pr_WindowPtr
;
596 MyProcess
->pr_WindowPtr
= (APTR
) - 1;
597 iff_Stream
= _OpenFile(locale
, "MOSSYS:LOCALE/Catalogs", name
, language
);
598 MyProcess
->pr_WindowPtr
= oldwinptr
;
605 iff_Stream
= _OpenFile(locale
, "LOCALE:Catalogs", name
, language
);