2 Copyright © 1995-2007, 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(struct Locale
*, locale
, A0
),
37 AROS_LHA(STRPTR
, name
, A1
),
38 AROS_LHA(struct TagItem
*, tags
, A2
),
41 struct LocaleBase
*, LocaleBase
, 25, Locale
)
60 27-11-96 digulla automatically created from
61 locale_lib.fd and clib/locale_protos.h
63 *****************************************************************************/
67 struct Locale
* def_locale
= NULL
;
68 struct IntCatalog
* catalog
= NULL
;
71 char * specific_language
;
72 struct Process
* MyProcess
;
73 #define FILENAMESIZE 256
75 char filename
[FILENAMESIZE
];
79 ULONG catversion
,catrevision
;
83 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: locale 0x%lx name <%s> Tags 0x%lx localebase 0x%lx\n",
93 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: no locale\n"));
94 locale
= def_locale
= OpenLocale(NULL
);
95 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: def_locale 0x%lx\n",
101 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: nolocale..done\n"));
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
;
114 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: language 0x%lx\n",language
));
118 language
= locale
->loc_PrefLanguages
[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"));
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
,
141 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: app_language 0x%lx\n",
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"));
151 version
= GetTagData(OC_Version
,
155 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: version %ld\n",version
));
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
);
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. */
205 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: iff 0x%lx\n",iff
));
208 if (def_locale
) CloseLocale(def_locale
);
209 SetIoErr(ERROR_NO_FREE_STORE
);
214 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: pref_language %ld language 0x%lx\n",
218 while ((pref_language
< 10) && language
)
220 if (app_language
&& (strcmp(language
, app_language
) == 0))
223 if (def_locale
) CloseLocale(def_locale
);
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",
242 if (iff
->iff_Stream
) break;
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;
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;
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 */
284 CloseLocale(def_locale
);
290 if (iff
->iff_Stream
== 0)
292 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: end..nostream\n"));
294 SetIoErr(ERROR_OBJECT_NOT_FOUND
);
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
));
303 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: end..no catalog\n"));
304 Close((BPTR
)iff
->iff_Stream
);
306 SetIoErr(ERROR_NO_FREE_STORE
);
310 catalog
->ic_UseCount
= 1;
311 catalog
->ic_Catalog
.cat_Language
= catalog
->ic_LanguageName
;
312 strcpy(catalog
->ic_Name
, name
);
316 if (!OpenIFF(iff
, IFFF_READ
))
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
);
345 Close((BPTR
)iff
->iff_Stream
);
348 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: return catalog 0x%lx\n",catalog
));
350 return &catalog
->ic_Catalog
;
353 if (IFFERR_EOC
== error
) /* end of chunk */
358 struct ContextNode
* top
= CurrentChunk(iff
);
367 if (top
->cn_Size
> 100) break; /*max 100 bytes*/
369 error
= ReadChunkBytes(iff
, buf
, top
->cn_Size
);
370 if (error
== top
->cn_Size
)
381 /*Ok now we want to get the version and the revision.
382 They are separated by a blank space*/
385 while (buf
[i
] && (buf
[i
] != ' '))
387 while (buf
[i
] && (buf
[i
] == ' '))
389 while (buf
[i
] && (buf
[i
] != ' '))
394 if ((chars
= StrToLong(&buf
[i
],(LONG
*)&catversion
)) < 0)
400 if (StrToLong(&buf
[i
],(LONG
*)&catrevision
) < 0)
404 catalog
->ic_Catalog
.cat_Version
= catversion
;
405 catalog
->ic_Catalog
.cat_Revision
= catrevision
;
407 if (version
&& (catversion
!= version
))
409 error
= RETURN_ERROR
;
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
)
430 if (top
->cn_Size
!= sizeof(struct CodeSet
)) break;
431 if (top
->cn_Size
== ReadChunkBytes(iff
,
432 &catalog
->ic_CodeSet
,
435 /* Who cares: codeset is not used at the moment */
440 if (!(catalog
->ic_StringChunk
= AllocVec(top
->cn_Size
, MEMF_PUBLIC
| MEMF_CLEAR
)))
442 error
= ERROR_NO_FREE_STORE
;
447 error
= ReadChunkBytes(iff
, catalog
->ic_StringChunk
, top
->cn_Size
);
448 if (error
== top
->cn_Size
)
457 /* Count the number of strings */
460 UBYTE
*buffer
= catalog
->ic_StringChunk
;
463 catalog
->ic_NumStrings
= 0;
465 while(c
< top
->cn_Size
)
467 catalog
->ic_NumStrings
++;
469 strlen
= (buffer
[4] << 24) +
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
;
491 /* Fill out catalog->ic_CatStrings array */
494 UBYTE
*buffer
= catalog
->ic_StringChunk
;
495 ULONG i
, strlen
, id
, previd
= 0;
498 for(i
= 0; i
< catalog
->ic_NumStrings
; i
++)
500 id
= (buffer
[0] << 24) +
505 strlen
= (buffer
[4] << 24) +
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
;
524 if (inorder
) catalog
->ic_Flags
|= ICF_INORDER
;
528 } /* switch (top->cn_ID) */
530 } /* if (0 == error) */
534 dispose_catalog(catalog
, LocaleBase
);
536 ** An error with the file occurred
545 } /* if (!OpenIFF(iff, IFFF_READ)) */
548 Close((BPTR
)iff
->iff_Stream
);
552 } /* if (NULL != name) */
554 if (def_locale
) CloseLocale(def_locale
);
556 DEBUG_OPENCATALOG(dprintf("OpenCatalogA: catalog not loaded\n"));