2 Copyright © 1995-2008, 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
;
67 char * specific_language
;
68 struct Process
* MyProcess
;
69 #define FILENAMESIZE 256
71 char filename
[FILENAMESIZE
];
75 ULONG catversion
,catrevision
;
79 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: locale 0x%lx name <%s> Tags 0x%lx localebase 0x%lx\n",
89 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: no locale\n"));
90 locale
= def_locale
= OpenLocale(NULL
);
91 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: def_locale 0x%lx\n",
97 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: nolocale..done\n"));
101 MyProcess
=(struct Process
*)FindTask(NULL
);
103 specific_language
= (char *)GetTagData(OC_Language
, (IPTR
)0, tags
);
105 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: specific lang 0x%lx\n",specific_language
));
106 if (specific_language
)
108 language
= specific_language
;
110 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: language 0x%lx\n",language
));
114 language
= locale
->loc_PrefLanguages
[0];
116 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: language 0x%lx\n",language
));
119 if (language
== NULL
)
121 if (def_locale
) CloseLocale(def_locale
);
122 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: nolanguage..done\n"));
127 ** Check whether the built in language of the application matches
128 ** the language of the default locale. If it matches, then I
129 ** don't need to load anything.
132 app_language
= "english";
133 app_language
= (char *)GetTagData(OC_BuiltInLanguage
,
137 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: app_language 0x%lx\n",
140 if (NULL
!= app_language
&& 0 == strcmp(app_language
, language
))
142 if (def_locale
) CloseLocale(def_locale
);
143 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: failure..done\n"));
147 version
= GetTagData(OC_Version
,
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("OpenCatalogA: found Catalog 0x%lx\n",catalog
));
177 catalog
->ic_UseCount
++;
178 ReleaseSemaphore(&IntLB(LocaleBase
)->lb_CatalogLock
);
182 CloseLocale(def_locale
);
185 SetIoErr(ERROR_ACTION_NOT_KNOWN
);
187 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: return Catalog 0x%lx\n",catalog
));
188 return (struct Catalog
*)catalog
;
191 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: found none\n"));
193 ReleaseSemaphore(&IntLB(LocaleBase
)->lb_CatalogLock
);
196 /* Clear error condition before we start. */
201 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: iff 0x%lx\n",iff
));
204 if (def_locale
) CloseLocale(def_locale
);
205 SetIoErr(ERROR_NO_FREE_STORE
);
210 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: pref_language %ld language 0x%lx\n",
214 while ((pref_language
< 10) && language
)
216 if (app_language
&& (strcmp(language
, app_language
) == 0))
219 if (def_locale
) CloseLocale(def_locale
);
224 if ((MyProcess
->pr_HomeDir
) != NULL
)
226 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: HomeDir !=NULL..try progdir\n"));
227 strcpy(filename
, "PROGDIR:Catalogs");
228 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename
));
229 AddPart(filename
, language
, FILENAMESIZE
);
230 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename
));
231 AddPart(filename
, name
, FILENAMESIZE
);
233 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename
));
234 iff
->iff_Stream
= (IPTR
)Open(filename
, MODE_OLDFILE
);
235 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: iffstream 0x%lx\n",
238 if (iff
->iff_Stream
) break;
241 strcpy(filename
, "MOSSYS:LOCALE/Catalogs");
243 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename
));
244 AddPart(filename
, language
, FILENAMESIZE
);
245 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename
));
246 AddPart(filename
, name
, FILENAMESIZE
);
248 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: try filename <%s>\n",filename
));
250 { APTR oldwinptr
=MyProcess
->pr_WindowPtr
;
251 MyProcess
->pr_WindowPtr
=(APTR
)-1;
252 iff
->iff_Stream
= (IPTR
)Open(filename
, MODE_OLDFILE
);
253 MyProcess
->pr_WindowPtr
=oldwinptr
;
256 if (iff
->iff_Stream
) break;
258 strcpy(filename
, "LOCALE:Catalogs");
260 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename
));
261 AddPart(filename
, language
, FILENAMESIZE
);
262 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: filename <%s>\n",filename
));
263 AddPart(filename
, name
, FILENAMESIZE
);
265 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: try filename <%s>\n",filename
));
267 iff
->iff_Stream
= (IPTR
)Open(filename
, MODE_OLDFILE
);
268 if (iff
->iff_Stream
) break;
271 language
= locale
->loc_PrefLanguages
[pref_language
];
274 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: language 0x%lx\n",language
));
276 /* I no longer need the locale. So close it if we opened it */
280 CloseLocale(def_locale
);
286 if (iff
->iff_Stream
== 0)
288 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: end..nostream\n"));
290 SetIoErr(ERROR_OBJECT_NOT_FOUND
);
294 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog name <%s>\n",name
));
295 catalog
= AllocVec(sizeof(struct IntCatalog
) + strlen(name
) + 1, MEMF_CLEAR
| MEMF_PUBLIC
);
296 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog 0x%lx\n",catalog
));
299 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: end..no catalog\n"));
300 Close((BPTR
)iff
->iff_Stream
);
302 SetIoErr(ERROR_NO_FREE_STORE
);
306 catalog
->ic_UseCount
= 1;
307 catalog
->ic_Catalog
.cat_Language
= catalog
->ic_LanguageName
;
308 strcpy(catalog
->ic_Name
, name
);
312 if (!OpenIFF(iff
, IFFF_READ
))
316 LONG error
= ParseIFF(iff
, IFFPARSE_STEP
);
318 if (IFFERR_EOF
== error
)
320 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: parsed catalog\n"));
321 /* Did everything go fine? */
323 if (!(catalog
->ic_LanguageName
[0]))
325 /* No ID_LANG chunk found. So setup languagename ourselves.
326 Hmm ... maybe this should be done anyway always. Because
327 if the catalog file *does* contain an ID_LANG chunk then
328 this should be the same as "language" anyway. And if it
329 is not, then maybe OpenCatalogA() should fail :-\ */
331 strcpy(catalog
->ic_LanguageName
, language
);
334 /* Connect this catalog to the list of catalogs */
335 ObtainSemaphore (&IntLB(LocaleBase
)->lb_CatalogLock
);
336 AddHead((struct List
*)&IntLB(LocaleBase
)->lb_CatalogList
,
337 &catalog
->ic_Catalog
.cat_Link
);
338 ReleaseSemaphore(&IntLB(LocaleBase
)->lb_CatalogLock
);
341 Close((BPTR
)iff
->iff_Stream
);
344 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: return catalog 0x%lx\n",catalog
));
346 return &catalog
->ic_Catalog
;
349 if (IFFERR_EOC
== error
) /* end of chunk */
354 struct ContextNode
* top
= CurrentChunk(iff
);
363 if (top
->cn_Size
> 100) break; /*max 100 bytes*/
365 error
= ReadChunkBytes(iff
, buf
, top
->cn_Size
);
366 if (error
== top
->cn_Size
)
377 /*Ok now we want to get the version and the revision.
378 They are separated by a blank space*/
381 while (buf
[i
] && (buf
[i
] != ' '))
383 while (buf
[i
] && (buf
[i
] == ' '))
385 while (buf
[i
] && (buf
[i
] != ' '))
390 if ((chars
= StrToLong(&buf
[i
],(LONG
*)&catversion
)) < 0)
396 if (StrToLong(&buf
[i
],(LONG
*)&catrevision
) < 0)
400 catalog
->ic_Catalog
.cat_Version
= catversion
;
401 catalog
->ic_Catalog
.cat_Revision
= catrevision
;
403 if (version
&& (catversion
!= version
))
405 error
= RETURN_ERROR
;
413 /* The IntCatalog structure has only 30 bytes reserved for
414 the language name. So make sure the chunk is not bigger. */
416 if (top
->cn_Size
> 30) break;
418 error
= ReadChunkBytes(iff
, catalog
->ic_LanguageName
, top
->cn_Size
);
419 if (error
== top
->cn_Size
)
426 if (top
->cn_Size
!= sizeof(struct CodeSet
)) break;
427 if (top
->cn_Size
== ReadChunkBytes(iff
,
428 &catalog
->ic_CodeSet
,
431 /* Who cares: codeset is not used at the moment */
436 if (!(catalog
->ic_StringChunk
= AllocVec(top
->cn_Size
, MEMF_PUBLIC
| MEMF_CLEAR
)))
438 error
= ERROR_NO_FREE_STORE
;
443 error
= ReadChunkBytes(iff
, catalog
->ic_StringChunk
, top
->cn_Size
);
444 if (error
== top
->cn_Size
)
453 /* Count the number of strings */
456 UBYTE
*buffer
= catalog
->ic_StringChunk
;
459 catalog
->ic_NumStrings
= 0;
461 while(c
< top
->cn_Size
)
463 catalog
->ic_NumStrings
++;
465 strlen
= (buffer
[4] << 24) +
470 strlen
= 8 + strlen
+ (strlen
& 1);
471 if (strlen
& 3) strlen
+= 4 - (strlen
& 3);
473 c
+= strlen
; buffer
+= strlen
;
478 if (catalog
->ic_NumStrings
== 0) break; /* Paranoia? */
480 if (!(catalog
->ic_CatStrings
= AllocVec(catalog
->ic_NumStrings
* sizeof(struct CatStr
), MEMF_PUBLIC
| MEMF_CLEAR
)))
482 error
= ERROR_NO_FREE_STORE
;
487 /* Fill out catalog->ic_CatStrings array */
490 UBYTE
*buffer
= catalog
->ic_StringChunk
;
491 ULONG i
, strlen
, id
, previd
= 0;
494 for(i
= 0; i
< catalog
->ic_NumStrings
; i
++)
496 id
= (buffer
[0] << 24) +
501 strlen
= (buffer
[4] << 24) +
506 catalog
->ic_CatStrings
[i
].cs_String
= &buffer
[8];
507 catalog
->ic_CatStrings
[i
].cs_Id
= id
;
509 //kprintf("Catalog String #%d id=%d string=\"%s\"\n", i, id, catalog->ic_CatStrings[i].cs_String);
511 strlen
= 8 + strlen
+ (strlen
& 1);
512 if (strlen
& 3) strlen
+= 4 - (strlen
& 3);
514 if (id
< previd
) inorder
= FALSE
;
520 if (inorder
) catalog
->ic_Flags
|= ICF_INORDER
;
524 } /* switch (top->cn_ID) */
526 } /* if (0 == error) */
530 dispose_catalog(catalog
, LocaleBase
);
532 ** An error with the file occurred
541 } /* if (!OpenIFF(iff, IFFF_READ)) */
544 Close((BPTR
)iff
->iff_Stream
);
548 } /* if (NULL != name) */
550 if (def_locale
) CloseLocale(def_locale
);
552 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog not loaded\n"));