2 Copyright © 1995-2011, 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 /*****************************************************************************
31 #include <proto/locale.h>
33 AROS_LH3(struct Catalog
*, OpenCatalogA
,
36 AROS_LHA(const struct Locale
*, locale
, A0
),
37 AROS_LHA(CONST_STRPTR
, name
, A1
),
38 AROS_LHA(const struct TagItem
*, tags
, A2
),
41 struct LocaleBase
*, LocaleBase
, 25, Locale
)
59 *****************************************************************************/
63 struct Locale
*def_locale
= NULL
;
64 struct IntCatalog
*catalog
= NULL
;
66 char *app_language
; /* Language given with tag OC_BuiltInLanguage */
67 char *specific_language
; /* Language given with tag OC_Language */
68 struct Process
*MyProcess
;
69 #define FILENAMESIZE 256
71 char filename
[FILENAMESIZE
];
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 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: no locale\n"));
88 locale
= def_locale
= OpenLocale(NULL
);
89 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: def_locale 0x%lx\n",
95 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: nolocale..done\n"));
99 MyProcess
= (struct Process
*)FindTask(NULL
);
101 specific_language
= (char *)GetTagData(OC_Language
, (IPTR
) 0, tags
);
103 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: specific lang 0x%lx\n",
105 if (specific_language
)
107 language
= specific_language
;
109 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: language 0x%lx\n",
114 language
= locale
->loc_PrefLanguages
[0];
116 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: language 0x%lx\n",
120 if (language
== NULL
)
123 CloseLocale(def_locale
);
124 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: nolanguage..done\n"));
129 ** Check whether the built in language of the application matches
130 ** the language of the default locale. If it matches, then I
131 ** don't need to load anything.
134 app_language
= "english";
135 app_language
= (char *)GetTagData(OC_BuiltInLanguage
,
136 (IPTR
) app_language
, tags
);
138 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: app_language 0x%lx\n",
141 if (NULL
!= app_language
&& 0 == strcasecmp(app_language
, language
))
144 CloseLocale(def_locale
);
145 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: failure..done\n"));
149 version
= GetTagData(OC_Version
, 0, tags
);
151 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: version %ld\n", version
));
155 struct IFFHandle
*iff
= NULL
;
158 ** The wanted catalog might be in the list of catalogs that are
159 ** already loaded. So check that list first.
162 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: CatalogLock 0x%lx\n",
163 &IntLB(LocaleBase
)->lb_CatalogLock
));
165 ObtainSemaphore(&IntLB(LocaleBase
)->lb_CatalogLock
);
167 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: search cached Catalog\n"));
169 ForeachNode(&IntLB(LocaleBase
)->lb_CatalogList
, catalog
)
171 if (catalog
->ic_Name
&&
172 0 == strcmp(catalog
->ic_Name
, name
) &&
173 catalog
->ic_Catalog
.cat_Language
&&
174 0 == strcmp(catalog
->ic_Catalog
.cat_Language
, language
))
176 DEBUG_OPENCATALOG(dprintf
177 ("OpenCatalogA: found Catalog 0x%lx\n", catalog
));
178 catalog
->ic_UseCount
++;
179 ReleaseSemaphore(&IntLB(LocaleBase
)->lb_CatalogLock
);
183 CloseLocale(def_locale
);
186 SetIoErr(ERROR_ACTION_NOT_KNOWN
);
188 DEBUG_OPENCATALOG(dprintf
189 ("OpenCatalogA: return Catalog 0x%lx\n", catalog
));
190 return (struct Catalog
*)catalog
;
193 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: found none\n"));
195 ReleaseSemaphore(&IntLB(LocaleBase
)->lb_CatalogLock
);
197 /* Clear error condition before we start. */
202 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: iff 0x%lx\n", iff
));
206 CloseLocale(def_locale
);
207 SetIoErr(ERROR_NO_FREE_STORE
);
212 DEBUG_OPENCATALOG(dprintf
213 ("OpenCatalogA: pref_language %ld language 0x%lx\n",
214 pref_language
, language
));
216 while ((pref_language
< 10) && language
)
218 if (app_language
&& (strcmp(language
, app_language
) == 0))
222 CloseLocale(def_locale
);
227 if ((MyProcess
->pr_HomeDir
) != BNULL
)
229 DEBUG_OPENCATALOG(dprintf
230 ("OpenCatalogA: HomeDir != BNULL..try progdir\n"));
231 strcpy(filename
, "PROGDIR:Catalogs");
232 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",
234 AddPart(filename
, language
, FILENAMESIZE
);
235 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",
237 AddPart(filename
, name
, FILENAMESIZE
);
239 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",
241 iff
->iff_Stream
= (IPTR
) Open(filename
, MODE_OLDFILE
);
242 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: iffstream 0x%lx\n",
249 strcpy(filename
, "MOSSYS:LOCALE/Catalogs");
251 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",
253 AddPart(filename
, language
, FILENAMESIZE
);
254 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",
256 AddPart(filename
, name
, FILENAMESIZE
);
258 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: try filename <%s>\n",
262 APTR oldwinptr
= MyProcess
->pr_WindowPtr
;
263 MyProcess
->pr_WindowPtr
= (APTR
) - 1;
264 iff
->iff_Stream
= (IPTR
) Open(filename
, MODE_OLDFILE
);
265 MyProcess
->pr_WindowPtr
= oldwinptr
;
271 strcpy(filename
, "LOCALE:Catalogs");
273 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",
275 AddPart(filename
, language
, FILENAMESIZE
);
276 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",
278 AddPart(filename
, name
, FILENAMESIZE
);
280 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: try filename <%s>\n",
283 iff
->iff_Stream
= (IPTR
) Open(filename
, MODE_OLDFILE
);
284 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: iffstream 0x%lx\n",
291 language
= locale
->loc_PrefLanguages
[pref_language
];
294 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: language 0x%lx\n",
297 /* I no longer need the locale. So close it if we opened it */
301 CloseLocale(def_locale
);
307 if (iff
->iff_Stream
== 0)
309 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: end... no stream\n"));
311 SetIoErr(ERROR_OBJECT_NOT_FOUND
);
315 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog name <%s>\n",
318 AllocVec(sizeof(struct IntCatalog
) + strlen(name
) + 1,
319 MEMF_CLEAR
| MEMF_PUBLIC
);
320 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog 0x%lx\n",
324 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: end..no catalog\n"));
325 Close((BPTR
) iff
->iff_Stream
);
327 SetIoErr(ERROR_NO_FREE_STORE
);
331 catalog
->ic_UseCount
= 1;
332 catalog
->ic_Catalog
.cat_Language
= catalog
->ic_LanguageName
;
333 strcpy(catalog
->ic_Name
, name
);
334 catalog
->ic_Catalog
.cat_Link
.ln_Name
= catalog
->ic_Name
; /* Scout expects this */
338 if (!OpenIFF(iff
, IFFF_READ
))
342 LONG error
= ParseIFF(iff
, IFFPARSE_STEP
);
344 if (IFFERR_EOF
== error
)
346 DEBUG_OPENCATALOG(dprintf
347 ("OpenCatalogA: parsed catalog\n"));
348 /* Did everything go fine? */
350 if (!(catalog
->ic_LanguageName
[0]))
352 /* No ID_LANG chunk found. So setup languagename ourselves.
353 Hmm ... maybe this should be done anyway always. Because
354 if the catalog file *does* contain an ID_LANG chunk then
355 this should be the same as "language" anyway. And if it
356 is not, then maybe OpenCatalogA() should fail :-\ */
358 strcpy(catalog
->ic_LanguageName
, language
);
361 /* Connect this catalog to the list of catalogs */
362 ObtainSemaphore(&IntLB(LocaleBase
)->lb_CatalogLock
);
363 AddHead((struct List
*)&IntLB(LocaleBase
)->
364 lb_CatalogList
, &catalog
->ic_Catalog
.cat_Link
);
365 ReleaseSemaphore(&IntLB(LocaleBase
)->lb_CatalogLock
);
368 Close((BPTR
) iff
->iff_Stream
);
371 DEBUG_OPENCATALOG(dprintf
372 ("OpenCatalogA: return catalog 0x%lx\n", catalog
));
374 return &catalog
->ic_Catalog
;
377 if (IFFERR_EOC
== error
) /* end of chunk */
382 struct ContextNode
*top
= CurrentChunk(iff
);
391 if (top
->cn_Size
> 100)
392 break; /*max 100 bytes */
394 error
= ReadChunkBytes(iff
, buf
, top
->cn_Size
);
395 if (error
== top
->cn_Size
)
406 /*Ok now we want to get the version and the revision.
407 They are separated by a blank space */
410 while (buf
[i
] && (buf
[i
] != ' '))
412 while (buf
[i
] && (buf
[i
] == ' '))
414 while (buf
[i
] && (buf
[i
] != ' '))
421 (LONG
*) & catversion
)) < 0)
427 if (StrToLong(&buf
[i
],
428 (LONG
*) & catrevision
) < 0)
432 catalog
->ic_Catalog
.cat_Version
= catversion
;
433 catalog
->ic_Catalog
.cat_Revision
= catrevision
;
435 if (version
&& (catversion
!= version
))
437 error
= RETURN_ERROR
;
445 /* The IntCatalog structure has only 30 bytes reserved for
446 the language name. So make sure the chunk is not bigger. */
448 if (top
->cn_Size
> 30)
452 ReadChunkBytes(iff
, catalog
->ic_LanguageName
,
454 if (error
== top
->cn_Size
)
461 if (top
->cn_Size
!= sizeof(struct CodeSet
))
463 if (top
->cn_Size
== ReadChunkBytes(iff
,
464 &catalog
->ic_CodeSet
, top
->cn_Size
))
466 /* Who cares: codeset is not used at the moment */
471 if (!(catalog
->ic_StringChunk
=
472 AllocVec(top
->cn_Size
,
473 MEMF_PUBLIC
| MEMF_CLEAR
)))
475 error
= ERROR_NO_FREE_STORE
;
481 ReadChunkBytes(iff
, catalog
->ic_StringChunk
,
483 if (error
== top
->cn_Size
)
492 /* Count the number of strings */
495 UBYTE
*buffer
= catalog
->ic_StringChunk
;
498 catalog
->ic_NumStrings
= 0;
500 while (c
< top
->cn_Size
)
502 catalog
->ic_NumStrings
++;
504 strlen
= (buffer
[4] << 24) +
506 (buffer
[6] << 8) + (buffer
[7]);
508 strlen
= 8 + strlen
+ (strlen
& 1);
510 strlen
+= 4 - (strlen
& 3);
518 if (catalog
->ic_NumStrings
== 0)
519 break; /* Paranoia? */
521 if (!(catalog
->ic_CatStrings
=
522 AllocVec(catalog
->ic_NumStrings
*
523 sizeof(struct CatStr
),
524 MEMF_PUBLIC
| MEMF_CLEAR
)))
526 error
= ERROR_NO_FREE_STORE
;
531 /* Fill out catalog->ic_CatStrings array */
534 UBYTE
*buffer
= catalog
->ic_StringChunk
;
535 ULONG i
, strlen
, id
, previd
= 0;
538 for (i
= 0; i
< catalog
->ic_NumStrings
; i
++)
540 id
= (buffer
[0] << 24) +
542 (buffer
[2] << 8) + (buffer
[3]);
544 strlen
= (buffer
[4] << 24) +
546 (buffer
[6] << 8) + (buffer
[7]);
548 catalog
->ic_CatStrings
[i
].cs_String
=
550 catalog
->ic_CatStrings
[i
].cs_Id
= id
;
552 //kprintf("Catalog String #%d id=%d string=\"%s\"\n", i, id, catalog->ic_CatStrings[i].cs_String);
554 strlen
= 8 + strlen
+ (strlen
& 1);
556 strlen
+= 4 - (strlen
& 3);
566 catalog
->ic_Flags
|= ICF_INORDER
;
570 } /* switch (top->cn_ID) */
572 } /* if (0 == error) */
576 dispose_catalog(catalog
, LocaleBase
);
578 ** An error with the file occurred
587 } /* if (!OpenIFF(iff, IFFF_READ)) */
590 Close((BPTR
) iff
->iff_Stream
);
594 } /* if (NULL != name) */
597 CloseLocale(def_locale
);
599 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog not loaded\n"));