Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / libs / codesetslib / src / init.c
blob29793f72ea57faf14b8ddd9d9366831d41d0873c
1 /***************************************************************************
3 codesets.library - Amiga shared library for handling different codesets
4 Copyright (C) 2001-2005 by Alfonso [alfie] Ranieri <alforan@tin.it>.
5 Copyright (C) 2005-2009 by codesets.library Open Source Team
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 codesets.library project: http://sourceforge.net/projects/codesetslib/
19 $Id$
21 ***************************************************************************/
23 #include "lib.h"
25 #include <diskfont/glyph.h>
26 #include <diskfont/diskfonttag.h>
27 #include <proto/diskfont.h>
28 #include <proto/keymap.h>
29 #include <proto/locale.h>
30 #include <proto/exec.h>
31 #include <proto/dos.h>
32 #include <proto/utility.h>
34 #include "debug.h"
36 #if defined(__amigaos4__)
37 struct Library *DOSBase = NULL;
38 struct Library *UtilityBase = NULL;
39 struct Library *LocaleBase = NULL;
40 struct Library *DiskfontBase = NULL;
42 struct DOSIFace* IDOS = NULL;
43 struct UtilityIFace* IUtility = NULL;
44 struct LocaleIFace* ILocale = NULL;
45 struct DiskfontIFace* IDiskfont = NULL;
47 #if !defined(__NEWLIB__)
48 extern struct Library *__UtilityBase;
49 extern struct UtilityIFace* __IUtility;
50 #endif
52 #else
53 struct DosLibrary *DOSBase = NULL;
54 #if defined(__MORPHOS__)
55 struct Library *LocaleBase = NULL;
56 #else
57 struct LocaleBase *LocaleBase = NULL;
58 #endif
59 #ifdef __AROS__
60 struct UtilityBase *UtilityBase = NULL;
61 #else
62 struct Library *UtilityBase = NULL;
63 struct Library *__UtilityBase = NULL; // required by clib2 & libnix
64 #endif
65 #endif
67 /****************************************************************************/
69 ULONG
70 freeBase(struct LibraryHeader *lib)
72 ENTER();
74 D(DBF_STARTUP, "freeing all resources of codesets.library");
76 // cleanup also the internal public codesets list
77 codesetsCleanup(&lib->codesets);
79 // close locale.library
80 if(LocaleBase)
82 DROPINTERFACE(ILocale);
83 CloseLibrary((struct Library *)LocaleBase);
84 LocaleBase = NULL;
87 #if defined(__amigaos4__)
88 // close diskfont.library
89 if(DiskfontBase)
91 DROPINTERFACE(IDiskfont);
92 CloseLibrary((struct Library *)DiskfontBase);
93 DiskfontBase = NULL;
95 #endif
97 // delete our private memory pool
98 if(lib->pool != NULL)
100 #if defined(__amigaos4__)
101 FreeSysObject(ASOT_MEMPOOL, lib->pool);
102 #else
103 DeletePool(lib->pool);
104 #endif
105 lib->pool = NULL;
108 // close utility.library
109 if(UtilityBase)
111 DROPINTERFACE(IUtility);
112 CloseLibrary(UtilityBase);
113 UtilityBase = NULL;
116 // close dos.library
117 if(DOSBase)
119 DROPINTERFACE(IDOS);
120 CloseLibrary((struct Library *)DOSBase);
121 DOSBase = NULL;
124 RETURN(TRUE);
125 return TRUE;
128 /***********************************************************************/
130 struct loc
132 const char *name;
133 ULONG len;
134 const char *codesetName;
137 // table with the default LANGUAGE<>CHARSET mapping we
138 // are using in codesets.library.
139 static const struct loc locs[] =
141 { "bosanski", 8, "ISO-8859-2" },
142 { "català", 6, "ISO-8859-1 + Euro" },
143 { "czech", 5, "ISO-8859-2" },
144 { "dansk", 5, "ISO-8859-1 + Euro" },
145 { "deutsch", 7, "ISO-8859-1 + Euro" },
146 { "english", 7, "ISO-8859-1 + Euro" },
147 { "esperanto", 9, "ISO-8859-3" },
148 { "eesti", 5, "ISO-8859-15" },
149 { "èe¹tina", 7, "ISO-8859-2" }, /* Czech in MorphOS 2.0 */
150 { "español", 7, "ISO-8859-1 + Euro" },
151 { "français", 8, "ISO-8859-1 + Euro" },
152 { "gaeilge", 7, "ISO-8859-15" },
153 { "galego", 6, "ISO-8859-1 + Euro" },
154 { "greek", 5, "ISO-8859-7" },
155 { "hrvatski", 8, "ISO-8859-2" },
156 { "italiano", 8, "ISO-8859-1 + Euro" },
157 { "lietuvi", 7, "ISO-8859-13" },
158 { "magyar", 6, "ISO-8859-2" },
159 { "nederlands", 10, "ISO-8859-1 + Euro" },
160 { "norsk", 5, "ISO-8859-1 + Euro" },
161 { "polski", 6, "ISO-8859-2" },
162 { "português", 9, "ISO-8859-1 + Euro" },
163 { "russian", 7, "Amiga-1251" },
164 { "slovak", 6, "ISO-8859-2" },
165 { "slovensko", 9, "ISO-8859-2" },
166 { "srpski", 6, "ISO-8859-2" },
167 { "suomi", 5, "ISO-8859-1" },
168 { "svenska", 7, "ISO-8859-1 + Euro" },
169 { "türkçe", 6, "ISO-8859-9" },
170 { NULL, 0, NULL }
173 static void
174 getSystemCodeset(struct LibraryHeader *lib)
176 struct codeset *foundCodeset = NULL;
178 ENTER();
180 // before we go any query the system via locale.library (which
181 // might not be so accurate) we try different other means of
182 // finding the codeset/charset of the system
183 #ifdef __amigaos4__
185 LONG default_charset = GetDiskFontCtrl(DFCTRL_CHARSET);
186 char *charset = (char *)ObtainCharsetInfo(DFCS_NUMBER, default_charset, DFCS_MIMENAME);
188 foundCodeset = codesetsFind(&lib->codesets, charset);
190 D(DBF_STARTUP, "%s system default codeset: '%s' (diskfont)", foundCodeset ? "found" : "not found", charset);
192 #endif
194 #ifdef __MORPHOS__
196 /* The system maintains CODEPAGE environment variable which defines the preferred codepage for this user. */
197 TEXT codepage[40];
199 if (GetVar("CODEPAGE", codepage, sizeof(codepage), 0) > 0)
201 foundCodeset = codesetsFind(&lib->codesets, codepage);
204 D(DBF_STARTUP, "%s system default codeset: '%s' (keymap)", foundCodeset ? "found" : "not found", codepage);
206 /* If CODEPAGE did not work (maybe user deleted it or something) we try a keymap instead. This only works
207 * in MorphOS 2 and only if an old Amiga keymap is not used.
209 if (foundCodeset == NULL)
211 struct Library *KeymapBase;
213 KeymapBase = OpenLibrary("keymap.library", 51);
215 if (KeymapBase)
217 /* Since we requested V51 it is either V51 or newer */
218 if (KeymapBase->lib_Version > 51 || KeymapBase->lib_Revision >= 4)
220 #ifndef GetKeyMapCodepage
221 #define GetKeyMapCodepage(__p0) LP1(78, CONST_STRPTR , GetKeyMapCodepage, CONST struct KeyMap *, __p0, a0, , KEYMAP_BASE_NAME, 0, 0, 0, 0, 0, 0)
222 #endif
224 CONST_STRPTR codepage;
226 codepage = GetKeyMapCodepage(NULL);
228 if (codepage)
230 foundCodeset = codesetsFind(&lib->codesets, codepage);
232 D(DBF_STARTUP, "%s system default codeset: '%s' (keymap)", foundCodeset ? "found" : "not found", codepage);
236 CloseLibrary(KeymapBase);
240 #endif
242 // if we still do not have our default charset we try to load
243 // it from and environment variable ENVARC:CHARSET
244 if(foundCodeset == NULL)
246 char charset[80];
247 charset[0] = '\0';
249 if(GetVar("CHARSET", charset, sizeof(charset), 0) > 0)
251 foundCodeset = codesetsFind(&lib->codesets, charset);
254 D(DBF_STARTUP, "%s system default codeset: '%s' (ENV:CHARSET)", foundCodeset ? "found" : "not found", charset);
257 // and if even the CHARSET environment variable didn't work
258 // out we check the LANGUAGE env variable against our own
259 // internal fallback list
260 if(foundCodeset == NULL)
262 char language[80];
264 if(GetVar("LANGUAGE", language, sizeof(language), 0) > 0)
266 int i;
267 struct loc *curLoc = NULL;
268 BOOL found = FALSE;
270 for(i=0;;i++)
272 curLoc = (struct loc *)&locs[i];
273 if(curLoc == NULL || curLoc->name == NULL)
274 break;
276 if(!Strnicmp(language, curLoc->name, curLoc->len))
278 found = TRUE;
279 break;
283 if(found)
284 foundCodeset = codesetsFind(&lib->codesets, curLoc->codesetName);
287 D(DBF_STARTUP, "%s system default codeset: '%s' (ENV:LANGUAGE)", foundCodeset ? "found" : "not found",
288 foundCodeset ? foundCodeset->name : "?");
291 // and the very last check we do to find out the system's charset is
292 // to use locale.library.
293 if(foundCodeset == NULL)
295 struct Locale *locale;
297 if((locale = OpenLocale(NULL)))
299 int i;
300 char *language = locale->loc_LanguageName;
301 struct loc *curLoc = NULL;
302 BOOL found = FALSE;
304 for(i=0;;i++)
306 curLoc = (struct loc *)&locs[i];
307 if(curLoc == NULL || curLoc->name == NULL)
308 break;
310 if(!Strnicmp(language, curLoc->name, curLoc->len))
312 found = TRUE;
313 break;
317 CloseLocale(locale);
319 if(found)
320 foundCodeset = codesetsFind(&lib->codesets, curLoc->codesetName);
323 D(DBF_STARTUP, "%s system default codeset: '%s' (locale)", foundCodeset ? "found" : "not found",
324 foundCodeset ? foundCodeset->name : "?");
327 // and if even that very last test didn't work out we
328 // can just take the ISO-8859-1 charset as the fallback default
329 if(foundCodeset == NULL)
330 lib->systemCodeset = codesetsFind(&lib->codesets, "ISO-8859-1");
331 else
332 lib->systemCodeset = foundCodeset;
334 LEAVE();
337 /***********************************************************************/
339 ULONG
340 initBase(struct LibraryHeader *lib)
342 ENTER();
344 if((DOSBase = (APTR)OpenLibrary("dos.library", 37)) &&
345 GETINTERFACE(IDOS, DOSBase))
347 if((UtilityBase = OpenLibrary("utility.library", 37)) &&
348 GETINTERFACE(IUtility, UtilityBase))
350 // we have to please the internal utilitybase
351 // pointers of libnix and clib2
352 #if !defined(__NEWLIB__) && !defined(__AROS__)
353 __UtilityBase = (APTR)UtilityBase;
354 #if defined(__amigaos4__)
355 __IUtility = IUtility;
356 #endif
357 #endif
359 // setup the debugging stuff
360 #if defined(DEBUG)
361 SetupDebug();
362 #endif
364 #if defined(__amigaos4__)
365 if((DiskfontBase = OpenLibrary("diskfont.library", 50)) &&
366 GETINTERFACE(IDiskfont, DiskfontBase))
368 #endif
369 #if defined(__amigaos4__)
370 lib->pool = AllocSysObjectTags(ASOT_MEMPOOL, ASOPOOL_MFlags, MEMF_SHARED,
371 ASOPOOL_Puddle, 4096,
372 ASOPOOL_Threshold, 512,
373 TAG_DONE);
374 #else
375 lib->pool = CreatePool(MEMF_ANY, 4096, 512);
376 #endif
377 if(lib->pool != NULL)
379 if(codesetsInit(&lib->codesets))
381 lib->systemCodeset = (struct codeset *)lib->codesets.list.mlh_Head;
383 if((LocaleBase = (APTR)OpenLibrary("locale.library", 37)) &&
384 GETINTERFACE(ILocale, LocaleBase))
386 getSystemCodeset(lib);
389 RETURN(TRUE);
390 return TRUE;
393 #if defined(__amigaos4__)
395 #endif
399 freeBase(lib);
401 RETURN(FALSE);
402 return FALSE;
405 /***********************************************************************/