klavaro  3.13
About: Klavaro is a touch typing tutor program.
  Fossies Dox: klavaro-3.13.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

keyboard.c
Go to the documentation of this file.
1 /**************************************************************************/
2 /* Klavaro - a flexible touch typing tutor */
3 /* Copyright (C) 2005-2021 Felipe Emmanuel Ferreira de Castro */
4 /* */
5 /* This file is part of Klavaro, which is a free software: you can */
6 /* redistribute it and/or modify it under the terms of the GNU General */
7 /* Public License as published by the Free Software Foundation, either */
8 /* version 3 of the License, or (at your option) any later version. */
9 /* */
10 /* Klavaro is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU General Public License for more details (in the file COPYING). */
14 /* You should have received a copy of the GNU General Public License */
15 /* along with Klavaro. If not, see <https://www.gnu.org/licenses/> */
16 /**************************************************************************/
17 
18 /* Functions to implement and manage the keyboard editing operations
19  */
20 #include <errno.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <glib.h>
25 #include <glib/gstdio.h>
26 #include <gtk/gtk.h>
27 
28 #include "auxiliar.h"
29 #include "main.h"
30 #include "callbacks.h"
31 #include "translation.h"
32 #include "keyboard.h"
33 
34 #define KEY_DX 35
35 #define KEY_DY 35
36 
37 extern gchar *KEYB_CUSTOM;
38 extern gchar *KEYB_EDIT;
39 
40 //static GtkCssProvider *keyb_css = NULL;
41 GtkCssProvider *keyb_css = NULL;
42 
43 static struct
44 {
45  gchar *name;
46  gchar *name_last;
47  gboolean modified_status;
48  gunichar lochars[4][KEY_LINE_LEN + 1];
49  gunichar upchars[4][KEY_LINE_LEN + 1];
50  GtkWidget *but[4][KEY_LINE_LEN - 1];
51  GtkWidget *lab[4][KEY_LINE_LEN - 1];
52  GtkWidget *entry;
53  struct
54  {
55  guint i;
56  guint j;
57  } pos;
58  gint cmb_n;
59  gint intro_step;
60 } keyb;
61 static guint x0[4] = {0, 49, 59, 43};
62 
63 static struct
64 {
65  KeybLayout *orig; // Original layouts already defined
66  gint n_orig;
67  KeybLayout *cust; // Custom layouts created by the user
68  gint n_cust;
70 
71 /* Constants
72  */
73 const gunichar vowels[] = {
74  L'a', L'e', L'i', L'o', L'u',
75  (gunichar) 945,
76  (gunichar) 949,
77  (gunichar) 953,
78  (gunichar) 959,
79  (gunichar) 965,
80  (gunichar) 1072,
81  (gunichar) 1077,
82  (gunichar) 1080,
83  (gunichar) 1086,
84  (gunichar) 1091,
85  // Tibetan vowels
86  (gunichar) 0x0F72,
87  (gunichar) 0x0F74,
88  (gunichar) 0x0F7A,
89  (gunichar) 0x0F7C,
90  L'\0'
91 };
92 
93 /* Diacritic chars should never appear one after another
94  */
95 const gunichar diacritics[] = {
96  // Urdu diacritics
97  (gunichar) 0x0640,
98  (gunichar) 0x064B,
99  (gunichar) 0x064E,
100  (gunichar) 0x064F,
101  (gunichar) 0x0650,
102  (gunichar) 0x0651,
103  (gunichar) 0x0654,
104  (gunichar) 0x0670,
105  // Tibetan diacritics
106  (gunichar) 0x0F35,
107  (gunichar) 0x0F37,
108  (gunichar) 0x0F71,
109  (gunichar) 0x0F72,
110  (gunichar) 0x0F74,
111  (gunichar) 0x0F7A,
112  (gunichar) 0x0F7B,
113  (gunichar) 0x0F7C,
114  (gunichar) 0x0F7D,
115  (gunichar) 0x0F7E,
116  (gunichar) 0x0F80,
117  (gunichar) 0x0F83,
118  (gunichar) 0x0F90,
119  (gunichar) 0x0F91,
120  (gunichar) 0x0F92,
121  (gunichar) 0x0F94,
122  (gunichar) 0x0F95,
123  (gunichar) 0x0F96,
124  (gunichar) 0x0F97,
125  (gunichar) 0x0F98,
126  (gunichar) 0x0F99,
127  (gunichar) 0x0F9A,
128  (gunichar) 0x0F9F,
129  (gunichar) 0x0FA0,
130  (gunichar) 0x0FA1,
131  (gunichar) 0x0FA3,
132  (gunichar) 0x0FA4,
133  (gunichar) 0x0FA5,
134  (gunichar) 0x0FA6,
135  (gunichar) 0x0FA8,
136  (gunichar) 0x0FA9,
137  (gunichar) 0x0FAA,
138  (gunichar) 0x0FAB,
139  (gunichar) 0x0FAD,
140  (gunichar) 0x0FAE,
141  (gunichar) 0x0FAF,
142  (gunichar) 0x0FB0,
143  (gunichar) 0x0FB1,
144  (gunichar) 0x0FB2,
145  (gunichar) 0x0FB3,
146  (gunichar) 0x0FB4,
147  (gunichar) 0x0FB6,
148  (gunichar) 0x0FB7,
149  (gunichar) 0x0FB8,
150  (gunichar) 0x0FBA,
151  (gunichar) 0x0FBB,
152  // Other arabic diacritics
153  (gunichar) 0x0610,
154  (gunichar) 0x0611,
155  (gunichar) 0x0612,
156  (gunichar) 0x0613,
157  (gunichar) 0x0614,
158  (gunichar) 0x0615,
159  (gunichar) 0x0616,
160  (gunichar) 0x0617,
161  (gunichar) 0x0618,
162  (gunichar) 0x0619,
163  (gunichar) 0x061A,
164  (gunichar) 0x064C,
165  (gunichar) 0x064D,
166  (gunichar) 0x0652,
167  (gunichar) 0x0653,
168  (gunichar) 0x0655,
169  (gunichar) 0x0656,
170  (gunichar) 0x0657,
171  (gunichar) 0x0658,
172  (gunichar) 0x0659,
173  (gunichar) 0x065A,
174  (gunichar) 0x065B,
175  (gunichar) 0x065C,
176  (gunichar) 0x065D,
177  (gunichar) 0x065E,
178  (gunichar) 0x06D6,
179  (gunichar) 0x06D7,
180  (gunichar) 0x06D8,
181  (gunichar) 0x06D9,
182  (gunichar) 0x06DA,
183  (gunichar) 0x06DB,
184  (gunichar) 0x06DC,
185  (gunichar) 0x06DF,
186  (gunichar) 0x06E0,
187  (gunichar) 0x06E1,
188  (gunichar) 0x06E2,
189  (gunichar) 0x06E3,
190  (gunichar) 0x06E4,
191  (gunichar) 0x06E7,
192  (gunichar) 0x06E8,
193  (gunichar) 0x06EA,
194  (gunichar) 0x06EB,
195  (gunichar) 0x06EC,
196  (gunichar) 0x06ED,
197  L'\0'
198 };
199 
200 /*******************************************************************************
201  * Interface functions
202  */
203 gchar *
205 {
206  return (keyb.name);
207 }
208 
209 gchar *
211 {
212  return (keyb.name_last);
213 }
214 
215 void
216 keyb_set_name (const gchar * name)
217 {
218  g_free (keyb.name_last);
219  keyb.name_last = g_strdup (keyb.name);
220  g_free (keyb.name);
221  keyb.name = g_strdup (name);
222 }
223 
224 void
225 keyb_init_name (const gchar * name)
226 {
227  keyb.name = g_strdup (name);
228  keyb.name_last = g_strdup (name);
229 }
230 
231 gunichar
232 keyb_get_lochars (gint i, gint j)
233 {
234  return (keyb.lochars[i][j]);
235 }
236 
237 gunichar
238 keyb_get_upchars (gint i, gint j)
239 {
240  return (keyb.upchars[i][j]);
241 }
242 
243 gboolean
245 {
246  return (keyb.modified_status);
247 }
248 
249 void
250 keyb_set_modified_status (gboolean new_status)
251 {
252  gtk_widget_set_sensitive (get_wg ("combobox_keyboard_country"), ! new_status);
253  gtk_widget_set_sensitive (get_wg ("combobox_keyboard_variant"), ! new_status);
254  gtk_widget_set_sensitive (get_wg ("button_kb_save"), new_status);
255  keyb.modified_status = new_status;
256  if (new_status)
257  {
258  callbacks_shield_set (TRUE);
259  gtk_combo_box_set_active (GTK_COMBO_BOX (get_wg ("combobox_keyboard_country")), 0);
260  gtk_combo_box_set_active (GTK_COMBO_BOX (get_wg ("combobox_keyboard_variant")), -1);
261  callbacks_shield_set (FALSE);
262  }
263 }
264 
265 void
267 {
268  gint i, j;
269  gchar *hlp;
270  GtkFixed *fix;
271  GdkRGBA color;
272  gchar *css_text;
273  gchar *tmp;
274  gchar *tmp2;
275  gchar chcd;
276  GtkStyleContext *sc;
277 
278  /* Set color of keys
279  */
280  if (main_preferences_exist ("colors", "key_fg"))
281  hlp = main_preferences_get_string ("colors", "key_fg");
282  else
283  hlp = g_strdup (KEYB_BLACK);
284  if (keyb_css == NULL)
285  {
286  keyb_css = gtk_css_provider_new ();
287  css_text = g_strdup ("");
288  for (chcd = '1'; chcd <= '9'; chcd++)
289  {
290  tmp = g_strdup_printf (".key-but%c {background-image: none; background-color: %s; color: %s} "
291  ".key-but%c:hover {background-image: none; background-color: white; color: black} "
292  ".key-but%c:active {background-image: none; background-color: black; color: white} ",
293  chcd, hints_color_from_charcode (chcd), hlp, chcd, chcd);
294  css_text = g_strdup_printf ("%s%s", css_text, tmp);
295  g_free (tmp);
296  }
297  gtk_css_provider_load_from_data (keyb_css, css_text, -1, NULL);
298  g_free (css_text);
299  }
300  g_free (hlp);
301 
302  /* Set space key
303  */
304  sc = gtk_widget_get_style_context (get_wg ("but_space"));
305  gtk_style_context_add_provider (sc, GTK_STYLE_PROVIDER (keyb_css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
306  gtk_style_context_add_class (sc, "key-but5");
307 
308  /* Create and position buttons and labels
309  */
310  fix = GTK_FIXED (get_wg ("fixed_keyboard"));
311  for (i = 0; i < 4; i++)
312  {
313  for (j = 0; j < KEY_LINE_LEN - 1; j++)
314  {
315  keyb.but[i][j] = gtk_button_new ();
316  gtk_fixed_put (fix, keyb.but[i][j], x0[i] + j * KEY_DX, i * KEY_DY);
317  gtk_widget_set_size_request (keyb.but[i][j], 32, 32);
318  g_signal_connect_after ((gpointer) keyb.but[i][j], "clicked",
319  G_CALLBACK (on_virtual_key_clicked), NULL);
320  g_signal_connect_after ((gpointer) keyb.but[i][j], "grab-focus",
321  G_CALLBACK (on_virtual_key_grab_focus), NULL);
322  keyb.lab[i][j] = gtk_label_new ("0");
323  gtk_container_add (GTK_CONTAINER (keyb.but[i][j]), keyb.lab[i][j]);
324 
325  if (i > 0)
326  {
327  if (i == 1)
328  {
329  if (j > 12)
330  continue;
331  }
332  else
333  {
334  if (j > 11)
335  continue;
336  }
337  }
338  gtk_widget_show (keyb.but[i][j]);
339  gtk_widget_show (keyb.lab[i][j]);
340  }
341  }
342  gtk_widget_set_size_request (keyb.but[1][12], 53, 32);
343 
344  /* Key entry little evil
345  */
346  keyb.entry = gtk_entry_new ();
347  gtk_fixed_put (fix, keyb.entry, 2, 2);
348  gtk_entry_set_width_chars (GTK_ENTRY (keyb.entry), 1);
349  gtk_entry_set_max_length (GTK_ENTRY (keyb.entry), 1);
350  gtk_entry_set_alignment (GTK_ENTRY (keyb.entry), 0.5);
351  gtk_widget_set_size_request (keyb.entry, 28, 28);
352  g_object_set (G_OBJECT (keyb.entry), "shadow-type", GTK_SHADOW_NONE, NULL);
353  g_signal_connect_after ((gpointer) keyb.entry, "changed", G_CALLBACK (on_virtual_key_changed), NULL);
354 }
355 
356 /**********************************************************************
357  * Read the character sets (keyb.lochars[] & keyb.upchars[])
358  * for the keyboard currently selected.
359  */
360 void
362 {
363  gint i;
364  gchar *tmp_name = NULL;
365  gchar tmp_str[6 * KEY_LINE_LEN + 1];
366  glong n_itens;
367  gunichar *uchs;
368  FILE *fh;
369 
370  /* Search at home
371  */
372  tmp_name = g_strconcat (main_path_user (), G_DIR_SEPARATOR_S, keyb.name, ".kbd", NULL);
373  fh = (FILE *) g_fopen (tmp_name, "r");
374  if (fh == NULL)
375  {
376  /* Search at data
377  */
378  g_free (tmp_name);
379  tmp_name = g_strconcat (main_path_data (), G_DIR_SEPARATOR_S, keyb.name, ".kbd", NULL);
380  fh = (FILE *) g_fopen (tmp_name, "r");
381  }
382  g_free (tmp_name);
383 
384  /* Success */
385  if (fh)
386  {
387  for (i = 0; i < 4; i++)
388  {
389  tmp_name = fgets (tmp_str, 6 * KEY_LINE_LEN + 1, fh);
390  tmp_str[6 * KEY_LINE_LEN] = '\0';
391  uchs = g_utf8_to_ucs4_fast (tmp_str, -1, &n_itens);
392  if (n_itens > KEY_LINE_LEN)
393  g_error ("invalid keyboard layout: %s\n"
394  "invalid line: %i\n"
395  "invalid number of chars: %li", keyb.name, i + 1, n_itens);
396  memcpy (keyb.lochars[i], uchs, (n_itens - 1) * sizeof (gunichar));
397  g_free (uchs);
398  for (; n_itens < KEY_LINE_LEN; n_itens++)
399  keyb.lochars[i][n_itens] = L' ';
400  }
401  for (i = 0; i < 4; i++)
402  {
403  tmp_name = fgets (tmp_str, 6 * KEY_LINE_LEN + 1, fh);
404  tmp_str[6 * KEY_LINE_LEN] = '\0';
405  uchs = g_utf8_to_ucs4_fast (tmp_str, -1, &n_itens);
406  if (n_itens > KEY_LINE_LEN)
407  g_error ("invalid keyboard layout: %s\n"
408  "invalid line: %i\n"
409  "invalid number of chars: %li", keyb.name, i + 5, n_itens);
410  memcpy (keyb.upchars[i], uchs, (n_itens - 1) * sizeof (gunichar));
411  g_free (uchs);
412  for (; n_itens < KEY_LINE_LEN; n_itens++)
413  keyb.upchars[i][n_itens] = L' ';
414  }
415  fclose (fh);
416 
417  keyb_set_modified_status (FALSE);
418  }
419  /*
420  * Recursively try defaults
421  */
422  else
423  {
424  if (g_str_equal (keyb.name, trans_get_default_keyboard ()))
425  {
426  main_preferences_remove ("tutor", "keyboard");
427  g_error ("couldn't open the default keyboard layout: [%s]", trans_get_default_keyboard ());
428  }
429 
430  g_message ("couldn't find the keyboard layout: \"%s\"\n"
431  " Opening the default one: \"%s\"", keyb.name, trans_get_default_keyboard ());
434  keyb_set_chars ();
435  return;
436  }
437 }
438 
439 /**********************************************************************
440  * Test if chr belongs to the current key set
441  */
442 gboolean keyb_is_inset (gunichar chr)
443 {
444  register gint i, j;
445 
446  for (i = 0; i < 4; i++)
447  for (j = 0; j <= KEY_LINE_LEN; j++)
448  if (chr == keyb.lochars[i][j])
449  return (TRUE);
450 
451  for (i = 0; i < 4; i++)
452  for (j = 0; j <= KEY_LINE_LEN; j++)
453  if (chr == keyb.upchars[i][j])
454  return (TRUE);
455  return (FALSE);
456 }
457 
458 /**********************************************************************
459  * Test if chr is a vowel
460  */
461 gboolean
462 keyb_is_vowel (gunichar chr)
463 {
464  gint i;
465 
466  for (i = 0; vowels[i] != L'\0'; i++)
467  if (g_unichar_tolower (chr) == vowels[i])
468  return (TRUE);
469  return (FALSE);
470 }
471 
472 /**********************************************************************
473  * Test if chr is a diacritic character
474  */
475 gboolean
476 keyb_is_diacritic (gunichar chr)
477 {
478  gint i;
479  gunichar *diac_array;
480 
481  for (i = 0; diacritics[i] != L'\0'; i++)
482  if (chr == diacritics[i])
483  return (TRUE);
484  return (FALSE);
485 }
486 
487 /**********************************************************************
488  * Get the set of available vowels of the keyboard
489  */
490 gint
491 keyb_get_vowels (gunichar * vows)
492 {
493  gint i;
494  gint j;
495  gint k = 0;
496 
497  for (i = 0; i < 4; i++)
498  for (j = 0; j < KEY_LINE_LEN; j++)
499  {
500  if (keyb_is_vowel (keyb.lochars[i][j]))
501  vows[k++] = keyb.lochars[i][j];
502  if (k == 20)
503  break;
504  }
505  if (k == 0)
506  for (i = j = 0, k = 5; i < 5 && j < 10; i++, j++)
507  {
508  for (; keyb_is_diacritic (keyb.lochars[2][j]) && j < 12; j++);
509  vows[i] = keyb.lochars[2][j];
510  }
511  return (k);
512 }
513 
514 /**********************************************************************
515  * Get the set of available consonants of the keyboard
516  */
517 gint
518 keyb_get_consonants (gunichar * consonants)
519 {
520  gint i, j;
521  gint k = 0;
522  gunichar chr;
523 
524  for (i = 0; i < 4; i++)
525  for (j = 0; j < KEY_LINE_LEN; j++)
526  {
527  chr = keyb.lochars[i][j];
528  if (g_unichar_isalpha (chr) && (!keyb_is_vowel (chr)))
529  consonants[k++] = chr;
530 
531  chr = g_unichar_tolower (keyb.upchars[i][j]);
532  if (g_unichar_isalpha (chr) && (!keyb_is_vowel (chr))
533  && (chr != keyb.lochars[i][j]))
534  consonants[k++] = chr;
535  }
536  return (k);
537 }
538 
539 /**********************************************************************
540  * Get the set of available symbols of the keyboard
541  */
542 gint
543 keyb_get_symbols (gunichar * symbols)
544 {
545  gint i, j;
546  gint k = 0;
547  gunichar chr;
548 
549  for (i = 0; i < 4; i++)
550  for (j = 0; j < KEY_LINE_LEN; j++)
551  {
552  chr = keyb.lochars[i][j];
553  if (g_unichar_ispunct (chr))
554  symbols[k++] = chr;
555 
556  chr = keyb.upchars[i][j];
557  if (g_unichar_ispunct (chr))
558  symbols[k++] = chr;
559  }
560  return (k);
561 }
562 
563 /**********************************************************************
564  * Get the set of available non-arabic digits in the keyboard
565  */
566 gint
567 keyb_get_altnums (gunichar * altnums)
568 {
569  gint i, j;
570  gint k = 0;
571  gunichar chr;
572 
573  for (i = 0; i < 4; i++)
574  for (j = 0; j < KEY_LINE_LEN; j++)
575  {
576  chr = keyb.lochars[i][j];
577  if (g_unichar_isdigit (chr) && chr > 255)
578  altnums[k++] = chr;
579 
580  chr = keyb.upchars[i][j];
581  if (g_unichar_isdigit (chr) && chr > 255)
582  altnums[k++] = chr;
583  }
584  return (k);
585 }
586 
587 /**********************************************************************
588  * Get the upper case of a letter, only if it's included in the keyboard (by shift)
589  */
590 gunichar
591 keyb_unichar_toupper (gunichar uchar)
592 {
593  gint i,j;
594  gunichar Uchar;
595 
596  Uchar = g_unichar_toupper (uchar);
597  for (i = 0; i < 4; i++)
598  for (j = 0; j < KEY_LINE_LEN; j++)
599  if (uchar == keyb.lochars[i][j] && Uchar == keyb.upchars[i][j])
600  return Uchar;
601  return uchar;
602 }
603 
604 /**********************************************************************
605  * Save the custom keyboard layout created by the user
606  */
607 void
609 {
610  gint i;
611  gchar *tmp_name = NULL;
612  FILE *fh;
613 
614  assert_user_dir ();
615  tmp_name = g_strconcat (main_path_user (), G_DIR_SEPARATOR_S, keyb.name, ".kbd", NULL);
616  fh = (FILE *) g_fopen (tmp_name, "w");
617  g_free (tmp_name);
618 
619  for (i = 0; i < 4; i++)
620  {
621  tmp_name = g_ucs4_to_utf8 (keyb.lochars[i], KEY_LINE_LEN - 1, NULL, NULL, NULL);
622  fprintf (fh, "%s\n", tmp_name);
623  g_free (tmp_name);
624  }
625  for (i = 0; i < 4; i++)
626  {
627  tmp_name = g_ucs4_to_utf8 (keyb.upchars[i], KEY_LINE_LEN - 1, NULL, NULL, NULL);
628  fprintf (fh, "%s\n", tmp_name);
629  g_free (tmp_name);
630  }
631  fclose (fh);
632 
633  keyb_set_modified_status (FALSE);
634 }
635 
636 /**********************************************************************
637  * Remove custom keyboard layout created by the user
638  */
639 void
641 {
642  guint active;
643  gchar *aux;
644  gchar *tmp_name;
645  GtkComboBox *cmb;
646 
647  callbacks_shield_set (TRUE);
648 
649  cmb = GTK_COMBO_BOX (get_wg ("combobox_keyboard_variant"));
650  aux = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (cmb));
651  active = gtk_combo_box_get_active (cmb);
652  gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (cmb), active);
653 
654  tmp_name = g_strconcat (main_path_user (), G_DIR_SEPARATOR_S, aux, ".kbd", NULL);
655  g_unlink (tmp_name);
656  g_free (tmp_name);
657 
659 
660  gtk_combo_box_set_active (cmb, -1);
661 
662  callbacks_shield_set (FALSE);
663 }
664 
665 
666 /**********************************************************************
667  * Update the virtual keyboard accordingly to its character set and
668  * shift key state.
669  */
670 void
672 {
673  gint i, j;
674  gchar ut8[7];
675  gunichar uch;
676  gboolean tog_state;
677  GtkWidget *wg;
678 
679  wg = get_wg ("toggle_shift1");
680  tog_state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wg));
681  for (i = 0; i < 4; i++)
682  {
683  for (j = 0; j < KEY_LINE_LEN - (i == 0 ? 1 : (i == 1 ? 2 : 3)); j++)
684  {
685  uch = tog_state ? keyb.upchars[i][j] : keyb.lochars[i][j];
686  if (g_unichar_isalpha (uch)
687  && g_unichar_tolower (keyb.upchars[i][j]) == keyb.lochars[i][j])
688  uch = g_unichar_toupper (uch);
689  ut8[g_unichar_to_utf8 (uch, ut8)] = '\0';
690  gtk_label_set_text (GTK_LABEL (keyb.lab[i][j]), ut8);
691  }
692  }
693 }
694 
695 /* Get a list of .kbd file names in the subdir path, stripping their .kbd extensions
696  */
697 GList *
699 {
700  gsize name_len;
701  GDir *dir = NULL;
702  gchar *dentry = NULL;
703  GList *files = NULL;
704 
705  dir = g_dir_open (path, 0, NULL);
706  if (dir == NULL)
707  g_error ("keyb_get_layout_list_from_path ():\n\tCould not find this directory:\n\t%s\n", path);
708 
709  while ( (dentry = g_strdup (g_dir_read_name (dir))) )
710  {
711  name_len = strlen (dentry);
712  if (name_len > 255 || name_len < 5)
713  {
714  g_free (dentry);
715  continue;
716  }
717 
718  if (! g_str_has_suffix (dentry, ".kbd"))
719  {
720  g_free (dentry);
721  continue;
722  }
723 
724  dentry[name_len - 4] = '\0';
725  if (g_str_equal (dentry, ".tmp"))
726  {
727  g_free (dentry);
728  continue;
729  }
730  files = g_list_insert_sorted (files, dentry, compare_string_function);
731  }
732  g_dir_close (dir);
733 
734  return (files);
735 }
736 
737 /* Get the country code from a keyboard name
738  */
739 gchar *
740 keyb_get_country_code (const gchar *kbd)
741 {
742  gchar *code = NULL;
743 
744  code = strchr (kbd, '_');
745  if (code)
746  code = strdup (code + 1);
747  else
748  code = strdup ("xx");
749  code[2] = '\0';
750 
751  return code;
752 }
753 
754 
755 /* Get the country from a keyboard name
756  */
757 gchar *
758 keyb_get_country (const gchar *kbd)
759 {
760  gchar *country = NULL;
761  gchar *code = NULL;
762 
763  code = keyb_get_country_code (kbd);
764  country = g_strdup (trans_code_to_country (code));
765  g_free (code);
766 
767  return country;
768 }
769 
770 /* Get the variant from a keyboard name
771  */
772 gchar *
773 keyb_get_variant (const gchar *kbd)
774 {
775  gchar *begin;
776  gchar *end;
777 
778  begin = g_strdup (kbd);
779  end = strchr (begin, '_');
780  if (end == NULL)
781  return begin;
782  *end = '\0';
783  end++;
784  end = strchr (end, '_');
785  if (end == NULL)
786  return begin;
787  end = g_strconcat (begin, end, NULL);
788  g_free (begin);
789 
790  return end;
791 }
792 
793 /* Set the array of available keyboard layouts
794  */
795 #define LAYOUT_BLOCK 64
796 void
798 {
799  static gboolean init = FALSE;
800  gchar *data;
801  gint i;
802  GList *files;
803 
804  if (! init)
805  {
806 
807  /* Read original layouts just once, now.
808  */
810  layouts.n_orig = g_list_length (files);
811  layouts.orig = g_malloc (layouts.n_orig * sizeof (KeybLayout));
812  //g_printf ("==> Data dir: %s\n", main_path_data ());
813  for (i = 0; i < layouts.n_orig; i++)
814  {
815  data = g_list_nth_data (files, i);
816  //g_printf ("kb(%i): %s\n", i, data);
817  layouts.orig[i].name = data;
818  layouts.orig[i].country = keyb_get_country (data);
819  layouts.orig[i].variant = keyb_get_variant (data);
820  //g_printf ("kb(%i): %s\t", i, layouts.orig[i].name);
821  //g_printf ("%s\t", layouts.orig[i].country);
822  //g_printf ("%s\n", layouts.orig[i].variant);
823  }
824  g_list_free (files);
825 
826  init = TRUE;
827  layouts.n_cust = 0;
828  layouts.cust = g_malloc (LAYOUT_BLOCK * sizeof (KeybLayout));
829  }
830 
831  /*
832  * Reads the list of custom files
833  */
834  for (i = 0; i < layouts.n_cust; i++)
835  g_free (layouts.cust[i].name);
836  assert_user_dir ();
838  layouts.n_cust = g_list_length (files);
839  if (layouts.n_cust == 0)
840  return;
841  if (layouts.n_cust > LAYOUT_BLOCK)
842  layouts.cust = g_realloc (layouts.cust, layouts.n_cust * sizeof (KeybLayout));
843  for (i = 0; i < layouts.n_cust; i++)
844  {
845  data = g_list_nth_data (files, i);
846  layouts.cust[i].name = data;
847  //g_printf ("kb(%i): %s\n", i, layouts.cust[i].name);
848  }
849  g_list_free (files);
850 }
851 
852 void
853 keyb_update_from_variant (gchar *cmb_country, gchar *cmb_variant)
854 {
855  gint i;
856  gchar *country;
857  gchar *variant;
858  GtkComboBox *cmb;
859 
860  cmb = GTK_COMBO_BOX (get_wg (cmb_country));
861  country = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (cmb));
862  if (country == NULL)
863  return;
864 
865  cmb = GTK_COMBO_BOX (get_wg (cmb_variant));
866  variant = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (cmb));
867  if (variant == NULL)
868  {
869  g_free (country);
870  return;
871  }
872 
873  callbacks_shield_set (TRUE);
874 
875  if (g_str_equal (country, KEYB_CUSTOM))
876  {
877  /* Update the keyboard for a custom layout
878  */
879  if (! g_str_equal (variant, KEYB_EDIT))
880  {
881  keyb_set_name (variant);
882  keyb_set_chars ();
884  }
885  }
886  else
887  {
888  /* Update it for a original layout
889  */
890  for (i = 0; i < layouts.n_orig; i++)
891  {
892  if (g_str_equal (layouts.orig[i].country, country))
893  if (g_str_equal (layouts.orig[i].variant, variant))
894  break;
895  }
896 
897  if (i == layouts.n_orig)
898  g_warning ("selected unavailable keyboard layout.");
899  else
900  {
901  keyb_set_name (layouts.orig[i].name);
902  keyb_set_chars ();
904  }
905  }
906 
907  g_free (country);
908  g_free (variant);
909 
910  callbacks_shield_set (FALSE);
911 }
912 
913 void
914 keyb_set_combo_kbd_variant (gchar *cmb_country, gchar *cmb_variant)
915 {
916  gint i;
917  gint n;
918  gchar *country_txt;
919  gboolean valid;
920  GtkComboBox *cmb;
921  GtkTreeModel *tmd;
922  GtkTreeIter iter;
923 
924  callbacks_shield_set (TRUE);
925 
926  /* Clear the combo variant
927  */
928  cmb = GTK_COMBO_BOX (get_wg (cmb_variant));
929  tmd = gtk_combo_box_get_model (cmb);
930  n = 0;
931  valid = gtk_tree_model_get_iter_first (tmd, &iter);
932  while (valid)
933  {
934  n++;
935  valid = gtk_tree_model_iter_next (tmd, &iter);
936  }
937  for (i = 0; i < n; i++)
938  gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (cmb), 0);
939 
940  /* Get the selected country text
941  */
942  country_txt = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (get_wg (cmb_country)));
943  if (country_txt == NULL)
944  {
945  g_warning ("Country combo not set, so nothing done with variant combo.");
946  callbacks_shield_set (FALSE);
947  return;
948  }
949 
950  /* Set the original variants for the selected country */
951  if (! g_str_equal (country_txt, KEYB_CUSTOM))
952  {
953  gchar *current;
954 
955  n = 0;
956  for (i = 0; i < layouts.n_orig; i++)
957  {
958  if (g_str_equal (layouts.orig[i].country, country_txt))
959  {
960  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cmb), layouts.orig[i].variant);
961  n++;
962  }
963  }
964 
965  current = keyb_get_variant (keyb.name);
966  for (i = 0; i < n; i++)
967  {
968  gchar *variant;
969 
970  gtk_combo_box_set_active (cmb, i);
971  variant = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (cmb));
972  if (g_str_equal (variant, current))
973  {
974  g_free (variant);
975  break;
976  }
977  g_free (variant);
978  }
979 
980  if (i == n)
981  {
982  if (n > 0)
983  gtk_combo_box_set_active (cmb, 0);
984  else
985  gtk_combo_box_set_active (cmb, -1);
986  }
987 
988  if (n > 1)
989  gtk_widget_set_sensitive (get_wg (cmb_variant), TRUE);
990  else
991  gtk_widget_set_sensitive (get_wg (cmb_variant), FALSE);
992 
993  g_free (current);
994 
995  }
996  /* Set custom layouts in the variant combo */
997  else
998  {
999  n = 0;
1000  if (g_str_equal (cmb_variant, "combobox_kbd_variant"))
1001  {
1002  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cmb), KEYB_EDIT);
1003  n++;
1004  }
1005  for (i = 0; i < layouts.n_cust; i++)
1006  {
1007  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cmb), layouts.cust[i].name);
1008  n++;
1009  }
1010 
1011  for (i = 0; i < n; i++)
1012  {
1013  gchar *variant;
1014 
1015  gtk_combo_box_set_active (cmb, i);
1016  variant = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (cmb));
1017  if (g_str_equal (variant, keyb.name))
1018  {
1019  g_free (variant);
1020  break;
1021  }
1022  g_free (variant);
1023  }
1024 
1025  if (i == n)
1026  {
1027  if (n > 1)
1028  gtk_combo_box_set_active (cmb, 1);
1029  else if (! gtk_widget_get_visible (get_wg ("window_keyboard")))
1030  {
1031  gtk_combo_box_set_active (cmb, 0);
1032  keyb_mode_edit ();
1033  }
1034  }
1035 
1036  if (layouts.n_cust > 0)
1037  gtk_widget_set_sensitive (get_wg (cmb_variant), TRUE);
1038  else
1039  gtk_widget_set_sensitive (get_wg (cmb_variant), FALSE);
1040  }
1041  g_free (country_txt);
1042 
1043  keyb_update_from_variant (cmb_country, cmb_variant);
1044 
1045  callbacks_shield_set (FALSE);
1046 }
1047 
1048 void
1049 keyb_set_combo_kbd (gchar *cmb_country, gchar *cmb_variant)
1050 {
1051  static gboolean init = FALSE;
1052  gchar *tmp;
1053  gint i, j;
1054  GtkComboBox *cmb;
1055 
1056  callbacks_shield_set (TRUE);
1057 
1058  if (! main_preferences_exist ("tutor", "keyboard"))
1059  main_preferences_set_string ("tutor", "keyboard", trans_get_default_keyboard ());
1060 
1061  if (init == FALSE)
1062  {
1063  tmp = main_preferences_get_string ("tutor", "keyboard");
1064  if (tmp == NULL)
1065  g_error ("Unexpected keyboard layout, NULL");
1066  keyb_init_name (tmp);
1067  keyb_set_chars ();
1068  init = TRUE;
1069  g_free (tmp);
1070  }
1071 
1072  keyb_set_keyboard_layouts (); // if already initialized, this sets only the custom layouts
1073 
1074  cmb = GTK_COMBO_BOX (get_wg (cmb_country));
1075  gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (cmb), 0);
1076  keyb.cmb_n = 0;
1077  for (i = 0; i < layouts.n_orig; i++)
1078  {
1079  j = i - 1;
1080  while (j >= 0)
1081  {
1082  if (g_str_equal (layouts.orig[i].country, layouts.orig[j].country))
1083  break;
1084  j--;
1085  }
1086  if (j < 0)
1087  {
1088  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cmb), layouts.orig[i].country);
1089  keyb.cmb_n++;
1090  }
1091  }
1092  gtk_combo_box_text_prepend_text (GTK_COMBO_BOX_TEXT (cmb), KEYB_CUSTOM);
1093  keyb.cmb_n++;
1094 
1095  keyb_update_combos (cmb_country, cmb_variant);
1096 
1097  callbacks_shield_set (FALSE);
1098 }
1099 
1100 void
1101 keyb_update_combos (gchar *cmb_country, gchar *cmb_variant)
1102 {
1103  gint i;
1104  GtkComboBox *cmb;
1105 
1106  callbacks_shield_set (TRUE);
1107 
1108  cmb = GTK_COMBO_BOX (get_wg (cmb_country));
1109 
1110  for (i = 0; i < layouts.n_orig; i++)
1111  {
1112  if (g_str_equal (keyb.name, layouts.orig[i].name))
1113  break;
1114  }
1115  if (i < layouts.n_orig)
1116  {
1117  gchar *country;
1118  gchar *current;
1119 
1120  /* Set original */
1121  for (i = 1; i < keyb.cmb_n; i++)
1122  {
1123 
1124  gtk_combo_box_set_active (cmb, i);
1125  country = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (cmb));
1126  current = keyb_get_country (keyb.name);
1127  if (g_str_equal (country, current))
1128  {
1129  g_free (country);
1130  g_free (current);
1131  break;
1132  }
1133  g_free (country);
1134  g_free (current);
1135  }
1136  if (i == keyb.cmb_n)
1137  gtk_combo_box_set_active (cmb, 0);
1138  }
1139  else /* Set custom */
1140  gtk_combo_box_set_active (cmb, 0);
1141 
1142  keyb_set_combo_kbd_variant (cmb_country, cmb_variant);
1143 
1144  callbacks_shield_set (FALSE);
1145 }
1146 
1147 void
1149 {
1150  if (keyb.intro_step < 7)
1151  keyb_intro_step (++keyb.intro_step);
1152 }
1153 
1154 void
1156 {
1157  if (keyb.intro_step > 0)
1158  keyb_intro_step (--keyb.intro_step);
1159 }
1160 
1161 void
1162 keyb_intro_step (gint step)
1163 {
1164  gchar *intro00;
1165  GtkLabel *tit;
1166  GtkLabel *tx1;
1167  GtkLabel *tx2;
1168  GtkTextBuffer *buffer;
1169  GtkWidget *wg;
1170 
1171  static gchar *intro01 = NULL;
1172  static gchar *intro02 = NULL;
1173  static gchar *intro03 = NULL;
1174  static gchar *intro04 = NULL;
1175  static gchar *intro05 = NULL;
1176  static gchar *intro06 = NULL;
1177  static gchar *intro07 = NULL;
1178  static gchar *intro08 = NULL;
1179  static gchar *intro09 = NULL;
1180  static gchar *intro10 = NULL;
1181  static gchar *intro11 = NULL;
1182 
1183  if (intro01 == NULL)
1184  {
1185  intro01 = g_strdup (_("Correct positioning of the hands and fingers is very important to efficient typing. "
1186  "You will learn faster and type better if you follow the next recommendations."));
1187  intro02 = g_strdup (_(
1188  "The index-finger tips rest over each of the two keys which have a small raised mark, "
1189  "in the center of the keyboard."));
1190  intro03 = g_strdup (_(
1191  "These marks function as 'tactile hooks' for your fingers to remain at the correct position. "
1192  "This way, with a little experience, you will not need to look at the keyboard to see if your "
1193  "fingers are properly positioned."));
1194  intro04 = g_strdup (_(
1195  "The tips of the other fingers lie naturally beside the index ones, "
1196  "over the keys on the same row of the keyboard."));
1197  intro05 = g_strdup (_(
1198  "The outside edges of your thumbs rest over the space bar."));
1199  intro06 = g_strdup (_(
1200  "The part of the hands closest to the wrist (the base) rest over the table, "
1201  "outside the keyboard. Without this kind of support the arms would quickly tire."));
1202  intro07 = g_strdup (_(
1203  "This is referred to as the home position for the hands. "
1204  "From it the fingers move all over the keyboard, "
1205  "reaching all the keys as naturally and quickly as possible. "
1206  "To reach this goal one uses a specific relation between each key and finger. "
1207  "This relation will be learned gradually as you complete the basic course."));
1208  intro08 = g_strdup (_(
1209  "When learning the relation between fingers and keys, "
1210  "it is very important that you only move the finger which must press the key "
1211  "and allow all other fingers to remain in the home position."));
1212  intro09 = g_strdup (_(
1213  "After memorizing this relationship, you can relax the previous rule some, "
1214  "so that you can attain greater speed while typing."));
1215  intro10 = g_strdup (_(
1216  "The shift keys are used for capital letters and for some symbols. "
1217  "To get a shifted key input you should first use the small finger of the opposite hand. "
1218  "Just keep it in the closest Shift while reaching the target key with the other hand."));
1219  intro11 = g_strdup (_(
1220  "You should be prepared to start training with the basic course. "
1221  "It will take effort and patience to be successful as a typist. "
1222  "We trust you have these and look forward to your success!"));
1223  }
1224 
1225  tit = GTK_LABEL (get_wg ("label_keyboard_title"));
1226  tx1 = GTK_LABEL (get_wg ("label_keyboard_text_1"));
1227  tx2 = GTK_LABEL (get_wg ("label_keyboard_text_2"));
1228 
1229  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (get_wg ("textview_keyboard")));
1230 
1231  intro00 = g_strdup_printf (_("Step %i"), step);
1232  switch (step)
1233  {
1234  case 0: /* Recommendations */
1235  gtk_label_set_text (tit, _("To position the hands"));
1236  gtk_text_buffer_set_text (buffer, intro01, -1);
1237  gtk_widget_grab_focus (get_wg ("button_keyboard_next"));
1238  keyb_set_sensitive (TRUE);
1239  hints_demo_fingers (0);
1240  break;
1241  case 1: /* Index fingers */
1242  gtk_label_set_text (tit, intro00);
1243  gtk_text_buffer_set_text (buffer, intro02, -1);
1244  gtk_text_buffer_insert_at_cursor (buffer, "\n", -1);
1245  gtk_text_buffer_insert_at_cursor (buffer, intro03, -1);
1246  keyb_set_sensitive (FALSE);
1247  gtk_widget_set_sensitive (keyb.but[2][3], TRUE);
1248  gtk_widget_set_sensitive (keyb.but[2][6], TRUE);
1249  hints_demo_fingers (1000);
1250  break;
1251  case 2: /* Fingers beside index */
1252  gtk_label_set_text (tit, intro00);
1253  gtk_text_buffer_set_text (buffer, intro04, -1);
1254  keyb_set_sensitive (FALSE);
1255  gtk_widget_set_sensitive (keyb.but[2][0], TRUE);
1256  gtk_widget_set_sensitive (keyb.but[2][1], TRUE);
1257  gtk_widget_set_sensitive (keyb.but[2][2], TRUE);
1258  gtk_widget_set_sensitive (keyb.but[2][7], TRUE);
1259  gtk_widget_set_sensitive (keyb.but[2][8], TRUE);
1260  gtk_widget_set_sensitive (keyb.but[2][9], TRUE);
1261  hints_demo_fingers (1000/3);
1262  break;
1263  case 3: /* Thumbs and wrists */
1264  gtk_label_set_text (tit, intro00);
1265  gtk_text_buffer_set_text (buffer, intro05, -1);
1266  gtk_text_buffer_insert_at_cursor (buffer, "\n", -1);
1267  gtk_text_buffer_insert_at_cursor (buffer, intro06, -1);
1268  keyb_set_sensitive (FALSE);
1269  gtk_widget_set_sensitive (get_wg ("but_space"), TRUE);
1270  hints_demo_fingers (0);
1271  gtk_widget_grab_focus (get_wg ("but_space"));
1272  hints_update_from_button (GTK_BUTTON (get_wg ("but_space")));
1273  break;
1274  case 4: /* The home position */
1275  gtk_label_set_text (tit, intro00);
1276  gtk_text_buffer_set_text (buffer, intro07, -1);
1277  keyb_set_sensitive (FALSE);
1278  gtk_widget_set_sensitive (keyb.but[2][0], TRUE);
1279  gtk_widget_set_sensitive (keyb.but[2][1], TRUE);
1280  gtk_widget_set_sensitive (keyb.but[2][2], TRUE);
1281  gtk_widget_set_sensitive (keyb.but[2][3], TRUE);
1282  gtk_widget_set_sensitive (keyb.but[2][6], TRUE);
1283  gtk_widget_set_sensitive (keyb.but[2][7], TRUE);
1284  gtk_widget_set_sensitive (keyb.but[2][8], TRUE);
1285  gtk_widget_set_sensitive (keyb.but[2][9], TRUE);
1286  hints_demo_fingers (1000/4);
1287  break;
1288  case 5: /* Reaching keys */
1289  gtk_label_set_text (tit, intro00);
1290  gtk_text_buffer_set_text (buffer, intro08, -1);
1291  gtk_text_buffer_insert_at_cursor (buffer, "\n", -1);
1292  gtk_text_buffer_insert_at_cursor (buffer, intro09, -1);
1293  keyb_set_sensitive (TRUE);
1294  gtk_widget_set_sensitive (keyb.but[2][0], FALSE);
1295  gtk_widget_set_sensitive (keyb.but[2][1], FALSE);
1296  gtk_widget_set_sensitive (keyb.but[2][2], FALSE);
1297  gtk_widget_set_sensitive (keyb.but[2][3], FALSE);
1298  gtk_widget_set_sensitive (keyb.but[2][6], FALSE);
1299  gtk_widget_set_sensitive (keyb.but[2][7], FALSE);
1300  gtk_widget_set_sensitive (keyb.but[2][8], FALSE);
1301  gtk_widget_set_sensitive (keyb.but[2][9], FALSE);
1302  gtk_widget_set_sensitive (get_wg ("but_space"), FALSE);
1303  gtk_widget_set_sensitive (get_wg ("toggle_shift1"), FALSE);
1304  gtk_widget_set_sensitive (get_wg ("toggle_shift2"), FALSE);
1305  hints_demo_fingers (1000/5);
1306  break;
1307  case 6: /* Shift key */
1308  gtk_label_set_text (tit, intro00);
1309  gtk_text_buffer_set_text (buffer, intro10, -1);
1310  keyb_set_sensitive (FALSE);
1311  gtk_widget_set_sensitive (keyb.but[0][0], TRUE);
1312  gtk_widget_set_sensitive (keyb.but[0][13], TRUE);
1313  gtk_widget_set_sensitive (get_wg ("toggle_shift1"), TRUE);
1314  gtk_widget_set_sensitive (get_wg ("toggle_shift2"), TRUE);
1315  hints_demo_fingers (1000/2);
1316  break;
1317  case 7: /* Final words */
1318  gtk_label_set_text (tit, _("Go ahead!"));
1319  gtk_text_buffer_set_text (buffer, intro11, -1);
1320  gtk_widget_grab_focus (get_wg ("button_keyboard_close"));
1321  keyb_set_sensitive (TRUE);
1322  hints_demo_fingers (0);
1323  break;
1324  default:
1325  g_free (intro00);
1326  intro00 = g_strdup (_("Click on any key to see which finger you must use:"));
1327  gtk_label_set_text (tit, _("Relation between fingers and keys"));
1328  gtk_label_set_text (tx1, _("Click on any key to see which finger you must use:"));
1329  gtk_label_set_text (tx2, "");
1330  gtk_text_buffer_set_text (buffer, intro00, -1);
1331  keyb_set_sensitive (TRUE);
1332  hints_demo_fingers (0);
1333  }
1334  g_free (intro00);
1335 
1336  /* Blind people want no fancy autonomous buttons jumping around */
1337  wg = get_wg ("checkbutton_speech");
1338  if (gtk_widget_get_visible (wg) && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wg)))
1339  hints_demo_fingers (0);
1340 
1341  if (step == 0)
1342  gtk_widget_set_sensitive (get_wg ("button_keyboard_previous"), FALSE);
1343  else
1344  gtk_widget_set_sensitive (get_wg ("button_keyboard_previous"), TRUE);
1345 
1346  if (step == 7)
1347  gtk_widget_set_sensitive (get_wg ("button_keyboard_next"), FALSE);
1348  else
1349  gtk_widget_set_sensitive (get_wg ("button_keyboard_next"), TRUE);
1350 
1351  if (step >= 0 && step <= 7)
1352  keyb.intro_step = step;
1353  else
1354  keyb.intro_step = 0;
1355 }
1356 
1357 gchar *
1359 {
1360  gchar *country;
1361  gchar *variant;
1362  static gchar *kbname = NULL;
1363 
1364  if (kbname != NULL)
1365  g_free (kbname);
1366 
1367  country = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (get_wg ("combobox_kbd_country")));
1368  variant = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (get_wg ("combobox_kbd_variant")));
1369  kbname = g_strdup_printf ("%s - %s", country, variant);
1370  g_free (country);
1371  g_free (variant);
1372 
1373  return (kbname);
1374 }
1375 
1376 void
1378 {
1379  gchar *tit;
1380 
1382  gtk_widget_hide (get_wg ("window_hints"));
1383  keyb_edit_none ();
1384 
1385  tit = g_strdup_printf ("%s - %s: %s", _("Introduction"), _("Keyboard"), keyb_mode_get_name ());
1386  gtk_window_set_title (get_win ("window_keyboard"), tit);
1387  g_free (tit);
1388 
1389  gtk_window_set_resizable (get_win ("window_keyboard"), TRUE);
1390  gtk_widget_set_size_request (get_wg ("window_keyboard"), -1, 420);
1391  gtk_widget_hide (get_wg ("label_keyboard_text_1"));
1392  gtk_widget_hide (get_wg ("button_kb_save"));
1393  gtk_widget_hide (get_wg ("button_keyboard_hands"));
1394  gtk_widget_hide (get_wg ("button_keyboard_cancel"));
1395  gtk_widget_hide (get_wg ("hbox_keyboard_selector"));
1396  gtk_widget_hide (get_wg ("hbox_keyboard_saveas"));
1397  gtk_widget_show (get_wg ("label_keyboard_spacer"));
1398  gtk_widget_show (get_wg ("scrolledwindow_keyboard"));
1399  gtk_widget_show (get_wg ("button_keyboard_close"));
1400  gtk_widget_show (get_wg ("button_keyboard_previous"));
1401  gtk_widget_show (get_wg ("button_keyboard_next"));
1402  gtk_widget_show (get_wg ("hbox_keyboard_hints"));
1403 
1404  hints_set_tips ();
1405  keyb_intro_step (0);
1406 
1407  gtk_widget_show (get_wg ("window_keyboard"));
1408 }
1409 
1410 void
1412 {
1413  gchar *tit;
1414 
1416  gtk_widget_hide (get_wg ("window_hints"));
1417  keyb_edit_none ();
1418 
1419  tit = g_strdup_printf ("%s: %s", _("Keyboard"), keyb_mode_get_name ());
1420  gtk_window_set_title (get_win ("window_keyboard"), tit);
1421  g_free (tit);
1422 
1423  gtk_window_set_resizable (get_win ("window_keyboard"), FALSE);
1424  gtk_widget_set_size_request (get_wg ("window_keyboard"), -1, -1);
1425  gtk_widget_hide (get_wg ("label_keyboard_spacer"));
1426  gtk_widget_hide (get_wg ("scrolledwindow_keyboard"));
1427  gtk_widget_hide (get_wg ("button_kb_save"));
1428  gtk_widget_hide (get_wg ("button_keyboard_cancel"));
1429  gtk_widget_hide (get_wg ("button_keyboard_previous"));
1430  gtk_widget_hide (get_wg ("button_keyboard_next"));
1431  gtk_widget_hide (get_wg ("hbox_keyboard_selector"));
1432  gtk_widget_hide (get_wg ("hbox_keyboard_saveas"));
1433  gtk_widget_show (get_wg ("label_keyboard_text_1"));
1434  gtk_widget_show (get_wg ("button_keyboard_hands"));
1435  gtk_widget_show (get_wg ("button_keyboard_close"));
1436  gtk_widget_show (get_wg ("hbox_keyboard_hints"));
1437 
1438  hints_set_tips ();
1439  keyb_intro_step (-1);
1440  gtk_widget_grab_focus (get_wg ("button_keyboard_close"));
1441 
1442  gtk_widget_show (get_wg ("window_keyboard"));
1443 }
1444 
1445 void
1447 {
1448  gchar *tmp;
1449 
1450  /* Save the current name as 'name_last' */
1451  tmp = g_strdup (keyb.name);
1452  keyb_set_name (tmp);
1453  g_free (tmp);
1454 
1455  keyb_set_modified_status (FALSE);
1456  if (layouts.n_cust == 0)
1457  gtk_widget_set_sensitive (get_wg ("button_kb_remove"), FALSE);
1458  else
1459  gtk_widget_set_sensitive (get_wg ("button_kb_remove"), TRUE);
1460 
1461  keyb_update_combos ("combobox_keyboard_country", "combobox_keyboard_variant");
1462 
1464  keyb_edit_none ();
1465 
1466  gtk_window_set_title (get_win ("window_keyboard"), _("Create or modify a custom keyboard layout"));
1467  gtk_window_set_resizable (get_win ("window_keyboard"), FALSE);
1468  gtk_widget_set_size_request (get_wg ("window_keyboard"), -1, -1);
1469  gtk_widget_hide (get_wg ("button_keyboard_hands"));
1470  gtk_widget_hide (get_wg ("button_keyboard_close"));
1471  gtk_widget_hide (get_wg ("button_keyboard_previous"));
1472  gtk_widget_hide (get_wg ("button_keyboard_next"));
1473  gtk_widget_hide (get_wg ("hbox_keyboard_hints"));
1474  gtk_widget_show (get_wg ("button_keyboard_cancel"));
1475  gtk_widget_show (get_wg ("hbox_keyboard_selector"));
1476  gtk_widget_show (get_wg ("hbox_keyboard_saveas"));
1477  gtk_widget_show (get_wg ("button_kb_save"));
1478 
1479  keyb_set_sensitive (TRUE);
1480  gtk_widget_set_sensitive (get_wg ("but_space"), FALSE);
1481 
1482  hints_set_tips ();
1483  gtk_widget_grab_focus (get_wg ("button_keyboard_cancel"));
1484 
1485  gtk_widget_show (get_wg ("window_keyboard"));
1486 }
1487 
1488 void
1489 keyb_set_sensitive (gboolean state)
1490 {
1491  gint i, j;
1492  gint j_max;
1493 
1494  for (i = 0; i < 4; i++)
1495  {
1496  j_max = KEY_LINE_LEN - (i == 0 ? 1 : (i == 1 ? 2 : 3));
1497  for (j = 0; j < j_max; j++)
1498  gtk_widget_set_sensitive (keyb.but[i][j], state);
1499  }
1500  gtk_widget_set_sensitive (get_wg ("but_space"), state);
1501  gtk_widget_set_sensitive (get_wg ("toggle_shift1"), state);
1502  gtk_widget_set_sensitive (get_wg ("toggle_shift2"), state);
1503 }
1504 
1505 gboolean
1506 keyb_button_match (GtkButton * button)
1507 {
1508  gint i, j;
1509  gint j_max;
1510 
1511  for (i = 0; i < 4; i++)
1512  {
1513  j_max = KEY_LINE_LEN - (i == 0 ? 1 : (i == 1 ? 2 : 3));
1514  for (j = 0; j < j_max; j++)
1515  {
1516  if (keyb.but[i][j] == GTK_WIDGET (button))
1517  {
1518  keyb.pos.i = i;
1519  keyb.pos.j = j;
1520  return TRUE;
1521  }
1522  }
1523  }
1524  return FALSE;
1525 }
1526 
1527 /**********************************************************************
1528  * Moves the entry widget to get a real key pressed and
1529  * writes the name of the virtual one.
1530  */
1531 void
1532 keyb_edit_button (GtkButton * button)
1533 {
1534  if (! keyb_button_match (button))
1535  return;
1536 
1537  callbacks_shield_set (TRUE);
1538 
1539  gtk_widget_grab_focus (GTK_WIDGET (button));
1540  gtk_entry_set_text (GTK_ENTRY (keyb.entry),
1541  gtk_label_get_text (GTK_LABEL (keyb.lab[keyb.pos.i][keyb.pos.j])));
1542  gtk_fixed_move (GTK_FIXED (get_wg ("fixed_keyboard")), keyb.entry,
1543  2 + x0[keyb.pos.i] + KEY_DX * keyb.pos.j,
1544  2 + KEY_DY * keyb.pos.i);
1545  if (keyb.pos.i == 1 && keyb.pos.j == 12)
1546  gtk_widget_set_size_request (keyb.entry, 49, 28);
1547  else
1548  gtk_widget_set_size_request (keyb.entry, 28, 28);
1549  gtk_editable_select_region (GTK_EDITABLE (keyb.entry), 0, 1);
1550  gtk_widget_show (keyb.entry);
1551  gtk_widget_grab_focus (keyb.entry);
1552 
1553  callbacks_shield_set (FALSE);
1554 }
1555 
1556 void
1558 {
1559  gtk_widget_hide (keyb.entry);
1560 }
1561 
1562 gboolean
1564 {
1565  keyb.pos.j++;
1566 
1567  switch (keyb.pos.i)
1568  {
1569  case 0:
1570  if (keyb.pos.j > 13)
1571  {
1572  keyb.pos.i++;
1573  keyb.pos.j = 0;
1574  }
1575  break;
1576  case 1:
1577  if (keyb.pos.j > 12)
1578  {
1579  keyb.pos.i++;
1580  keyb.pos.j = 0;
1581  }
1582  break;
1583  default:
1584  if (keyb.pos.j > 11)
1585  {
1586  keyb.pos.i++;
1587  keyb.pos.j = 0;
1588  }
1589  }
1590 
1591  if (keyb.pos.i > 3)
1592  keyb.pos.i = 0;
1593 
1594  gtk_widget_hide (keyb.entry);
1595  if (gtk_widget_get_sensitive (keyb.but[keyb.pos.i][keyb.pos.j]))
1596  {
1597  gtk_widget_grab_focus (keyb.but[keyb.pos.i][keyb.pos.j]);
1598  return TRUE;
1599  }
1600  else
1601  return FALSE;
1602 }
1603 
1604 /**********************************************************************
1605  * Apply the key pressed to the virtual keyboard
1606  * and to the upper or lower character sets
1607  */
1608 void
1609 keyb_change_key (gunichar real_key)
1610 {
1611  gint key_lin, key_col;
1612  gunichar str_char;
1613  gchar tmp_utf8[7];
1614  gboolean tog_state;
1615  GtkWidget *wg;
1616 
1617  key_lin = keyb.pos.i;
1618  key_col = keyb.pos.j;
1619 
1620  str_char = g_unichar_toupper (real_key);
1621  tmp_utf8[g_unichar_to_utf8 (str_char, tmp_utf8)] = '\0';
1622  gtk_label_set_text (GTK_LABEL (keyb.lab[key_lin][key_col]), tmp_utf8);
1623 
1624  wg = get_wg ("toggle_shift1");
1625  tog_state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wg));
1626  if (tog_state)
1627  {
1628  keyb.upchars[key_lin][key_col] = str_char;
1629  if (str_char >= L'A' && str_char <= L'Z')
1630  keyb.lochars[key_lin][key_col] = g_unichar_tolower (str_char);
1631  }
1632  else
1633  {
1634  keyb.lochars[key_lin][key_col] = g_unichar_tolower (str_char);
1635  if (str_char >= L'A' && str_char <= L'Z')
1636  keyb.upchars[key_lin][key_col] = str_char;
1637  }
1638 
1639  keyb_set_modified_status (TRUE);
1640  gtk_widget_set_sensitive (get_wg ("button_kb_save"), TRUE);
1641  gtk_widget_set_sensitive (get_wg ("combobox_keyboard_country"), FALSE);
1642  gtk_widget_set_sensitive (get_wg ("combobox_keyboard_variant"), FALSE);
1643 }
1644 
1645 /*******************************************************************************
1646  * Get an utf8 string for the par symbol
1647  */
1648 gchar *
1650 {
1651  static gchar parsym[7] = {0, 0, 0, 0, 0, 0, 0};
1652  static gboolean is_initialized = FALSE;
1653 
1654  if (is_initialized == FALSE)
1655  {
1656  is_initialized = TRUE;
1657  g_unichar_to_utf8 (UPSYM, parsym);
1658  }
1659  return (parsym);
1660 }
1661 
1662 /*******************************************************************************
1663  * Initialize the hints mapping array
1664  */
1665 static gchar hints[4][KEY_LINE_LEN + 1];
1666 static gboolean hints_is_initialized = FALSE;
1667 
1668 void
1670 {
1671  gint i;
1672  gchar *tmp_name;
1673  gchar *tmp;
1674  FILE *fh;
1675 
1676  if (hints_is_initialized == TRUE)
1677  return;
1678 
1679  tmp_name = g_build_filename ("/etc/klavaro/fingers_position.txt", NULL);
1680  if (!g_file_test (tmp_name, G_FILE_TEST_IS_REGULAR))
1681  {
1682  g_free (tmp_name);
1683  tmp_name = g_build_filename (main_path_user (), "fingers_position.txt", NULL);
1684  }
1685  if (!g_file_test (tmp_name, G_FILE_TEST_IS_REGULAR))
1686  {
1687  g_free (tmp_name);
1688  tmp_name = g_build_filename (main_path_data (), "fingers_position.txt", NULL);
1689  }
1690  fh = (FILE *) g_fopen (tmp_name, "r");
1691  if (fh)
1692  {
1693  hints_is_initialized = TRUE;
1694  for (i = 0; i < 4; i++)
1695  tmp = fgets (hints[i], KEY_LINE_LEN + 1, fh);
1696  fclose (fh);
1697  hints_set_tips ();
1698  hints_set_colors ();
1699  }
1700  else
1701  g_warning ("couldn't open the file:\n %s", tmp_name);
1702  g_free (tmp_name);
1703 
1704 }
1705 
1706 gchar *
1708 {
1709  gchar *fingerhint = NULL;
1710 
1711  switch (charcode)
1712  {
1713  case '1':
1714  fingerhint = g_strdup (_("small finger"));
1715  break;
1716  case '2':
1717  fingerhint = g_strdup (_("ring finger"));
1718  break;
1719  case '3':
1720  fingerhint = g_strdup (_("middle finger"));
1721  break;
1722  case '4':
1723  fingerhint = g_strdup (_("index finger"));
1724  break;
1725  case '5':
1726  fingerhint = g_strdup (_("thumbs"));
1727  break;
1728  case '6':
1729  fingerhint = g_strdup (_("index finger"));
1730  break;
1731  case '7':
1732  fingerhint = g_strdup (_("middle finger"));
1733  break;
1734  case '8':
1735  fingerhint = g_strdup (_("ring finger"));
1736  break;
1737  case '9':
1738  fingerhint = g_strdup (_("small finger"));
1739  break;
1740  default:
1741  fingerhint = g_strdup ("???");
1742  }
1743  return (fingerhint);
1744 }
1745 
1746 gchar *
1748 {
1749  static gchar *hlp = NULL;
1750 
1751  g_free (hlp);
1752 
1753  switch (charcode)
1754  {
1755  case '1':
1756  if (main_preferences_exist ("colors", "key_1"))
1757  hlp = main_preferences_get_string ("colors", "key_1");
1758  else
1759  hlp = g_strdup (KEYB_BLUE);
1760  break;
1761  case '2':
1762  if (main_preferences_exist ("colors", "key_2"))
1763  hlp = main_preferences_get_string ("colors", "key_2");
1764  else
1765  hlp = g_strdup (KEYB_RED);
1766  break;
1767  case '3':
1768  if (main_preferences_exist ("colors", "key_3"))
1769  hlp = main_preferences_get_string ("colors", "key_3");
1770  else
1771  hlp = g_strdup (KEYB_GREEN);
1772  break;
1773  case '4':
1774  if (main_preferences_exist ("colors", "key_4"))
1775  hlp = main_preferences_get_string ("colors", "key_4");
1776  else
1777  hlp = g_strdup (KEYB_YELLOW);
1778  break;
1779  case '5':
1780  if (main_preferences_exist ("colors", "key_5"))
1781  hlp = main_preferences_get_string ("colors", "key_5");
1782  else
1783  hlp = g_strdup (KEYB_PURPLE);
1784  break;
1785  case '6':
1786  if (main_preferences_exist ("colors", "key_6"))
1787  hlp = main_preferences_get_string ("colors", "key_6");
1788  else
1789  hlp = g_strdup (KEYB_ORANGE);
1790  break;
1791  case '7':
1792  if (main_preferences_exist ("colors", "key_7"))
1793  hlp = main_preferences_get_string ("colors", "key_7");
1794  else
1795  hlp = g_strdup (KEYB_GREEN);
1796  break;
1797  case '8':
1798  if (main_preferences_exist ("colors", "key_8"))
1799  hlp = main_preferences_get_string ("colors", "key_8");
1800  else
1801  hlp = g_strdup (KEYB_RED);
1802  break;
1803  case '9':
1804  if (main_preferences_exist ("colors", "key_9"))
1805  hlp = main_preferences_get_string ("colors", "key_9");
1806  else
1807  hlp = g_strdup (KEYB_BLUE);
1808  break;
1809  default:
1810  hlp = g_strdup ("#AFAFAF");
1811  }
1812  return hlp;
1813 }
1814 
1815 void
1817 {
1818  static gchar *editme = NULL;
1819  gint i, j;
1820  gint j_max;
1821  gchar *tmp;
1822 
1823  if (editme == NULL)
1824  editme = g_strdup (_("Press and edit me"));
1825 
1826  if (hints_is_initialized == FALSE)
1827  {
1828  g_warning ("Not able to set keyboard tips without initializing the hints");
1829  return;
1830  }
1831 
1832  for (i = 0; i < 4; i++)
1833  {
1834  j_max = KEY_LINE_LEN - (i == 0 ? 1 : (i == 1 ? 2 : 3));
1835  for (j = 0; j < j_max; j++)
1836  {
1837  tmp = hints_string_from_charcode (hints[i][j]);
1838  if (! gtk_widget_get_visible (get_wg ("hbox_keyboard_hints")))
1839  gtk_widget_set_tooltip_text (keyb.but[i][j], editme);
1840  else
1841  gtk_widget_set_tooltip_text (keyb.but[i][j], tmp);
1842  g_free (tmp);
1843  }
1844  }
1845 }
1846 
1847 void
1849 {
1850  gint i, j;
1851  gint j_max;
1852  GdkRGBA color;
1853  GtkStyleContext *sc;
1854  gchar *tmp;
1855 
1856  if (hints_is_initialized == FALSE)
1857  {
1858  g_warning ("Not able to set keyboard colors without initializing the hints");
1859  return;
1860  }
1861 
1862  for (i = 0; i < 4; i++)
1863  {
1864  j_max = KEY_LINE_LEN - (i == 0 ? 1 : (i == 1 ? 2 : 3));
1865  for (j = 0; j < j_max; j++)
1866  {
1867  sc = gtk_widget_get_style_context (keyb.but[i][j]);
1868  gtk_style_context_add_provider (sc, GTK_STYLE_PROVIDER (keyb_css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1869  tmp = g_strdup_printf ("key-but%c", hints[i][j]);
1870  gtk_style_context_add_class (sc, tmp);
1871  g_free (tmp);
1872  }
1873  }
1874 }
1875 
1876 /* Update the image of the window_keyboard
1877  * Maps the button to the file which shows the finger associated with its key
1878  */
1879 void
1880 hints_update_from_button (GtkButton *button)
1881 {
1882  gchar *pix_name;
1883  gchar ch;
1884 
1885  hints_init (); // if already initialized, do nothing
1886 
1887  if (keyb_button_match (button))
1888  {
1889  pix_name = g_strdup ("hands_0.png");
1890  ch = hints[keyb.pos.i][keyb.pos.j];
1891  if (ch >= '1' && ch <= '9')
1892  pix_name[6] = ch;
1893  }
1894  else if ( button == GTK_BUTTON (get_wg ("but_space")) )
1895  pix_name = g_strdup ("hands_5.png");
1896  else if ( button == GTK_BUTTON (get_wg ("toggle_shift1")) )
1897  pix_name = g_strdup ("hands_1.png");
1898  else if ( button == GTK_BUTTON (get_wg ("toggle_shift2")) )
1899  pix_name = g_strdup ("hands_9.png");
1900  else
1901  pix_name = g_strdup ("hands_0.png");
1902 
1903  set_pixmap ("pixmap_hints_fixed", pix_name);
1904  g_free (pix_name);
1905 }
1906 
1907 /* Update the image of the window_hints
1908  * Maps the character to the file which shows the finger associated with that key
1909  */
1910 void
1911 hints_update_from_char (gunichar character)
1912 {
1913  gchar file_name[32];
1914  gint i, j;
1915 
1916  if (! gtk_widget_get_visible (get_wg ("window_hints")))
1917  return;
1918 
1919  strcpy (file_name, "hands_0.png");
1920  if (character == UPSYM)
1921  strcpy (file_name, "hands_9.png");
1922  else if (character == L' ')
1923  strcpy (file_name, "hands_5.png");
1924  else if (character != 0)
1925  {
1926  hints_init (); // if already initialized, do nothing
1927 
1928  for (i = 3; i >= 0; i--)
1929  for (j = 0; j < 15; j++)
1930  if (character == keyb.lochars[i][j])
1931  {
1932  file_name[6] = hints[i][j];
1933  set_pixmap ("pixmap_hints", file_name);
1934  return;
1935  }
1936 
1937  for (i = 3; i >= 0; i--)
1938  for (j = 0; j < 15; j++)
1939  if (character == keyb.upchars[i][j])
1940  {
1941  file_name[6] = hints[i][j];
1942  set_pixmap ("pixmap_hints", file_name);
1943  return;
1944  }
1945  file_name[6] = '0';
1946  }
1947 
1948  set_pixmap ("pixmap_hints", file_name);
1949 }
1950 
1951 gboolean
1953 {
1954  static int i = 0;
1955 
1956  if (data)
1957  {
1958  keyb.pos.i = 0;
1959  keyb.pos.j = 0;
1960  }
1961 
1962  for (i = 0; i < 500; i++)
1963  if (keyb_edit_next ())
1964  break;
1965  return TRUE;
1966 }
1967 
1968 void
1970 {
1971  static GSource *source = NULL;
1972  guint id;
1973 
1974  if (source != NULL)
1975  g_source_destroy (source);
1976  source = NULL;
1977  hints_demo_fingers_move (&msec);
1978 
1979  if (msec != 0)
1980  {
1981  id = g_timeout_add (msec, hints_demo_fingers_move, NULL);
1982  source = g_main_context_find_source_by_id (NULL, id);
1983  }
1984 }
1985 
1986 gchar *
1988 {
1989  gint i, j;
1990 
1991  if (uch == UPSYM || uch == L'\n' || uch == L'\r')
1992  return (hints_string_from_charcode ('9'));
1993  if (uch == L' ')
1994  return (hints_string_from_charcode ('5'));
1995 
1996  hints_init (); // if already initialized, do nothing
1997 
1998  for (i = 3; i >= 0; i--)
1999  for (j = 0; j < 15; j++)
2000  if (uch == keyb.lochars[i][j])
2001  return (hints_string_from_charcode (hints[i][j]));
2002 
2003  for (i = 3; i >= 0; i--)
2004  for (j = 0; j < 15; j++)
2005  if (uch == keyb.upchars[i][j])
2006  return (hints_string_from_charcode (hints[i][j]));
2007 
2008  return (g_strdup (" "));
2009 }
2010 
void set_pixmap(gchar *widget, gchar *image)
Definition: auxiliar.c:87
GtkWidget * get_wg(gchar *name)
Definition: auxiliar.c:40
void assert_user_dir()
Definition: auxiliar.c:101
gint compare_string_function(gconstpointer a, gconstpointer b)
Definition: auxiliar.c:120
GtkWindow * get_win(gchar *name)
Definition: auxiliar.c:50
#define _(String)
Definition: auxiliar.h:45
G_MODULE_EXPORT void on_virtual_key_changed(GtkEditable *edit, gpointer user_data)
Definition: callbacks.c:1137
G_MODULE_EXPORT void on_virtual_key_grab_focus(GtkWidget *wg, gpointer user_data)
Definition: callbacks.c:1113
void callbacks_shield_set(gboolean state)
Definition: callbacks.c:57
G_MODULE_EXPORT void on_virtual_key_clicked(GtkButton *button, gpointer user_data)
Definition: callbacks.c:1125
gint id
Definition: cursor.c:29
gchar * hints_finger_name_from_char(gunichar uch)
Definition: keyboard.c:1987
guint i
Definition: keyboard.c:55
gchar * keyb_get_name()
Definition: keyboard.c:204
GtkWidget * entry
Definition: keyboard.c:52
void hints_set_tips()
Definition: keyboard.c:1816
void keyb_intro_step_previous()
Definition: keyboard.c:1155
void hints_demo_fingers(guint msec)
Definition: keyboard.c:1969
gunichar upchars[4][(14+1)+1]
Definition: keyboard.c:49
GtkWidget * but[4][(14+1) - 1]
Definition: keyboard.c:50
void keyb_set_chars()
Definition: keyboard.c:361
void keyb_remove_user_layout()
Definition: keyboard.c:640
void keyb_set_sensitive(gboolean state)
Definition: keyboard.c:1489
gboolean hints_demo_fingers_move(gpointer data)
Definition: keyboard.c:1952
#define LAYOUT_BLOCK
Definition: keyboard.c:795
void keyb_set_keyboard_layouts()
Definition: keyboard.c:797
void keyb_intro_step(gint step)
Definition: keyboard.c:1162
gunichar keyb_unichar_toupper(gunichar uchar)
Definition: keyboard.c:591
gchar * KEYB_EDIT
Definition: main.c:42
gboolean keyb_is_vowel(gunichar chr)
Definition: keyboard.c:462
void keyb_update_virtual_layout()
Definition: keyboard.c:671
void keyb_mode_hint()
Definition: keyboard.c:1411
static gchar hints[4][(14+1)+1]
Definition: keyboard.c:1665
static struct @4 keyb
gint intro_step
Definition: keyboard.c:59
const gunichar diacritics[]
Definition: keyboard.c:95
static guint x0[4]
Definition: keyboard.c:61
KeybLayout * orig
Definition: keyboard.c:65
void keyb_update_combos(gchar *cmb_country, gchar *cmb_variant)
Definition: keyboard.c:1101
gint keyb_get_altnums(gunichar *altnums)
Definition: keyboard.c:567
gchar * keyb_get_utf8_paragraph_symbol()
Definition: keyboard.c:1649
gchar * KEYB_CUSTOM
Definition: main.c:41
void keyb_edit_button(GtkButton *button)
Definition: keyboard.c:1532
guint j
Definition: keyboard.c:56
void keyb_set_name(const gchar *name)
Definition: keyboard.c:216
void hints_update_from_char(gunichar character)
Definition: keyboard.c:1911
gboolean modified_status
Definition: keyboard.c:47
void hints_set_colors()
Definition: keyboard.c:1848
gchar * name_last
Definition: keyboard.c:46
gint keyb_get_consonants(gunichar *consonants)
Definition: keyboard.c:518
gboolean keyb_button_match(GtkButton *button)
Definition: keyboard.c:1506
gunichar keyb_get_lochars(gint i, gint j)
Definition: keyboard.c:232
gboolean keyb_get_modified_status()
Definition: keyboard.c:244
gboolean keyb_is_inset(gunichar chr)
Definition: keyboard.c:442
gchar * keyb_mode_get_name()
Definition: keyboard.c:1358
gchar * keyb_get_country_code(const gchar *kbd)
Definition: keyboard.c:740
void keyb_mode_intro()
Definition: keyboard.c:1377
gchar * keyb_get_name_last()
Definition: keyboard.c:210
gint n_orig
Definition: keyboard.c:66
gunichar lochars[4][(14+1)+1]
Definition: keyboard.c:48
gint keyb_get_vowels(gunichar *vows)
Definition: keyboard.c:491
gchar * keyb_get_country(const gchar *kbd)
Definition: keyboard.c:758
KeybLayout * cust
Definition: keyboard.c:67
gboolean keyb_edit_next(void)
Definition: keyboard.c:1563
static gboolean hints_is_initialized
Definition: keyboard.c:1666
void keyb_set_combo_kbd(gchar *cmb_country, gchar *cmb_variant)
Definition: keyboard.c:1049
gunichar keyb_get_upchars(gint i, gint j)
Definition: keyboard.c:238
GList * keyb_get_layout_list_from_path(gchar *path)
Definition: keyboard.c:698
void keyb_init_name(const gchar *name)
Definition: keyboard.c:225
gboolean keyb_is_diacritic(gunichar chr)
Definition: keyboard.c:476
void keyb_mode_edit()
Definition: keyboard.c:1446
GtkWidget * lab[4][(14+1) - 1]
Definition: keyboard.c:51
gint keyb_get_symbols(gunichar *symbols)
Definition: keyboard.c:543
gchar * name
Definition: keyboard.c:45
void keyb_set_modified_status(gboolean new_status)
Definition: keyboard.c:250
static struct @5 layouts
void keyb_intro_step_next()
Definition: keyboard.c:1148
struct @4::@6 pos
gchar * hints_color_from_charcode(gchar charcode)
Definition: keyboard.c:1747
#define KEY_DY
Definition: keyboard.c:35
void keyb_create_virtual_keys()
Definition: keyboard.c:266
gint n_cust
Definition: keyboard.c:68
void keyb_update_from_variant(gchar *cmb_country, gchar *cmb_variant)
Definition: keyboard.c:853
#define KEY_DX
Definition: keyboard.c:34
GtkCssProvider * keyb_css
Definition: keyboard.c:41
gchar * keyb_get_variant(const gchar *kbd)
Definition: keyboard.c:773
gint cmb_n
Definition: keyboard.c:58
gchar * hints_string_from_charcode(gchar charcode)
Definition: keyboard.c:1707
void hints_init()
Definition: keyboard.c:1669
void keyb_set_combo_kbd_variant(gchar *cmb_country, gchar *cmb_variant)
Definition: keyboard.c:914
const gunichar vowels[]
Definition: keyboard.c:73
void keyb_save_new_layout()
Definition: keyboard.c:608
void hints_update_from_button(GtkButton *button)
Definition: keyboard.c:1880
void keyb_edit_none(void)
Definition: keyboard.c:1557
void keyb_change_key(gunichar real_key)
Definition: keyboard.c:1609
#define KEYB_YELLOW
Definition: keyboard.h:37
#define KEYB_PURPLE
Definition: keyboard.h:39
#define KEY_LINE_LEN
Definition: keyboard.h:21
#define KEYB_RED
Definition: keyboard.h:35
#define UPSYM
Definition: keyboard.h:23
#define KEYB_ORANGE
Definition: keyboard.h:38
#define KEYB_BLUE
Definition: keyboard.h:36
#define KEYB_BLACK
Definition: keyboard.h:40
#define KEYB_GREEN
Definition: keyboard.h:34
void main_preferences_remove(gchar *group, gchar *key)
Definition: main.c:103
gchar * main_preferences_get_string(gchar *group, gchar *key)
Definition: main.c:109
static struct @7 path
gchar * main_path_user()
Definition: main.c:61
gboolean main_preferences_exist(gchar *group, gchar *key)
Definition: main.c:97
void main_preferences_set_string(gchar *group, gchar *key, gchar *value)
Definition: main.c:115
gchar * data
Definition: main.c:53
gchar * main_path_data()
Definition: main.c:73
gchar * trans_get_default_keyboard()
Definition: translation.c:120
const gchar * trans_code_to_country(gchar *code)
Definition: translation.c:46