update copyright
[AROS.git] / workbench / prefs / locale / page_language.c
blob217032a2b43e5baa7da6660b1aa42f1f35864b3e
1 /*
2 Copyright © 2003-2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/debug.h>
8 #include <proto/alib.h>
9 #include <proto/codesets.h>
10 #include <proto/intuition.h>
11 #include <proto/utility.h>
12 #include <proto/muimaster.h>
14 #include <zune/customclasses.h>
15 #include <zune/prefseditor.h>
17 #include "locale.h"
18 #include "prefs.h"
19 #include "misc.h"
20 #include "registertab.h"
21 #include "page_language.h"
23 /*** Instance Data **********************************************************/
25 struct Language_DATA
27 int nr_languages;
28 int nr_preferred;
30 Object *child;
31 Object *available;
32 Object *preferred;
33 Object *charset;
34 Object *cslist;
35 Object *cslistview;
36 Object *popup;
37 Object *clear;
38 Object *prefs;
40 char **strings_available;
41 char **strings_preferred;
42 STRPTR *strings_charsets;
44 char *result[10]; /* result array for Gadget2Prefs */
47 struct MUI_CustomClass *Language_CLASS;
49 static struct Hook hook_available;
50 static struct Hook hook_preferred;
51 static struct Hook hook_clear;
53 /*** Helpers *****************************************************************/
55 STATIC VOID update_language_lists(struct Language_DATA *data)
57 struct LanguageEntry *entry;
58 int a;
59 int p;
61 a=0;
62 p=0;
63 ForeachNode(&language_list, entry)
65 if(entry->preferred)
67 data->strings_preferred[p] = entry->lve.node.ln_Name;
68 p++;
70 else
72 data->strings_available[a] = entry->lve.node.ln_Name;
73 a++;
76 data->strings_available[a] = NULL;
77 data->strings_preferred[p] = NULL;
80 STATIC VOID init_language_lists(struct Language_DATA *data)
83 struct LanguageEntry *entry;
84 int i;
86 data->nr_languages = 0;
87 ForeachNode(&language_list, entry)
89 D(bug("[LocalePrefs-LanguageClass] language %s\n",entry->lve.node.ln_Name));
90 entry->preferred = FALSE;
92 /* max 10 preferred langs, see prefs/locale.h */
93 for (i = 0; i < 10 && entry->preferred == FALSE && localeprefs.lp_PreferredLanguages[i][0]; i++)
95 if (Stricmp(localeprefs.lp_PreferredLanguages[i], entry->lve.node.ln_Name) == 0)
97 D(bug("[LocalePrefs-LanguageClass] %s is preferred\n",
98 entry->lve.node.ln_Name));
99 entry->preferred = TRUE;
102 data->nr_languages++;
105 D(bug("[LocalePrefs-LanguageClass]: nr of languages: %d\n",data->nr_languages));
107 data->strings_available = AllocVec(sizeof(char *) * (data->nr_languages+1), MEMF_CLEAR);
108 data->strings_preferred = AllocVec(sizeof(char *) * (data->nr_languages+1), MEMF_CLEAR);
110 update_language_lists(data);
113 /*** Hooks ******************************************************************
115 * hook_func_available
116 * handles double clicks on the available languages
118 * hook_func_preferred
119 * handles double clicks on the preferred languages
121 * hook_func_clear
122 * handles clearing of preferred languages
124 ****************************************************************************/
126 STATIC VOID func_move_to_selected(char* selstr, struct Language_DATA *data)
128 struct LanguageEntry *entry;
129 unsigned int i = 0;
130 char *test;
132 D(bug("[LocalePrefs-LanguageClass] func_move_to_selected(%s,..)\n", selstr));
134 if(selstr) {
135 ForeachNode(&language_list, entry)
137 if (stricmp(selstr, entry->lve.node.ln_Name) == 0)
139 DoMethod(data->preferred,
140 MUIM_List_InsertSingle, entry->lve.node.ln_Name,
141 MUIV_List_Insert_Bottom);
143 entry->preferred = TRUE;
148 /* we could use
149 * DoMethod(data->available,MUIM_List_Remove, MUIV_List_Remove_Active);
150 * of course, but I also want to be able to use that for
151 * the Set method.
154 GET(data->available,MUIA_List_Entries,&i);
155 while(i)
157 i--;
158 DoMethod(data->available, MUIM_List_GetEntry, i, &test);
159 if (stricmp(selstr, test) == 0)
161 DoMethod(data->available, MUIM_List_Remove, i);
162 i = 0;
167 AROS_UFH2
169 void, hook_func_available,
170 AROS_UFHA(struct Hook *, hook, A0),
171 AROS_UFHA(APTR, obj, A2)
174 AROS_USERFUNC_INIT
176 struct Language_DATA *data= hook->h_Data;
177 char *selstr;
179 D(bug("[LocalePrefs-LanguageClass] hook_func_available\n"));
181 DoMethod(obj,MUIM_List_GetEntry,
182 MUIV_List_GetEntry_Active, &selstr);
184 func_move_to_selected(selstr, data);
186 AROS_USERFUNC_EXIT
189 AROS_UFH2
191 void, hook_func_preferred,
192 AROS_UFHA(struct Hook *, hook, A0),
193 AROS_UFHA(APTR, obj, A2)
196 AROS_USERFUNC_INIT
198 struct Language_DATA *data= hook->h_Data;
199 char *selstr;
200 struct LanguageEntry *entry;
202 D(bug("[LocalePrefs-LanguageClass] hook_func_preferred\n"));
204 DoMethod(obj,MUIM_List_GetEntry,
205 MUIV_List_GetEntry_Active, &selstr);
207 if(selstr)
209 D(bug("move: %s\n",selstr));
211 ForeachNode(&language_list, entry)
213 if (strcmp(selstr, entry->lve.node.ln_Name) == 0)
215 DoMethod(data->available,
216 MUIM_List_InsertSingle, entry->lve.node.ln_Name,
217 MUIV_List_Insert_Sorted);
218 entry->preferred = FALSE;
221 DoMethod(obj, MUIM_List_Remove, MUIV_List_Remove_Active);
224 AROS_USERFUNC_EXIT
227 STATIC VOID func_clear(struct Language_DATA *data)
229 struct LanguageEntry *entry;
231 D(bug("[LocalePrefs-LanguageClass] func_clear\n"));
233 /* clear it */
234 DoMethod(data->preferred, MUIM_List_Clear);
236 /* add all old preferred languages again */
237 DoMethod(data->available, MUIM_Group_InitChange);
238 ForeachNode(&language_list, entry)
240 if(entry->preferred)
242 entry->preferred = FALSE;
243 DoMethod(data->available,
244 MUIM_List_InsertSingle, entry->lve.node.ln_Name,
245 MUIV_List_Insert_Bottom);
248 DoMethod(data->available, MUIM_List_Sort);
249 DoMethod(data->available, MUIM_Group_ExitChange);
253 AROS_UFH2(
254 void, hook_func_clear,
255 AROS_UFHA(struct Hook *, hook, A0),
256 AROS_UFHA(APTR *, obj, A2)
259 AROS_USERFUNC_INIT
261 struct Language_DATA *data = hook->h_Data;
263 func_clear(data);
264 SET(data->prefs, MUIA_PrefsEditor_Changed, TRUE);
266 AROS_USERFUNC_EXIT
269 AROS_UFH3
271 void, charset_popup_to_string,
272 AROS_UFHA(struct Hook*, hook, A0),
273 AROS_UFHA(Object *, list, A2),
274 AROS_UFHA(Object *, string, A1)
277 AROS_USERFUNC_INIT
279 STRPTR listentry;
280 STRPTR oldentry;
282 GetAttr(MUIA_Text_Contents, string, (IPTR *)&oldentry);
283 DoMethod(list, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, (IPTR)&listentry);
284 if (strcmp(listentry, oldentry))
286 SetAttrs(string, MUIA_Text_Contents, listentry, TAG_DONE);
287 SetAttrs(hook->h_Data, MUIA_PrefsEditor_Changed, TRUE, TAG_DONE);
290 AROS_USERFUNC_EXIT
293 AROS_UFH3
295 ULONG, charset_string_to_popup,
296 AROS_UFHA(struct Hook*, hook, A0),
297 AROS_UFHA(Object *, list, A2),
298 AROS_UFHA(Object *, str, A1)
301 AROS_USERFUNC_INIT
303 STRPTR strtext, listentry;
304 LONG index;
306 GetAttr(MUIA_Text_Contents, str, (IPTR *)&strtext);
308 for(index = 0; ; index++)
310 DoMethod(list, MUIM_List_GetEntry, index, (IPTR)&listentry);
312 if (!listentry)
314 SET(list, MUIA_List_Active, MUIV_List_Active_Off);
315 break;
318 if (stricmp(strtext, listentry) == 0)
320 SET(list, MUIA_List_Active, index);
321 break;
325 return TRUE;
327 AROS_USERFUNC_EXIT
330 static struct Hook charset_popup_to_string_hook =
332 {NULL, NULL},
333 (HOOKFUNC)AROS_ASMSYMNAME(charset_popup_to_string),
334 NULL,
335 NULL
338 static struct Hook charset_string_to_popup_hook =
340 {NULL, NULL},
341 (HOOKFUNC)AROS_ASMSYMNAME(charset_string_to_popup),
342 NULL,
343 NULL
346 /*** Methods ****************************************************************
350 static void free_strings(struct Language_DATA *data)
352 if (data->strings_charsets)
354 CodesetsFreeA(data->strings_charsets, NULL);
355 data->strings_charsets = NULL;
357 if(data->strings_available)
359 FreeVec(data->strings_available);
360 data->strings_available = NULL;
363 if(data->strings_preferred)
365 FreeVec(data->strings_preferred);
366 data->strings_preferred = NULL;
371 static Object *handle_New_error(Object *obj, struct IClass *cl, char *error)
373 struct Language_DATA *data;
375 ShowMessage(error);
376 D(bug("[LocalePrefs-LanguageClass] %s\n"));
378 if(!obj)
379 return NULL;
381 data = INST_DATA(cl, obj);
383 if(data->clear)
385 DisposeObject(data->clear);
386 data->clear=NULL;
389 if(data->available)
391 DisposeObject(data->available);
392 data->available=NULL;
395 if(data->preferred)
397 DisposeObject(data->preferred);
398 data->preferred = NULL;
401 if(data->child)
403 DisposeObject(data->child);
404 data->child = NULL;
407 if (data->charset) {
408 DisposeObject(data->charset);
409 data->charset = NULL;
412 if (data->cslist) {
413 DisposeObject(data->cslist);
414 data->cslist = NULL;
417 if (data->cslistview) {
418 DisposeObject(data->cslistview);
419 data->cslist = NULL;
422 if (data->popup) {
423 DisposeObject(data->popup);
424 data->popup = NULL;
427 free_strings(data);
429 CoerceMethod(cl, obj, OM_DISPOSE);
430 return NULL;
433 Object *Language__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
435 struct Language_DATA *data;
436 struct TagItem *tstate, *tag;
438 D(bug("[LocalePrefs-LanguageClass] Language Class New\n"));
441 * we create self first and then create the child,
442 * so we have self->data available already
445 obj = (Object *) DoSuperNewTags
447 cl, obj, NULL,
448 TAG_DONE
451 if (obj == NULL)
453 return handle_New_error(obj, cl, "ERROR: Unable to create object!\n");
456 data = INST_DATA(cl, obj);
458 tstate=((struct opSet *)msg)->ops_AttrList;
459 while ((tag = (struct TagItem *) NextTagItem((APTR) &tstate)))
461 switch (tag->ti_Tag)
463 case MUIA_UserData:
464 data->prefs = (Object *) tag->ti_Data;
465 break;
469 if(!data->prefs)
470 return handle_New_error(obj, cl, "ERROR: MA_PrefsObject not supplied!\n");
472 init_language_lists(data);
473 data->strings_charsets = CodesetsSupportedA(NULL);
475 data->clear = MUI_MakeObject(MUIO_Button, __(MSG_GAD_CLEAR_LANGUAGES));
477 data->available = ListviewObject, MUIA_Listview_List,
478 ListObject,
479 InputListFrame,
480 MUIA_List_SourceArray, data->strings_available,
481 End,
482 End;
484 data->preferred = ListviewObject, MUIA_Listview_List,
485 ListObject,
486 InputListFrame,
487 MUIA_List_SourceArray, data->strings_preferred,
488 End,
489 End;
491 data->charset = TextObject,
492 TextFrame,
493 MUIA_Background, MUII_TextBack,
494 End;
496 data->cslist = ListObject,
497 MUIA_Frame, MUIV_Frame_InputList,
498 MUIA_Background, MUII_ListBack,
499 MUIA_List_AutoVisible, TRUE,
500 MUIA_List_SourceArray, data->strings_charsets,
501 End;
503 data->cslistview = ListviewObject,
504 MUIA_Listview_List, data->cslist,
505 End;
507 charset_popup_to_string_hook.h_Data = data->prefs;
509 data->popup = PopobjectObject,
510 MUIA_Popobject_Object, data->cslistview,
511 MUIA_Popobject_StrObjHook, &charset_string_to_popup_hook,
512 MUIA_Popobject_ObjStrHook, &charset_popup_to_string_hook,
513 MUIA_Popstring_Button, PopButton(MUII_PopUp),
514 MUIA_Popstring_String, data->charset,
515 End;
517 if(!data->clear || !data->available || !data->preferred || !data->charset || !data->cslist ||
518 !data->cslistview || !data->popup)
519 return handle_New_error(obj,cl,"ERROR: MakeObject failed\n");
521 DoMethod(data->cslist, MUIM_List_Sort);
522 DoMethod(data->cslist, MUIM_List_InsertSingle, _(MSG_NOT_SPECIFIED), MUIV_List_Insert_Top);
524 data->child = VGroup,
525 Child, HGroup,
526 Child, VGroup, /* Available Languages */
527 Child, CLabel1(_(MSG_GAD_AVAIL_LANGUAGES)),
528 Child, data->available,
529 End,
530 Child, VGroup, /* Preferred Languages */
531 Child, CLabel1(_(MSG_GAD_PREF_LANGUAGES)),
532 Child, data->preferred,
533 End,
534 End,
535 Child, data->clear,
536 Child, HGroup,
537 Child, CLabel1(_(MSG_CHARACTER_SET)),
538 Child, data->popup,
539 End,
540 End;
542 if(!data->child)
543 return handle_New_error(obj, cl, "ERROR: create child failed\n");
545 /* add to self */
546 DoMethod(obj, OM_ADDMEMBER, data->child);
548 /* setup hooks */
549 DoMethod(data->cslistview, MUIM_Notify, MUIA_Listview_DoubleClick, TRUE, data->popup, 2, MUIM_Popstring_Close, TRUE);
551 /* move hooks */
552 hook_available.h_Entry = (HOOKFUNC) hook_func_available;
553 hook_available.h_Data = data ;
554 DoMethod
556 data->available, MUIM_Notify, MUIA_Listview_DoubleClick, MUIV_EveryTime, data->available,
557 2, MUIM_CallHook, (IPTR) &hook_available
560 hook_preferred.h_Entry = (HOOKFUNC) hook_func_preferred;
561 hook_preferred.h_Data = data ;
562 DoMethod
564 data->preferred, MUIM_Notify, MUIA_Listview_DoubleClick, MUIV_EveryTime, data->preferred,
565 2, MUIM_CallHook, (IPTR) &hook_preferred
568 /* clear hook */
569 hook_clear.h_Entry = (HOOKFUNC) hook_func_clear;
570 hook_clear.h_Data = data ;
571 DoMethod
573 data->clear, MUIM_Notify, MUIA_Selected, MUIV_EveryTime, data->preferred,
574 2, MUIM_CallHook, (IPTR) &hook_clear
577 /* changed hooks */
578 DoMethod
580 data->preferred, MUIM_Notify, MUIA_Listview_DoubleClick, MUIV_EveryTime, (IPTR) data->prefs,
581 3, MUIM_Set, MUIA_PrefsEditor_Changed, TRUE
583 DoMethod
585 data->available, MUIM_Notify, MUIA_Listview_DoubleClick, MUIV_EveryTime, (IPTR) data->prefs,
586 3, MUIM_Set, MUIA_PrefsEditor_Changed, TRUE
589 return obj;
592 /*** Get ******************************************************************/
594 static IPTR Language__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
596 struct Language_DATA *data = INST_DATA(cl, obj);
597 IPTR rc;
598 IPTR i;
600 switch (msg->opg_AttrID)
602 case MUIA_Language_Preferred: /* return array of preferred language strings */
603 for (i = 0; i < 10; i++)
605 DoMethod(data->preferred, MUIM_List_GetEntry, i, &data->result[i]);
607 rc = (IPTR) data->result;
608 break;
609 case MUIA_Language_Characterset:
610 GetAttr(MUIA_List_Active, data->cslist, (IPTR *)&i);
611 D(bug("[LocalePrefs-LanguageClass] Get: Active character set entry is %d\n", i));
612 if ((i == 0) || (i == MUIV_List_Active_Off))
613 *msg->opg_Storage = 0;
614 else
615 GetAttr(MUIA_Text_Contents, data->charset, msg->opg_Storage);
616 return TRUE;
617 default:
618 return DoSuperMethodA(cl, obj, (Msg)msg);
621 *msg->opg_Storage = rc;
622 return TRUE;
625 /*** Set ******************************************************************/
626 static IPTR Language__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
628 struct Language_DATA *data = INST_DATA(cl, obj);
629 struct TagItem *tstate, *tag;
630 ULONG update;
631 ULONG i;
633 tstate = msg->ops_AttrList;
634 update = FALSE;
636 while ((tag = (struct TagItem *) NextTagItem((APTR) &tstate)))
638 switch (tag->ti_Tag)
640 case MUIA_Language_Preferred:
641 /* clear preferred */
642 func_clear(data);
643 for (i = 0; i < 10; i++)
645 if(localeprefs.lp_PreferredLanguages[i][0] != '\0')
647 func_move_to_selected(localeprefs.lp_PreferredLanguages[i], data);
651 update = TRUE;
652 break;
653 case MUIA_Language_Characterset:
655 char *charset = (char *)tag->ti_Data;
657 if (!charset || !*charset)
658 DoMethod(data->cslist, MUIM_List_GetEntry, 0, (IPTR *)&charset);
659 SetAttrs(data->charset, MUIA_Text_Contents, charset, TAG_DONE);
661 break;
663 default:
664 return DoSuperMethodA(cl, obj, (Msg)msg);
668 if(update)
670 MUI_Redraw(obj, MADF_DRAWOBJECT);
673 return TRUE;
676 static IPTR Language__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
678 struct Language_DATA *data = INST_DATA(cl, obj);
680 D(bug("[LocalePrefs-LanguageClass] OM_DISPOSE()\n"));
682 free_strings(data);
684 return DoSuperMethodA(cl, obj, msg);
687 /*** Setup ******************************************************************/
688 ZUNE_CUSTOMCLASS_4
690 Language, NULL, MUIC_Group, NULL,
691 OM_NEW, struct opSet *,
692 OM_SET, struct opSet *,
693 OM_GET, struct opGet *,
694 OM_DISPOSE, Msg