Adapted to recent renamings/adds of keyboard drivers.
[AROS.git] / workbench / prefs / input / prefs.c
blobc164264a075028ac831e7e04c28391edc1194177
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
9 /*********************************************************************************************/
11 #define SHOWFLAGS 1 /* Set to 1 to show Flags in the keylist */
13 #include <libraries/kms.h>
15 #include <proto/alib.h>
16 #include <proto/dos.h>
17 #include <proto/intuition.h>
18 #include <proto/iffparse.h>
19 #include <proto/utility.h>
21 #define DEBUG 0
22 #include <aros/debug.h>
24 #include "prefs.h"
25 #include "misc.h"
27 /*********************************************************************************************/
29 #define PREFS_PATH_ENVARC "ENVARC:SYS/input.prefs"
30 #define PREFS_PATH_ENV "ENV:SYS/input.prefs"
32 /*********************************************************************************************/
34 APTR mempool;
35 struct InputPrefs inputprefs;
36 struct KMSPrefs kmsprefs;
37 struct List keymap_list;
39 /*********************************************************************************************/
41 static const struct nameexp layout_expansion_table[] =
43 {"al" , "Albanian" , NULL },
44 {"usa" , "American" , "United_States" },
45 {"usa0" , "American" , "United_States" },
46 {"us" , "American" , "United_States" },
47 {"usx" , "American" , "United_States" },
48 {"d" , "Deutsch" , "Deutschland" },
49 {"b" , "Belge" , "Belgique" },
50 {"by" , "Belarussian" , NULL },
51 {"br" , "Brasileiro" , "Brasil" },
52 {"gb" , "British" , "United_Kingdom" },
53 {"gbx" , "British Extended" , "United_Kingdom" },
54 {"bg" , "Bulgarian" , "Bulgarija" },
55 {"cdn" , "Canadien Français" , "Canada_Français" },
56 {"cz" , "Czech" , "Cesko" },
57 {"dk" , "Dansk" , "Danmark" },
58 {"nl" , "Dutch" , "Nederland" },
59 {"dvx" , "Dvorak" , NULL },
60 {"usa2" , "Dvorak" , NULL },
61 {"dvl" , "Dvorak Left-handed" , NULL },
62 {"dvr" , "Dvorak Right-handed" , NULL },
63 {"gr" , "Ellinikí" , "Hellas" }, // Greak
64 {"irl" , "English Ireland" , "Ireland" },
65 {"e" , "Español" , "España" },
66 {"sp" , "Español no deadkeys" , "España" },
67 {"est" , "Estonian" , "Eesti" },
68 {"fin" , "Finnish" , "Suomi" },
69 {"f" , "Français" , "France" },
70 {"hr" , "Hrvatski" , "Hrvatska" }, // Croatia
71 {"is" , "Íslenska" , "Ísland" },
72 {"i" , "Italiana" , "Italia" },
73 {"la" , "Latin American" , NULL },
74 {"lv" , "Latvian" , NULL }, // Lettland
75 {"lt" , "Lithuanian" , "Lietuva" }, // Lithuania
76 {"h" , "Magyar" , "Magyarország" }, // Hungary
77 {"n" , "Norsk" , "Norge" },
78 {"pl" , "Polski" , "Polska" },
79 {"p" , "Português" , "Portugal" },
80 {"rus" , "Russian" , "Rossija" },
81 {"ch2" , "Suisse" , "Suisse" },
82 {"sk" , "Slovak" , "Slovakia" },
83 {"ch1" , "Schweizer" , "Schweiz" },
84 {"s" , "Svenskt" , "Sverige" },
85 {"tr" , "Türkçe" , "Türkiye" },
86 {"ua" , "Ukranian" , "Ukrajina" },
87 {NULL , NULL , NULL }
90 static const struct typeexp type_expansion_table[] = {
91 {"amiga", "Amiga" },
92 {"pc104", "PC 104"},
93 {"pc105", "PC 105"},
94 {"sun" , "Sun" },
95 {NULL , NULL }
98 /*********************************************************************************************/
100 static BOOL Prefs_Load(STRPTR from)
102 BOOL retval = FALSE;
104 BPTR fh = Open(from, MODE_OLDFILE);
105 if (fh)
107 retval = Prefs_ImportFH(fh);
108 Close(fh);
111 return retval;
114 /*********************************************************************************************/
116 static void ExpandName(struct ListviewEntry *entry)
118 char *sp;
119 char *type = NULL;
120 const struct nameexp *exp;
122 strcpy(entry->layoutname, entry->realname);
124 sp = strchr(entry->realname, '_');
125 if (sp)
128 * We have several variants of US keyboard, so
129 * we append type name.
131 if ((sp[1] == 'u' && sp[2] == 's'))
133 const struct typeexp *te;
135 *sp = 0;
136 for (te = type_expansion_table; te->shortname; te++)
138 if (!strcmp(entry->realname, te->shortname))
140 type = te->longname;
141 break;
144 *sp = '_';
146 sp++;
148 else
149 sp = entry->realname;
151 for (exp = layout_expansion_table; exp->shortname; exp++)
153 if (stricmp(exp->shortname, sp) == 0)
155 if (type)
156 snprintf(entry->layoutname, sizeof(entry->layoutname), "%s (%s)", exp->longname, type);
157 else
158 strcpy(entry->layoutname, exp->longname);
160 if (exp->flag != NULL)
162 #if SHOWFLAGS == 1
163 sprintf(entry->displayflag, "\033I[5:Locale:Flags/Countries/%s]", exp->flag);
164 #else
165 entry->displayflag[0] = '\0';
166 #endif
168 break;
175 /*********************************************************************************************/
178 void SortInNode(struct List *list, struct Node *node)
180 struct Node *sort, *prev = NULL;
182 ForeachNode(list, sort)
184 if (Stricmp(node->ln_Name, sort->ln_Name) < 0) break;
185 prev = sort;
188 Insert(list, node, prev);
191 void Prefs_ScanDirectory(STRPTR pattern, struct List *list, LONG entrysize)
193 struct AnchorPath ap;
194 struct ListviewEntry *entry, *entry2;
195 struct List templist;
196 STRPTR sp;
197 LONG error;
199 memset(&ap, 0, sizeof(ap));
200 NewList(&templist);
203 * Add default keymap.
204 * CHECKME: possibly too hacky. May be we should verify its presence in keymap.resource?
205 * How is it done in classic AmigaOS(tm) ?
207 entry = AllocPooled(mempool, entrysize);
208 if (entry)
210 strcpy(entry->layoutname, "American (Default)");
211 strcpy(entry->realname , DEFAULT_KEYMAP);
212 #if SHOWFLAGS == 1
213 strcpy(entry->displayflag, "\033I[5:Locale:Flags/Countries/United_States]");
214 #else
215 entry->displayflag[0] = '\0';
216 #endif
218 entry->node.ln_Name = entry->layoutname;
219 AddTail(&templist, &entry->node);
222 error = MatchFirst(pattern, &ap);
223 while((error == 0))
225 if (ap.ap_Info.fib_DirEntryType < 0)
227 entry = (struct ListviewEntry *)AllocPooled((APTR)mempool, entrysize);
228 if (entry)
230 entry->node.ln_Name = entry->layoutname;
231 strncpy(entry->realname, ap.ap_Info.fib_FileName, sizeof(entry->realname));
233 sp = strchr(entry->realname, '_');
234 if (sp)
235 sp++;
236 else
237 sp = entry->realname;
238 strcpy(entry->layoutname, sp);
240 ExpandName(entry);
241 AddTail(&templist, &entry->node);
244 error = MatchNext(&ap);
246 MatchEnd(&ap);
248 /* Sort by Layout Name */
250 ForeachNodeSafe(&templist, entry, entry2)
252 Remove(&entry->node);
253 SortInNode(list, &entry->node);
257 /*********************************************************************************************/
259 static LONG stopchunks[] =
261 ID_PREF, ID_INPT,
262 ID_PREF, ID_KMSW
265 BOOL Prefs_ImportFH(BPTR fh)
267 struct FileInputPrefs loadprefs;
268 struct FileKMSPrefs loadkmsprefs;
269 struct IFFHandle *iff;
270 ULONG size;
271 BOOL retval = FALSE;
273 memset(&loadprefs, 0, sizeof(loadprefs));
275 if ((iff = AllocIFF()))
277 iff->iff_Stream = (IPTR)fh;
278 if (fh != BNULL)
280 D(Printf("LoadPrefs: stream opened.\n"));
282 InitIFFasDOS(iff);
284 if (!OpenIFF(iff, IFFF_READ))
286 D(Printf("LoadPrefs: OpenIFF okay.\n"));
288 if (!StopChunks(iff, stopchunks, 2))
290 D(Printf("LoadPrefs: StopChunk okay.\n"));
291 retval = TRUE;
293 while (!ParseIFF(iff, IFFPARSE_SCAN))
295 struct ContextNode *cn;
297 D(Printf("LoadPrefs: ParseIFF okay.\n"));
299 cn = CurrentChunk(iff);
300 size = cn->cn_Size;
302 switch (cn->cn_ID)
304 case ID_INPT:
305 D(Printf("LoadPrefs: INPT chunk\n"));
307 if (size > sizeof(struct FileInputPrefs))
308 size = sizeof(struct FileInputPrefs);
310 if (ReadChunkBytes(iff, &loadprefs, size) == size)
312 D(Printf("LoadPrefs: Reading chunk successful.\n"));
314 CopyMem(loadprefs.ip_Keymap, inputprefs.ip_Keymap, sizeof(loadprefs.ip_Keymap));
315 inputprefs.ip_PointerTicks = ARRAY_TO_WORD(loadprefs.ip_PointerTicks);
316 inputprefs.ip_DoubleClick.tv_secs = ARRAY_TO_LONG(loadprefs.ip_DoubleClick_secs);
317 inputprefs.ip_DoubleClick.tv_micro = ARRAY_TO_LONG(loadprefs.ip_DoubleClick_micro);
318 inputprefs.ip_KeyRptDelay.tv_secs = ARRAY_TO_LONG(loadprefs.ip_KeyRptDelay_secs);
319 inputprefs.ip_KeyRptDelay.tv_micro = ARRAY_TO_LONG(loadprefs.ip_KeyRptDelay_micro);
320 inputprefs.ip_KeyRptSpeed.tv_secs = ARRAY_TO_LONG(loadprefs.ip_KeyRptSpeed_secs);
321 inputprefs.ip_KeyRptSpeed.tv_micro = ARRAY_TO_LONG(loadprefs.ip_KeyRptSpeed_micro);
322 inputprefs.ip_MouseAccel = ARRAY_TO_WORD(loadprefs.ip_MouseAccel);
323 inputprefs.ip_ClassicKeyboard = ARRAY_TO_LONG(loadprefs.ip_ClassicKeyboard);
324 CopyMem(loadprefs.ip_KeymapName, inputprefs.ip_KeymapName, sizeof(loadprefs.ip_KeymapName));
325 inputprefs.ip_SwitchMouseButtons = loadprefs.ip_SwitchMouseButtons[3];
327 D(Printf("LoadPrefs: SwitchMouseButtons: %ld\n", inputprefs.ip_SwitchMouseButtons));
329 else
330 retval = FALSE;
331 break;
333 case ID_KMSW:
334 D(Printf("LoadPrefs: KMSW chunk\n"));
336 if (size > sizeof(struct FileKMSPrefs))
337 size = sizeof(struct FileKMSPrefs);
339 if (ReadChunkBytes(iff, &loadkmsprefs, size) == size)
341 D(Printf("LoadPrefs: Reading chunk successful.\n"));
343 kmsprefs.kms_Enabled = loadkmsprefs.kms_Enabled;
344 kmsprefs.kms_Reserved = loadkmsprefs.kms_Reserved;
345 kmsprefs.kms_SwitchQual = ARRAY_TO_WORD(loadkmsprefs.kms_SwitchQual);
346 kmsprefs.kms_SwitchCode = ARRAY_TO_WORD(loadkmsprefs.kms_SwitchCode);
347 CopyMem(loadkmsprefs.kms_AltKeymap, kmsprefs.kms_AltKeymap, sizeof(kmsprefs.kms_AltKeymap));
349 else
350 retval = FALSE;
351 break;
353 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
354 } /* if (!StopChunk(iff, ID_PREF, ID_INPT)) */
355 CloseIFF(iff);
356 } /* if (!OpenIFF(iff, IFFF_READ)) */
357 } /* if (fh != NULL) */
358 FreeIFF(iff);
359 } /* if ((iff = AllocIFF())) */
361 return retval;
364 /*********************************************************************************************/
366 BOOL Prefs_ExportFH(BPTR fh)
368 struct FileInputPrefs saveprefs;
369 struct FileKMSPrefs savekmsprefs;
370 struct IFFHandle *iff;
371 BOOL retval = FALSE;
372 #if 0 /* unused */
373 BOOL delete_if_error = FALSE;
374 #endif
376 D(Printf("SavePrefs: SwitchMouseButtons: %ld\n", inputprefs.ip_SwitchMouseButtons));
378 CopyMem(inputprefs.ip_Keymap, saveprefs.ip_Keymap, sizeof(saveprefs.ip_Keymap));
379 WORD_TO_ARRAY(inputprefs.ip_PointerTicks, saveprefs.ip_PointerTicks);
380 LONG_TO_ARRAY(inputprefs.ip_DoubleClick.tv_secs , saveprefs.ip_DoubleClick_secs);
381 LONG_TO_ARRAY(inputprefs.ip_DoubleClick.tv_micro, saveprefs.ip_DoubleClick_micro);
382 LONG_TO_ARRAY(inputprefs.ip_KeyRptDelay.tv_secs , saveprefs.ip_KeyRptDelay_secs);
383 LONG_TO_ARRAY(inputprefs.ip_KeyRptDelay.tv_micro, saveprefs.ip_KeyRptDelay_micro);
384 LONG_TO_ARRAY(inputprefs.ip_KeyRptSpeed.tv_secs , saveprefs.ip_KeyRptSpeed_secs);
385 LONG_TO_ARRAY(inputprefs.ip_KeyRptSpeed.tv_micro, saveprefs.ip_KeyRptSpeed_micro);
386 WORD_TO_ARRAY(inputprefs.ip_MouseAccel, saveprefs.ip_MouseAccel);
387 LONG_TO_ARRAY(inputprefs.ip_ClassicKeyboard, saveprefs.ip_ClassicKeyboard);
388 CopyMem(inputprefs.ip_KeymapName, saveprefs.ip_KeymapName, sizeof(saveprefs.ip_KeymapName));
389 saveprefs.ip_SwitchMouseButtons[0] = 0;
390 saveprefs.ip_SwitchMouseButtons[1] = 0;
391 saveprefs.ip_SwitchMouseButtons[2] = 0;
392 saveprefs.ip_SwitchMouseButtons[3] = inputprefs.ip_SwitchMouseButtons;
394 savekmsprefs.kms_Enabled = kmsprefs.kms_Enabled;
395 savekmsprefs.kms_Reserved = kmsprefs.kms_Reserved;
396 WORD_TO_ARRAY(kmsprefs.kms_SwitchQual, savekmsprefs.kms_SwitchQual);
397 WORD_TO_ARRAY(kmsprefs.kms_SwitchCode, savekmsprefs.kms_SwitchCode);
398 CopyMem(kmsprefs.kms_AltKeymap, savekmsprefs.kms_AltKeymap, sizeof(savekmsprefs.kms_AltKeymap));
400 if ((iff = AllocIFF()))
402 iff->iff_Stream = (IPTR)fh;
403 if (iff->iff_Stream)
405 D(Printf("SavePrefs: stream opened.\n"));
407 #if 0 /* unused */
408 delete_if_error = TRUE;
409 #endif
411 InitIFFasDOS(iff);
413 if (!OpenIFF(iff, IFFF_WRITE))
415 D(Printf("SavePrefs: OpenIFF okay.\n"));
417 if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN))
419 D(Printf("SavePrefs: PushChunk(FORM) okay.\n"));
421 if (!PushChunk(iff, ID_PREF, ID_PRHD, sizeof(struct FilePrefHeader)))
423 struct FilePrefHeader head;
425 D(Printf("SavePrefs: PushChunk(PRHD) okay.\n"));
427 head.ph_Version = 0; // FIXME: should be PHV_CURRENT, but see <prefs/prefhdr.h>
428 head.ph_Type = 0;
429 head.ph_Flags[0] =
430 head.ph_Flags[1] =
431 head.ph_Flags[2] =
432 head.ph_Flags[3] = 0;
434 if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head))
436 D(Printf("SavePrefs: WriteChunkBytes(PRHD) okay.\n"));
438 PopChunk(iff);
440 if (!PushChunk(iff, ID_PREF, ID_INPT, sizeof(saveprefs)))
442 D(Printf("SavePrefs: PushChunk(INPT) okay.\n"));
444 if (WriteChunkBytes(iff, &saveprefs, sizeof(saveprefs)) == sizeof(saveprefs))
446 D(Printf("SavePrefs: WriteChunkBytes(INPT) okay.\n"));
448 retval = TRUE;
451 PopChunk(iff);
453 } /* if (!PushChunk(iff, ID_PREF, ID_INPT, sizeof(saveprefs))) */
455 if (!PushChunk(iff, ID_PREF, ID_KMSW, sizeof(savekmsprefs)))
457 if (WriteChunkBytes(iff, &savekmsprefs, sizeof(savekmsprefs)) == sizeof(savekmsprefs))
458 retval = retval && TRUE;
460 PopChunk(iff);
462 } /* if (!PushChunk(iff, ID_PREF, ID_INPT, sizeof(saveprefs))) */
464 } /* if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head)) */
465 else
467 PopChunk(iff);
470 } /* if (!PushChunk(iff, ID_PREF, ID_PRHD, sizeof(struct PrefHeader))) */
472 PopChunk(iff);
474 } /* if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN)) */
476 CloseIFF(iff);
478 } /* if (!OpenIFF(iff, IFFFWRITE)) */
481 } /* if (iff->iff_Stream)) */
483 FreeIFF(iff);
485 } /* if ((iff = AllocIFF())) */
487 #if 0 /* unused */
488 if (!retval && delete_if_error)
490 DeleteFile(filename);
492 #endif
494 return retval;
497 /*********************************************************************************************/
499 BOOL Prefs_HandleArgs(STRPTR from, BOOL use, BOOL save)
501 BPTR fh;
503 if (from)
505 if (!Prefs_Load(from))
507 ShowMessage("Can't read from input file");
508 return FALSE;
511 else
513 if (!Prefs_Load(PREFS_PATH_ENV))
515 if (!Prefs_Load(PREFS_PATH_ENVARC))
517 ShowMessage
519 "Can't read from file " PREFS_PATH_ENVARC
520 ".\nUsing default values."
522 Prefs_Default();
527 if (use || save)
529 fh = Open(PREFS_PATH_ENV, MODE_NEWFILE);
530 if (fh)
532 Prefs_ExportFH(fh);
533 Close(fh);
535 else
537 ShowMessage("Can't open " PREFS_PATH_ENV " for writing.");
540 if (save)
542 fh = Open(PREFS_PATH_ENVARC, MODE_NEWFILE);
543 if (fh)
545 Prefs_ExportFH(fh);
546 Close(fh);
548 else
550 ShowMessage("Can't open " PREFS_PATH_ENVARC " for writing.");
553 return TRUE;
556 /*********************************************************************************************/
558 BOOL Prefs_Default(void)
560 strcpy(inputprefs.ip_Keymap, DEFAULT_KEYMAP);
561 inputprefs.ip_PointerTicks = 1;
562 inputprefs.ip_DoubleClick.tv_secs = 0;
563 inputprefs.ip_DoubleClick.tv_micro = 500000;
564 inputprefs.ip_KeyRptDelay.tv_secs = 0;
565 inputprefs.ip_KeyRptDelay.tv_micro = 500000;
566 inputprefs.ip_KeyRptSpeed.tv_secs = 0;
567 inputprefs.ip_KeyRptSpeed.tv_micro = 40000;
568 inputprefs.ip_MouseAccel = 1;
569 inputprefs.ip_ClassicKeyboard = 0;
570 strcpy(inputprefs.ip_KeymapName, DEFAULT_KEYMAP);
571 inputprefs.ip_SwitchMouseButtons = FALSE;
573 kmsprefs.kms_Enabled = FALSE;
574 kmsprefs.kms_SwitchQual = KMS_QUAL_DISABLE;
575 kmsprefs.kms_SwitchCode = KMS_CODE_NOKEY;
576 kmsprefs.kms_AltKeymap[0] = 0;
578 return TRUE;