revert between 56095 -> 55830 in arch
[AROS.git] / workbench / prefs / input / prefs.c
blob6a5a67d41259ebe879a883c404f5c3ebd393d572
1 /*
2 Copyright © 1995-2019, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Change your input preferences
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 {"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" },
90 {NULL , NULL , NULL }
93 static const struct typeexp type_expansion_table[] = {
94 {"amiga", "Amiga" },
95 {"pc104", "PC 104"},
96 {"pc105", "PC 105"},
97 {"sun" , "Sun" },
98 {NULL , NULL }
101 /*********************************************************************************************/
103 static BOOL Prefs_Load(STRPTR from)
105 BOOL retval = FALSE;
107 BPTR fh = Open(from, MODE_OLDFILE);
108 if (fh)
110 retval = Prefs_ImportFH(fh);
111 Close(fh);
114 return retval;
117 /*********************************************************************************************/
119 static void ExpandName(struct ListviewEntry *entry)
121 char *sp;
122 char *type = NULL;
123 const struct nameexp *exp;
125 strcpy(entry->layoutname, entry->realname);
127 sp = strchr(entry->realname, '_');
128 if (sp)
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;
138 *sp = 0;
139 for (te = type_expansion_table; te->shortname; te++)
141 if (!strcmp(entry->realname, te->shortname))
143 type = te->longname;
144 break;
147 *sp = '_';
149 sp++;
151 else
152 sp = entry->realname;
154 for (exp = layout_expansion_table; exp->shortname; exp++)
156 if (stricmp(exp->shortname, sp) == 0)
158 if (type)
159 snprintf(entry->layoutname, sizeof(entry->layoutname), "%s (%s)", exp->longname, type);
160 else
161 strcpy(entry->layoutname, exp->longname);
163 if (exp->flag != NULL)
165 #if SHOWFLAGS == 1
166 sprintf(entry->displayflag, "\033I[5:Locale:Flags/%s]", exp->flag);
167 #else
168 entry->displayflag[0] = '\0';
169 #endif
171 break;
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;
188 prev = sort;
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;
199 STRPTR sp;
200 LONG error;
202 memset(&ap, 0, sizeof(ap));
203 NewList(&templist);
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);
211 if (entry)
213 strcpy(entry->layoutname, "American (Default)");
214 strcpy(entry->realname , DEFAULT_KEYMAP);
215 #if SHOWFLAGS == 1
216 strcpy(entry->displayflag, "\033I[5:Locale:Flags/Countries/United_States]");
217 #else
218 entry->displayflag[0] = '\0';
219 #endif
221 entry->node.ln_Name = entry->layoutname;
222 AddTail(&templist, &entry->node);
225 error = MatchFirst(pattern, &ap);
226 while((error == 0))
228 if (ap.ap_Info.fib_DirEntryType < 0)
230 entry = (struct ListviewEntry *)AllocPooled((APTR)mempool, entrysize);
231 if (entry)
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, '_');
238 if (sp)
239 sp++;
240 else
241 sp = entry->realname;
242 strcpy(entry->layoutname, sp);
244 ExpandName(entry);
245 AddTail(&templist, &entry->node);
248 error = MatchNext(&ap);
250 MatchEnd(&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[] =
265 ID_PREF, ID_INPT,
266 ID_PREF, ID_KMSW
269 BOOL Prefs_ImportFH(BPTR fh)
271 struct FileInputPrefs loadprefs;
272 struct FileKMSPrefs loadkmsprefs;
273 struct IFFHandle *iff;
274 ULONG size;
275 BOOL retval = FALSE;
277 memset(&loadprefs, 0, sizeof(loadprefs));
279 if ((iff = AllocIFF()))
281 iff->iff_Stream = (IPTR)fh;
282 if (fh != BNULL)
284 D(Printf("LoadPrefs: stream opened.\n"));
286 InitIFFasDOS(iff);
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"));
295 retval = TRUE;
297 while (!ParseIFF(iff, IFFPARSE_SCAN))
299 struct ContextNode *cn;
301 D(Printf("LoadPrefs: ParseIFF okay.\n"));
303 cn = CurrentChunk(iff);
304 size = cn->cn_Size;
306 switch (cn->cn_ID)
308 case ID_INPT:
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));
333 else
334 retval = FALSE;
335 break;
337 case ID_KMSW:
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));
353 else
354 retval = FALSE;
355 break;
357 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
358 } /* if (!StopChunk(iff, ID_PREF, ID_INPT)) */
359 CloseIFF(iff);
360 } /* if (!OpenIFF(iff, IFFF_READ)) */
361 } /* if (fh != NULL) */
362 FreeIFF(iff);
363 } /* if ((iff = AllocIFF())) */
365 return retval;
368 /*********************************************************************************************/
370 BOOL Prefs_ExportFH(BPTR fh)
372 struct FileInputPrefs saveprefs;
373 struct FileKMSPrefs savekmsprefs;
374 struct IFFHandle *iff;
375 BOOL retval = FALSE;
376 #if 0 /* unused */
377 BOOL delete_if_error = FALSE;
378 #endif
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;
407 if (iff->iff_Stream)
409 D(Printf("SavePrefs: stream opened.\n"));
411 #if 0 /* unused */
412 delete_if_error = TRUE;
413 #endif
415 InitIFFasDOS(iff);
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>
432 head.ph_Type = 0;
433 head.ph_Flags[0] =
434 head.ph_Flags[1] =
435 head.ph_Flags[2] =
436 head.ph_Flags[3] = 0;
438 if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head))
440 D(Printf("SavePrefs: WriteChunkBytes(PRHD) okay.\n"));
442 PopChunk(iff);
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"));
452 retval = TRUE;
455 PopChunk(iff);
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;
464 PopChunk(iff);
466 } /* if (!PushChunk(iff, ID_PREF, ID_INPT, sizeof(saveprefs))) */
468 } /* if (WriteChunkBytes(iff, &head, sizeof(head)) == sizeof(head)) */
469 else
471 PopChunk(iff);
474 } /* if (!PushChunk(iff, ID_PREF, ID_PRHD, sizeof(struct PrefHeader))) */
476 PopChunk(iff);
478 } /* if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN)) */
480 CloseIFF(iff);
482 } /* if (!OpenIFF(iff, IFFFWRITE)) */
485 } /* if (iff->iff_Stream)) */
487 FreeIFF(iff);
489 } /* if ((iff = AllocIFF())) */
491 #if 0 /* unused */
492 if (!retval && delete_if_error)
494 DeleteFile(filename);
496 #endif
498 return retval;
501 /*********************************************************************************************/
503 BOOL Prefs_HandleArgs(STRPTR from, BOOL use, BOOL save)
505 BPTR fh;
507 if (from)
509 if (!Prefs_Load(from))
511 ShowMessage("Can't read from input file");
512 return FALSE;
515 else
517 if (!Prefs_Load(PREFS_PATH_ENV))
519 if (!Prefs_Load(PREFS_PATH_ENVARC))
521 ShowMessage
523 "Can't read from file " PREFS_PATH_ENVARC
524 ".\nUsing default values."
526 Prefs_Default();
531 if (use || save)
533 fh = Open(PREFS_PATH_ENV, MODE_NEWFILE);
534 if (fh)
536 Prefs_ExportFH(fh);
537 Close(fh);
539 else
541 ShowMessage("Can't open " PREFS_PATH_ENV " for writing.");
544 if (save)
546 fh = Open(PREFS_PATH_ENVARC, MODE_NEWFILE);
547 if (fh)
549 Prefs_ExportFH(fh);
550 Close(fh);
552 else
554 ShowMessage("Can't open " PREFS_PATH_ENVARC " for writing.");
557 return TRUE;
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;
582 return TRUE;