corrections
[AROS.git] / workbench / prefs / input / prefs.c
blobcb6794a9bbd8de6abcf423d02b89f07447134cf3
1 /*
2 Copyright © 1995-2013, 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" , "Countries/Albania" },
44 {"usa" , "American" , "Countries/United_States" },
45 {"usa0" , "American" , "Countries/United_States" },
46 {"us" , "American" , "Countries/United_States" },
47 {"usx" , "American" , "Countries/United_States" },
48 {"col" , "Colemak (US)" , "Countries/United_States" },
49 {"d" , "Deutsch" , "Countries/Germany" },
50 {"b" , "Belge" , "Countries/Belgium" },
51 {"by" , "Belarussian" , "Countries/Belarus" },
52 {"br" , "Brasileiro" , "Countries/Brazil" },
53 {"gb" , "British" , "Countries/United_Kingdom"},
54 {"gbx" , "British Extended" , "Countries/United_Kingdom"},
55 {"bg" , "Bulgarian" , "Countries/Bulgaria" },
56 {"cdn" , "Canadien Français" , "Countries/Quebec" },
57 {"cz" , "Czech" , "Countries/Czech_Republic"},
58 {"dk" , "Dansk" , "Countries/Denmark" },
59 {"nl" , "Dutch" , "Countries/Netherlands" },
60 {"dvx" , "Dvorak" , "Misc/Unknown" },
61 {"usa2" , "Dvorak" , "Misc/Unknown" },
62 {"dvl" , "Dvorak Left-handed" , "Misc/Unknown" },
63 {"dvr" , "Dvorak Right-handed" , "Misc/Unknown" },
64 {"irl" , "English Ireland" , "Countries/Ireland" },
65 {"e" , "Español" , "Countries/Spain" },
66 {"sp" , "Español no deadkeys" , "Countries/Spain" },
67 {"est" , "Estonian" , "Countries/Estonia" },
68 {"fin" , "Finnish" , "Countries/Finland" },
69 {"f" , "Français" , "Countries/France" },
70 {"gr" , "Hellenic" , "Countries/Greece" },
71 {"hr" , "Hrvatski" , "Countries/Croatia" },
72 {"is" , "Íslenska" , "Countries/Iceland" },
73 {"i" , "Italiana" , "Countries/Italy" },
74 {"la" , "Latin American" , "Misc/Unknown" },
75 {"lv" , "Latvian" , "Countries/Latvia" },
76 {"lt" , "Lithuanian" , "Countries/Lithuania" },
77 {"h" , "Magyar" , "Countries/Hungary" },
78 {"n" , "Norsk" , "Countries/Norway" },
79 {"pl" , "Polski" , "Countries/Poland" },
80 {"p" , "Português" , "Countries/Portugal" },
81 {"rus" , "Russian" , "Countries/Russia" },
82 {"ch2" , "Suisse" , "Countries/Switzerland" },
83 {"sk" , "Slovak" , "Countries/Slovakia" },
84 {"ch1" , "Schweizer" , "Countries/Switzerland" },
85 {"s" , "Svenskt" , "Countries/Sweden" },
86 {"tr" , "Türkçe" , "Countries/Turkey" },
87 {"ua" , "Ukranian" , "Countries/Ukraine" },
88 {NULL , NULL , NULL }
91 static const struct typeexp type_expansion_table[] = {
92 {"amiga", "Amiga" },
93 {"pc104", "PC 104"},
94 {"pc105", "PC 105"},
95 {"sun" , "Sun" },
96 {NULL , NULL }
99 /*********************************************************************************************/
101 static BOOL Prefs_Load(STRPTR from)
103 BOOL retval = FALSE;
105 BPTR fh = Open(from, MODE_OLDFILE);
106 if (fh)
108 retval = Prefs_ImportFH(fh);
109 Close(fh);
112 return retval;
115 /*********************************************************************************************/
117 static void ExpandName(struct ListviewEntry *entry)
119 char *sp;
120 char *type = NULL;
121 const struct nameexp *exp;
123 strcpy(entry->layoutname, entry->realname);
125 sp = strchr(entry->realname, '_');
126 if (sp)
129 * We have several variants of US keyboard, so
130 * we append type name.
132 if ((sp[1] == 'u' && sp[2] == 's'))
134 const struct typeexp *te;
136 *sp = 0;
137 for (te = type_expansion_table; te->shortname; te++)
139 if (!strcmp(entry->realname, te->shortname))
141 type = te->longname;
142 break;
145 *sp = '_';
147 sp++;
149 else
150 sp = entry->realname;
152 for (exp = layout_expansion_table; exp->shortname; exp++)
154 if (stricmp(exp->shortname, sp) == 0)
156 if (type)
157 snprintf(entry->layoutname, sizeof(entry->layoutname), "%s (%s)", exp->longname, type);
158 else
159 strcpy(entry->layoutname, exp->longname);
161 if (exp->flag != NULL)
163 #if SHOWFLAGS == 1
164 sprintf(entry->displayflag, "\033I[5:Locale:Flags/%s]", exp->flag);
165 #else
166 entry->displayflag[0] = '\0';
167 #endif
169 break;
176 /*********************************************************************************************/
179 void SortInNode(struct List *list, struct Node *node)
181 struct Node *sort, *prev = NULL;
183 ForeachNode(list, sort)
185 if (Stricmp(node->ln_Name, sort->ln_Name) < 0) break;
186 prev = sort;
189 Insert(list, node, prev);
192 void Prefs_ScanDirectory(STRPTR pattern, struct List *list, LONG entrysize)
194 struct AnchorPath ap;
195 struct ListviewEntry *entry, *entry2;
196 struct List templist;
197 STRPTR sp;
198 LONG error;
200 memset(&ap, 0, sizeof(ap));
201 NewList(&templist);
204 * Add default keymap.
205 * CHECKME: possibly too hacky. May be we should verify its presence in keymap.resource?
206 * How is it done in classic AmigaOS(tm) ?
208 entry = AllocPooled(mempool, entrysize);
209 if (entry)
211 strcpy(entry->layoutname, "American (Default)");
212 strcpy(entry->realname , DEFAULT_KEYMAP);
213 #if SHOWFLAGS == 1
214 strcpy(entry->displayflag, "\033I[5:Locale:Flags/Countries/United_States]");
215 #else
216 entry->displayflag[0] = '\0';
217 #endif
219 entry->node.ln_Name = entry->layoutname;
220 AddTail(&templist, &entry->node);
223 error = MatchFirst(pattern, &ap);
224 while((error == 0))
226 if (ap.ap_Info.fib_DirEntryType < 0)
228 entry = (struct ListviewEntry *)AllocPooled((APTR)mempool, entrysize);
229 if (entry)
231 entry->node.ln_Name = entry->layoutname;
232 strncpy(entry->realname, ap.ap_Info.fib_FileName, sizeof(entry->realname));
234 sp = strchr(entry->realname, '_');
235 if (sp)
236 sp++;
237 else
238 sp = entry->realname;
239 strcpy(entry->layoutname, sp);
241 ExpandName(entry);
242 AddTail(&templist, &entry->node);
245 error = MatchNext(&ap);
247 MatchEnd(&ap);
249 /* Sort by Layout Name */
251 ForeachNodeSafe(&templist, entry, entry2)
253 Remove(&entry->node);
254 SortInNode(list, &entry->node);
258 /*********************************************************************************************/
260 static LONG stopchunks[] =
262 ID_PREF, ID_INPT,
263 ID_PREF, ID_KMSW
266 BOOL Prefs_ImportFH(BPTR fh)
268 struct FileInputPrefs loadprefs;
269 struct FileKMSPrefs loadkmsprefs;
270 struct IFFHandle *iff;
271 ULONG size;
272 BOOL retval = FALSE;
274 memset(&loadprefs, 0, sizeof(loadprefs));
276 if ((iff = AllocIFF()))
278 iff->iff_Stream = (IPTR)fh;
279 if (fh != BNULL)
281 D(Printf("LoadPrefs: stream opened.\n"));
283 InitIFFasDOS(iff);
285 if (!OpenIFF(iff, IFFF_READ))
287 D(Printf("LoadPrefs: OpenIFF okay.\n"));
289 if (!StopChunks(iff, stopchunks, 2))
291 D(Printf("LoadPrefs: StopChunk okay.\n"));
292 retval = TRUE;
294 while (!ParseIFF(iff, IFFPARSE_SCAN))
296 struct ContextNode *cn;
298 D(Printf("LoadPrefs: ParseIFF okay.\n"));
300 cn = CurrentChunk(iff);
301 size = cn->cn_Size;
303 switch (cn->cn_ID)
305 case ID_INPT:
306 D(Printf("LoadPrefs: INPT chunk\n"));
308 if (size > sizeof(struct FileInputPrefs))
309 size = sizeof(struct FileInputPrefs);
311 if (ReadChunkBytes(iff, &loadprefs, size) == size)
313 D(Printf("LoadPrefs: Reading chunk successful.\n"));
315 CopyMem(loadprefs.ip_Keymap, inputprefs.ip_Keymap, sizeof(loadprefs.ip_Keymap));
316 inputprefs.ip_PointerTicks = ARRAY_TO_WORD(loadprefs.ip_PointerTicks);
317 inputprefs.ip_DoubleClick.tv_secs = ARRAY_TO_LONG(loadprefs.ip_DoubleClick_secs);
318 inputprefs.ip_DoubleClick.tv_micro = ARRAY_TO_LONG(loadprefs.ip_DoubleClick_micro);
319 inputprefs.ip_KeyRptDelay.tv_secs = ARRAY_TO_LONG(loadprefs.ip_KeyRptDelay_secs);
320 inputprefs.ip_KeyRptDelay.tv_micro = ARRAY_TO_LONG(loadprefs.ip_KeyRptDelay_micro);
321 inputprefs.ip_KeyRptSpeed.tv_secs = ARRAY_TO_LONG(loadprefs.ip_KeyRptSpeed_secs);
322 inputprefs.ip_KeyRptSpeed.tv_micro = ARRAY_TO_LONG(loadprefs.ip_KeyRptSpeed_micro);
323 inputprefs.ip_MouseAccel = ARRAY_TO_WORD(loadprefs.ip_MouseAccel);
324 inputprefs.ip_ClassicKeyboard = ARRAY_TO_LONG(loadprefs.ip_ClassicKeyboard);
325 CopyMem(loadprefs.ip_KeymapName, inputprefs.ip_KeymapName, sizeof(loadprefs.ip_KeymapName));
326 inputprefs.ip_SwitchMouseButtons = loadprefs.ip_SwitchMouseButtons[3];
328 D(Printf("LoadPrefs: SwitchMouseButtons: %ld\n", inputprefs.ip_SwitchMouseButtons));
330 else
331 retval = FALSE;
332 break;
334 case ID_KMSW:
335 D(Printf("LoadPrefs: KMSW chunk\n"));
337 if (size > sizeof(struct FileKMSPrefs))
338 size = sizeof(struct FileKMSPrefs);
340 if (ReadChunkBytes(iff, &loadkmsprefs, size) == size)
342 D(Printf("LoadPrefs: Reading chunk successful.\n"));
344 kmsprefs.kms_Enabled = loadkmsprefs.kms_Enabled;
345 kmsprefs.kms_Reserved = loadkmsprefs.kms_Reserved;
346 kmsprefs.kms_SwitchQual = ARRAY_TO_WORD(loadkmsprefs.kms_SwitchQual);
347 kmsprefs.kms_SwitchCode = ARRAY_TO_WORD(loadkmsprefs.kms_SwitchCode);
348 CopyMem(loadkmsprefs.kms_AltKeymap, kmsprefs.kms_AltKeymap, sizeof(kmsprefs.kms_AltKeymap));
350 else
351 retval = FALSE;
352 break;
354 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
355 } /* if (!StopChunk(iff, ID_PREF, ID_INPT)) */
356 CloseIFF(iff);
357 } /* if (!OpenIFF(iff, IFFF_READ)) */
358 } /* if (fh != NULL) */
359 FreeIFF(iff);
360 } /* if ((iff = AllocIFF())) */
362 return retval;
365 /*********************************************************************************************/
367 BOOL Prefs_ExportFH(BPTR fh)
369 struct FileInputPrefs saveprefs;
370 struct FileKMSPrefs savekmsprefs;
371 struct IFFHandle *iff;
372 BOOL retval = FALSE;
373 #if 0 /* unused */
374 BOOL delete_if_error = FALSE;
375 #endif
377 D(Printf("SavePrefs: SwitchMouseButtons: %ld\n", inputprefs.ip_SwitchMouseButtons));
379 CopyMem(inputprefs.ip_Keymap, saveprefs.ip_Keymap, sizeof(saveprefs.ip_Keymap));
380 WORD_TO_ARRAY(inputprefs.ip_PointerTicks, saveprefs.ip_PointerTicks);
381 LONG_TO_ARRAY(inputprefs.ip_DoubleClick.tv_secs , saveprefs.ip_DoubleClick_secs);
382 LONG_TO_ARRAY(inputprefs.ip_DoubleClick.tv_micro, saveprefs.ip_DoubleClick_micro);
383 LONG_TO_ARRAY(inputprefs.ip_KeyRptDelay.tv_secs , saveprefs.ip_KeyRptDelay_secs);
384 LONG_TO_ARRAY(inputprefs.ip_KeyRptDelay.tv_micro, saveprefs.ip_KeyRptDelay_micro);
385 LONG_TO_ARRAY(inputprefs.ip_KeyRptSpeed.tv_secs , saveprefs.ip_KeyRptSpeed_secs);
386 LONG_TO_ARRAY(inputprefs.ip_KeyRptSpeed.tv_micro, saveprefs.ip_KeyRptSpeed_micro);
387 WORD_TO_ARRAY(inputprefs.ip_MouseAccel, saveprefs.ip_MouseAccel);
388 LONG_TO_ARRAY(inputprefs.ip_ClassicKeyboard, saveprefs.ip_ClassicKeyboard);
389 CopyMem(inputprefs.ip_KeymapName, saveprefs.ip_KeymapName, sizeof(saveprefs.ip_KeymapName));
390 saveprefs.ip_SwitchMouseButtons[0] = 0;
391 saveprefs.ip_SwitchMouseButtons[1] = 0;
392 saveprefs.ip_SwitchMouseButtons[2] = 0;
393 saveprefs.ip_SwitchMouseButtons[3] = inputprefs.ip_SwitchMouseButtons;
395 savekmsprefs.kms_Enabled = kmsprefs.kms_Enabled;
396 savekmsprefs.kms_Reserved = kmsprefs.kms_Reserved;
397 WORD_TO_ARRAY(kmsprefs.kms_SwitchQual, savekmsprefs.kms_SwitchQual);
398 WORD_TO_ARRAY(kmsprefs.kms_SwitchCode, savekmsprefs.kms_SwitchCode);
399 CopyMem(kmsprefs.kms_AltKeymap, savekmsprefs.kms_AltKeymap, sizeof(savekmsprefs.kms_AltKeymap));
401 if ((iff = AllocIFF()))
403 iff->iff_Stream = (IPTR)fh;
404 if (iff->iff_Stream)
406 D(Printf("SavePrefs: stream opened.\n"));
408 #if 0 /* unused */
409 delete_if_error = TRUE;
410 #endif
412 InitIFFasDOS(iff);
414 if (!OpenIFF(iff, IFFF_WRITE))
416 D(Printf("SavePrefs: OpenIFF okay.\n"));
418 if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN))
420 D(Printf("SavePrefs: PushChunk(FORM) okay.\n"));
422 if (!PushChunk(iff, ID_PREF, ID_PRHD, sizeof(struct FilePrefHeader)))
424 struct FilePrefHeader head;
426 D(Printf("SavePrefs: PushChunk(PRHD) okay.\n"));
428 head.ph_Version = 0; // FIXME: should be PHV_CURRENT, but see <prefs/prefhdr.h>
429 head.ph_Type = 0;
430 head.ph_Flags[0] =
431 head.ph_Flags[1] =
432 head.ph_Flags[2] =
433 head.ph_Flags[3] = 0;
435 if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head))
437 D(Printf("SavePrefs: WriteChunkBytes(PRHD) okay.\n"));
439 PopChunk(iff);
441 if (!PushChunk(iff, ID_PREF, ID_INPT, sizeof(saveprefs)))
443 D(Printf("SavePrefs: PushChunk(INPT) okay.\n"));
445 if (WriteChunkBytes(iff, &saveprefs, sizeof(saveprefs)) == sizeof(saveprefs))
447 D(Printf("SavePrefs: WriteChunkBytes(INPT) okay.\n"));
449 retval = TRUE;
452 PopChunk(iff);
454 } /* if (!PushChunk(iff, ID_PREF, ID_INPT, sizeof(saveprefs))) */
456 if (!PushChunk(iff, ID_PREF, ID_KMSW, sizeof(savekmsprefs)))
458 if (WriteChunkBytes(iff, &savekmsprefs, sizeof(savekmsprefs)) == sizeof(savekmsprefs))
459 retval = retval && TRUE;
461 PopChunk(iff);
463 } /* if (!PushChunk(iff, ID_PREF, ID_INPT, sizeof(saveprefs))) */
465 } /* if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head)) */
466 else
468 PopChunk(iff);
471 } /* if (!PushChunk(iff, ID_PREF, ID_PRHD, sizeof(struct PrefHeader))) */
473 PopChunk(iff);
475 } /* if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN)) */
477 CloseIFF(iff);
479 } /* if (!OpenIFF(iff, IFFFWRITE)) */
482 } /* if (iff->iff_Stream)) */
484 FreeIFF(iff);
486 } /* if ((iff = AllocIFF())) */
488 #if 0 /* unused */
489 if (!retval && delete_if_error)
491 DeleteFile(filename);
493 #endif
495 return retval;
498 /*********************************************************************************************/
500 BOOL Prefs_HandleArgs(STRPTR from, BOOL use, BOOL save)
502 BPTR fh;
504 if (from)
506 if (!Prefs_Load(from))
508 ShowMessage("Can't read from input file");
509 return FALSE;
512 else
514 if (!Prefs_Load(PREFS_PATH_ENV))
516 if (!Prefs_Load(PREFS_PATH_ENVARC))
518 ShowMessage
520 "Can't read from file " PREFS_PATH_ENVARC
521 ".\nUsing default values."
523 Prefs_Default();
528 if (use || save)
530 fh = Open(PREFS_PATH_ENV, MODE_NEWFILE);
531 if (fh)
533 Prefs_ExportFH(fh);
534 Close(fh);
536 else
538 ShowMessage("Can't open " PREFS_PATH_ENV " for writing.");
541 if (save)
543 fh = Open(PREFS_PATH_ENVARC, MODE_NEWFILE);
544 if (fh)
546 Prefs_ExportFH(fh);
547 Close(fh);
549 else
551 ShowMessage("Can't open " PREFS_PATH_ENVARC " for writing.");
554 return TRUE;
557 /*********************************************************************************************/
559 BOOL Prefs_Default(void)
561 strcpy(inputprefs.ip_Keymap, DEFAULT_KEYMAP);
562 inputprefs.ip_PointerTicks = 1;
563 inputprefs.ip_DoubleClick.tv_secs = 0;
564 inputprefs.ip_DoubleClick.tv_micro = 500000;
565 inputprefs.ip_KeyRptDelay.tv_secs = 0;
566 inputprefs.ip_KeyRptDelay.tv_micro = 500000;
567 inputprefs.ip_KeyRptSpeed.tv_secs = 0;
568 inputprefs.ip_KeyRptSpeed.tv_micro = 40000;
569 inputprefs.ip_MouseAccel = 1;
570 inputprefs.ip_ClassicKeyboard = 0;
571 strcpy(inputprefs.ip_KeymapName, DEFAULT_KEYMAP);
572 inputprefs.ip_SwitchMouseButtons = FALSE;
574 kmsprefs.kms_Enabled = FALSE;
575 kmsprefs.kms_SwitchQual = KMS_QUAL_DISABLE;
576 kmsprefs.kms_SwitchCode = KMS_CODE_NOKEY;
577 kmsprefs.kms_AltKeymap[0] = 0;
579 return TRUE;