2 Copyright © 1995-2019, The AROS Development Team. All rights reserved.
5 Desc: Change your input preferences
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>
22 #include <aros/debug.h>
27 /*********************************************************************************************/
29 #define PREFS_PATH_ENVARC "ENVARC:SYS/input.prefs"
30 #define PREFS_PATH_ENV "ENV:SYS/input.prefs"
32 /*********************************************************************************************/
35 struct InputPrefs inputprefs
;
36 struct KMSPrefs kmsprefs
;
37 struct List keymap_list
;
39 /*********************************************************************************************/
41 static const struct nameexp layout_expansion_table
[] =
43 {"usa" , "American" , "Countries/United_States" },
44 {"usa0" , "American" , "Countries/United_States" },
45 {"us" , "American" , "Countries/United_States" },
46 {"usx" , "American" , "Countries/United_States" },
47 {"col" , "Colemak (US)" , "Countries/United_States" },
48 {"d" , "Deutsch" , "Countries/Germany" },
49 {"b" , "Belge" , "Countries/Belgium" },
50 {"by" , "Belarussian" , "Countries/Belarus" },
51 {"br" , "Brasileiro" , "Countries/Brazil" },
52 {"gb" , "British" , "Countries/United_Kingdom"},
53 {"gbx" , "British Extended" , "Countries/United_Kingdom"},
54 {"bg" , "Bulgarian" , "Countries/Bulgaria" },
55 {"cdn" , "Canadien Français" , "Countries/Quebec" },
56 {"cz" , "Czech" , "Countries/Czech_Republic"},
57 {"dk" , "Dansk" , "Countries/Denmark" },
58 {"nl" , "Dutch" , "Countries/Netherlands" },
59 {"dvx" , "Dvorak" , "Misc/Unknown" },
60 {"usa2" , "Dvorak" , "Misc/Unknown" },
61 {"dvl" , "Dvorak Left-handed" , "Misc/Unknown" },
62 {"dvr" , "Dvorak Right-handed" , "Misc/Unknown" },
63 {"irl" , "English Ireland" , "Countries/Ireland" },
64 {"e" , "Español" , "Countries/Spain" },
65 {"sp" , "Español no deadkeys" , "Countries/Spain" },
66 {"est" , "Eesti" , "Countries/Estonia" },
67 {"fin" , "Finnish" , "Countries/Finland" },
68 {"f" , "Français" , "Countries/France" },
69 {"il" , "Hebrew" , "Countries/Israel" },
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" , "Latvijas" , "Countries/Latvia" },
76 {"lt" , "Lietuvos" , "Countries/Lithuania" },
77 {"h" , "Magyar" , "Countries/Hungary" },
78 {"n" , "Norsk" , "Countries/Norway" },
79 {"pl" , "Polski" , "Countries/Poland" },
80 {"p" , "Português" , "Countries/Portugal" },
81 {"ro" , "Românesc" , "Countries/Romania" },
82 {"rus" , "Russian" , "Countries/Russia" },
83 {"ch1" , "Schweizer" , "Countries/Switzerland" },
84 {"al" , "Shqip" , "Countries/Albania" },
85 {"sk" , "Slovak" , "Countries/Slovakia" },
86 {"ch2" , "Suisse" , "Countries/Switzerland" },
87 {"s" , "Svenskt" , "Countries/Sweden" },
88 {"tr" , "Türkçe" , "Countries/Turkey" },
89 {"ua" , "Ukranian" , "Countries/Ukraine" },
93 static const struct typeexp type_expansion_table
[] = {
101 /*********************************************************************************************/
103 static BOOL
Prefs_Load(STRPTR from
)
107 BPTR fh
= Open(from
, MODE_OLDFILE
);
110 retval
= Prefs_ImportFH(fh
);
117 /*********************************************************************************************/
119 static void ExpandName(struct ListviewEntry
*entry
)
123 const struct nameexp
*exp
;
125 strcpy(entry
->layoutname
, entry
->realname
);
127 sp
= strchr(entry
->realname
, '_');
131 * We have several variants of US keyboard, so
132 * we append type name.
134 if ((sp
[1] == 'u' && sp
[2] == 's'))
136 const struct typeexp
*te
;
139 for (te
= type_expansion_table
; te
->shortname
; te
++)
141 if (!strcmp(entry
->realname
, te
->shortname
))
152 sp
= entry
->realname
;
154 for (exp
= layout_expansion_table
; exp
->shortname
; exp
++)
156 if (stricmp(exp
->shortname
, sp
) == 0)
159 snprintf(entry
->layoutname
, sizeof(entry
->layoutname
), "%s (%s)", exp
->longname
, type
);
161 strcpy(entry
->layoutname
, exp
->longname
);
163 if (exp
->flag
!= NULL
)
166 sprintf(entry
->displayflag
, "\033I[5:Locale:Flags/%s]", exp
->flag
);
168 entry
->displayflag
[0] = '\0';
178 /*********************************************************************************************/
181 void SortInNode(struct List
*list
, struct Node
*node
)
183 struct Node
*sort
, *prev
= NULL
;
185 ForeachNode(list
, sort
)
187 if (Stricmp(node
->ln_Name
, sort
->ln_Name
) < 0) break;
191 Insert(list
, node
, prev
);
194 void Prefs_ScanDirectory(STRPTR pattern
, struct List
*list
, LONG entrysize
)
196 struct AnchorPath ap
;
197 struct ListviewEntry
*entry
, *entry2
;
198 struct List templist
;
202 memset(&ap
, 0, sizeof(ap
));
206 * Add default keymap.
207 * CHECKME: possibly too hacky. May be we should verify its presence in keymap.resource?
208 * How is it done in classic AmigaOS(tm) ?
210 entry
= AllocPooled(mempool
, entrysize
);
213 strcpy(entry
->layoutname
, "American (Default)");
214 strcpy(entry
->realname
, DEFAULT_KEYMAP
);
216 strcpy(entry
->displayflag
, "\033I[5:Locale:Flags/Countries/United_States]");
218 entry
->displayflag
[0] = '\0';
221 entry
->node
.ln_Name
= entry
->layoutname
;
222 AddTail(&templist
, &entry
->node
);
225 error
= MatchFirst(pattern
, &ap
);
228 if (ap
.ap_Info
.fib_DirEntryType
< 0)
230 entry
= (struct ListviewEntry
*)AllocPooled((APTR
)mempool
, entrysize
);
233 entry
->node
.ln_Name
= entry
->layoutname
;
234 CopyMem(ap
.ap_Info
.fib_FileName
, entry
->realname
, sizeof(entry
->realname
));
235 entry
->realname
[sizeof(entry
->realname
) - 1] = '\0';
237 sp
= strchr(entry
->realname
, '_');
241 sp
= entry
->realname
;
242 strcpy(entry
->layoutname
, sp
);
245 AddTail(&templist
, &entry
->node
);
248 error
= MatchNext(&ap
);
252 /* Sort by Layout Name */
254 ForeachNodeSafe(&templist
, entry
, entry2
)
256 Remove(&entry
->node
);
257 SortInNode(list
, &entry
->node
);
261 /*********************************************************************************************/
263 static LONG stopchunks
[] =
269 BOOL
Prefs_ImportFH(BPTR fh
)
271 struct FileInputPrefs loadprefs
;
272 struct FileKMSPrefs loadkmsprefs
;
273 struct IFFHandle
*iff
;
277 memset(&loadprefs
, 0, sizeof(loadprefs
));
279 if ((iff
= AllocIFF()))
281 iff
->iff_Stream
= (IPTR
)fh
;
284 D(Printf("LoadPrefs: stream opened.\n"));
288 if (!OpenIFF(iff
, IFFF_READ
))
290 D(Printf("LoadPrefs: OpenIFF okay.\n"));
292 if (!StopChunks(iff
, stopchunks
, 2))
294 D(Printf("LoadPrefs: StopChunk okay.\n"));
297 while (!ParseIFF(iff
, IFFPARSE_SCAN
))
299 struct ContextNode
*cn
;
301 D(Printf("LoadPrefs: ParseIFF okay.\n"));
303 cn
= CurrentChunk(iff
);
309 D(Printf("LoadPrefs: INPT chunk\n"));
311 if (size
> sizeof(struct FileInputPrefs
))
312 size
= sizeof(struct FileInputPrefs
);
314 if (ReadChunkBytes(iff
, &loadprefs
, size
) == size
)
316 D(Printf("LoadPrefs: Reading chunk successful.\n"));
318 CopyMem(loadprefs
.ip_Keymap
, inputprefs
.ip_Keymap
, sizeof(loadprefs
.ip_Keymap
));
319 inputprefs
.ip_PointerTicks
= ARRAY_TO_WORD(loadprefs
.ip_PointerTicks
);
320 inputprefs
.ip_DoubleClick
.tv_secs
= ARRAY_TO_LONG(loadprefs
.ip_DoubleClick_secs
);
321 inputprefs
.ip_DoubleClick
.tv_micro
= ARRAY_TO_LONG(loadprefs
.ip_DoubleClick_micro
);
322 inputprefs
.ip_KeyRptDelay
.tv_secs
= ARRAY_TO_LONG(loadprefs
.ip_KeyRptDelay_secs
);
323 inputprefs
.ip_KeyRptDelay
.tv_micro
= ARRAY_TO_LONG(loadprefs
.ip_KeyRptDelay_micro
);
324 inputprefs
.ip_KeyRptSpeed
.tv_secs
= ARRAY_TO_LONG(loadprefs
.ip_KeyRptSpeed_secs
);
325 inputprefs
.ip_KeyRptSpeed
.tv_micro
= ARRAY_TO_LONG(loadprefs
.ip_KeyRptSpeed_micro
);
326 inputprefs
.ip_MouseAccel
= ARRAY_TO_WORD(loadprefs
.ip_MouseAccel
);
327 inputprefs
.ip_ClassicKeyboard
= ARRAY_TO_LONG(loadprefs
.ip_ClassicKeyboard
);
328 CopyMem(loadprefs
.ip_KeymapName
, inputprefs
.ip_KeymapName
, sizeof(loadprefs
.ip_KeymapName
));
329 inputprefs
.ip_SwitchMouseButtons
= loadprefs
.ip_SwitchMouseButtons
[3];
331 D(Printf("LoadPrefs: SwitchMouseButtons: %ld\n", inputprefs
.ip_SwitchMouseButtons
));
338 D(Printf("LoadPrefs: KMSW chunk\n"));
340 if (size
> sizeof(struct FileKMSPrefs
))
341 size
= sizeof(struct FileKMSPrefs
);
343 if (ReadChunkBytes(iff
, &loadkmsprefs
, size
) == size
)
345 D(Printf("LoadPrefs: Reading chunk successful.\n"));
347 kmsprefs
.kms_Enabled
= loadkmsprefs
.kms_Enabled
;
348 kmsprefs
.kms_Reserved
= loadkmsprefs
.kms_Reserved
;
349 kmsprefs
.kms_SwitchQual
= ARRAY_TO_WORD(loadkmsprefs
.kms_SwitchQual
);
350 kmsprefs
.kms_SwitchCode
= ARRAY_TO_WORD(loadkmsprefs
.kms_SwitchCode
);
351 CopyMem(loadkmsprefs
.kms_AltKeymap
, kmsprefs
.kms_AltKeymap
, sizeof(kmsprefs
.kms_AltKeymap
));
357 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
358 } /* if (!StopChunk(iff, ID_PREF, ID_INPT)) */
360 } /* if (!OpenIFF(iff, IFFF_READ)) */
361 } /* if (fh != NULL) */
363 } /* if ((iff = AllocIFF())) */
368 /*********************************************************************************************/
370 BOOL
Prefs_ExportFH(BPTR fh
)
372 struct FileInputPrefs saveprefs
;
373 struct FileKMSPrefs savekmsprefs
;
374 struct IFFHandle
*iff
;
377 BOOL delete_if_error
= FALSE
;
380 D(Printf("SavePrefs: SwitchMouseButtons: %ld\n", inputprefs
.ip_SwitchMouseButtons
));
382 CopyMem(inputprefs
.ip_Keymap
, saveprefs
.ip_Keymap
, sizeof(saveprefs
.ip_Keymap
));
383 WORD_TO_ARRAY(inputprefs
.ip_PointerTicks
, saveprefs
.ip_PointerTicks
);
384 LONG_TO_ARRAY(inputprefs
.ip_DoubleClick
.tv_secs
, saveprefs
.ip_DoubleClick_secs
);
385 LONG_TO_ARRAY(inputprefs
.ip_DoubleClick
.tv_micro
, saveprefs
.ip_DoubleClick_micro
);
386 LONG_TO_ARRAY(inputprefs
.ip_KeyRptDelay
.tv_secs
, saveprefs
.ip_KeyRptDelay_secs
);
387 LONG_TO_ARRAY(inputprefs
.ip_KeyRptDelay
.tv_micro
, saveprefs
.ip_KeyRptDelay_micro
);
388 LONG_TO_ARRAY(inputprefs
.ip_KeyRptSpeed
.tv_secs
, saveprefs
.ip_KeyRptSpeed_secs
);
389 LONG_TO_ARRAY(inputprefs
.ip_KeyRptSpeed
.tv_micro
, saveprefs
.ip_KeyRptSpeed_micro
);
390 WORD_TO_ARRAY(inputprefs
.ip_MouseAccel
, saveprefs
.ip_MouseAccel
);
391 LONG_TO_ARRAY(inputprefs
.ip_ClassicKeyboard
, saveprefs
.ip_ClassicKeyboard
);
392 CopyMem(inputprefs
.ip_KeymapName
, saveprefs
.ip_KeymapName
, sizeof(saveprefs
.ip_KeymapName
));
393 saveprefs
.ip_SwitchMouseButtons
[0] = 0;
394 saveprefs
.ip_SwitchMouseButtons
[1] = 0;
395 saveprefs
.ip_SwitchMouseButtons
[2] = 0;
396 saveprefs
.ip_SwitchMouseButtons
[3] = inputprefs
.ip_SwitchMouseButtons
;
398 savekmsprefs
.kms_Enabled
= kmsprefs
.kms_Enabled
;
399 savekmsprefs
.kms_Reserved
= kmsprefs
.kms_Reserved
;
400 WORD_TO_ARRAY(kmsprefs
.kms_SwitchQual
, savekmsprefs
.kms_SwitchQual
);
401 WORD_TO_ARRAY(kmsprefs
.kms_SwitchCode
, savekmsprefs
.kms_SwitchCode
);
402 CopyMem(kmsprefs
.kms_AltKeymap
, savekmsprefs
.kms_AltKeymap
, sizeof(savekmsprefs
.kms_AltKeymap
));
404 if ((iff
= AllocIFF()))
406 iff
->iff_Stream
= (IPTR
)fh
;
409 D(Printf("SavePrefs: stream opened.\n"));
412 delete_if_error
= TRUE
;
417 if (!OpenIFF(iff
, IFFF_WRITE
))
419 D(Printf("SavePrefs: OpenIFF okay.\n"));
421 if (!PushChunk(iff
, ID_PREF
, ID_FORM
, IFFSIZE_UNKNOWN
))
423 D(Printf("SavePrefs: PushChunk(FORM) okay.\n"));
425 if (!PushChunk(iff
, ID_PREF
, ID_PRHD
, sizeof(struct FilePrefHeader
)))
427 struct FilePrefHeader head
;
429 D(Printf("SavePrefs: PushChunk(PRHD) okay.\n"));
431 head
.ph_Version
= 0; // FIXME: should be PHV_CURRENT, but see <prefs/prefhdr.h>
436 head
.ph_Flags
[3] = 0;
438 if (WriteChunkBytes(iff
, &head
, sizeof(head
)) == sizeof(head
))
440 D(Printf("SavePrefs: WriteChunkBytes(PRHD) okay.\n"));
444 if (!PushChunk(iff
, ID_PREF
, ID_INPT
, sizeof(saveprefs
)))
446 D(Printf("SavePrefs: PushChunk(INPT) okay.\n"));
448 if (WriteChunkBytes(iff
, &saveprefs
, sizeof(saveprefs
)) == sizeof(saveprefs
))
450 D(Printf("SavePrefs: WriteChunkBytes(INPT) okay.\n"));
457 } /* if (!PushChunk(iff, ID_PREF, ID_INPT, sizeof(saveprefs))) */
459 if (!PushChunk(iff
, ID_PREF
, ID_KMSW
, sizeof(savekmsprefs
)))
461 if (WriteChunkBytes(iff
, &savekmsprefs
, sizeof(savekmsprefs
)) == sizeof(savekmsprefs
))
462 retval
= retval
&& TRUE
;
466 } /* if (!PushChunk(iff, ID_PREF, ID_INPT, sizeof(saveprefs))) */
468 } /* if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head)) */
474 } /* if (!PushChunk(iff, ID_PREF, ID_PRHD, sizeof(struct PrefHeader))) */
478 } /* if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN)) */
482 } /* if (!OpenIFF(iff, IFFFWRITE)) */
485 } /* if (iff->iff_Stream)) */
489 } /* if ((iff = AllocIFF())) */
492 if (!retval
&& delete_if_error
)
494 DeleteFile(filename
);
501 /*********************************************************************************************/
503 BOOL
Prefs_HandleArgs(STRPTR from
, BOOL use
, BOOL save
)
509 if (!Prefs_Load(from
))
511 ShowMessage("Can't read from input file");
517 if (!Prefs_Load(PREFS_PATH_ENV
))
519 if (!Prefs_Load(PREFS_PATH_ENVARC
))
523 "Can't read from file " PREFS_PATH_ENVARC
524 ".\nUsing default values."
533 fh
= Open(PREFS_PATH_ENV
, MODE_NEWFILE
);
541 ShowMessage("Can't open " PREFS_PATH_ENV
" for writing.");
546 fh
= Open(PREFS_PATH_ENVARC
, MODE_NEWFILE
);
554 ShowMessage("Can't open " PREFS_PATH_ENVARC
" for writing.");
560 /*********************************************************************************************/
562 BOOL
Prefs_Default(void)
564 strcpy(inputprefs
.ip_Keymap
, DEFAULT_KEYMAP
);
565 inputprefs
.ip_PointerTicks
= 1;
566 inputprefs
.ip_DoubleClick
.tv_secs
= 0;
567 inputprefs
.ip_DoubleClick
.tv_micro
= 500000;
568 inputprefs
.ip_KeyRptDelay
.tv_secs
= 0;
569 inputprefs
.ip_KeyRptDelay
.tv_micro
= 500000;
570 inputprefs
.ip_KeyRptSpeed
.tv_secs
= 0;
571 inputprefs
.ip_KeyRptSpeed
.tv_micro
= 40000;
572 inputprefs
.ip_MouseAccel
= 1;
573 inputprefs
.ip_ClassicKeyboard
= 0;
574 strcpy(inputprefs
.ip_KeymapName
, DEFAULT_KEYMAP
);
575 inputprefs
.ip_SwitchMouseButtons
= FALSE
;
577 kmsprefs
.kms_Enabled
= FALSE
;
578 kmsprefs
.kms_SwitchQual
= KMS_QUAL_DISABLE
;
579 kmsprefs
.kms_SwitchCode
= KMS_CODE_NOKEY
;
580 kmsprefs
.kms_AltKeymap
[0] = 0;