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)  

basic.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 /*
19  * Basic course
20  */
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <glib.h>
26 #include <glib/gstdio.h>
27 #include <gtk/gtk.h>
28 
29 #include "auxiliar.h"
30 #include "main.h"
31 #include "keyboard.h"
32 #include "tutor.h"
33 #include "basic.h"
34 
35 #define MAX_BASIC_CHAR_SET (8 * 14)
36 struct
37 {
38  gint lesson;
41  gboolean lesson_increased;
43 
44 /*******************************************************************************
45  * Interface functions
46  */
47 gint
49 {
50  return (basic.lesson);
51 }
52 
53 void
55 {
56  if (lesson >= 0)
57  {
58  basic.lesson = lesson;
59  main_preferences_set_int ("tutor", "basic_lesson", lesson);
60  }
61 }
62 
63 gunichar *
65 {
66  return (basic.char_set);
67 }
68 
69 gboolean
71 {
72  return (basic.lesson_increased);
73 }
74 
75 void
77 {
78  basic.lesson_increased = state;
79 }
80 
81 /*******************************************************************************
82  * Initialize basic vars
83  */
84 void
86 {
87  /* Retrieve the last lesson where the student had selected.
88  */
89  basic.lesson_increased = FALSE;
90 
91  if (main_preferences_exist ("tutor", "basic_lesson"))
92  basic.lesson = main_preferences_get_int ("tutor", "basic_lesson");
93  else
94  basic_set_lesson (1);
96 }
97 
98 /**********************************************************************
99  * Read the characters to be used with the current basic.lesson
100  */
101 gint
103 {
104  gint i, j, k;
105  gchar line_str[16];
106  gchar *lesson_file;
107  gchar *lesson_str;
108  gunichar *tmpuc;
109  FILE *fh;
110  GtkWidget *wg;
111 
112  /*
113  * Custom lessons
114  */
115  wg = get_wg ("togglebutton_edit_basic_lesson");
116  if (basic.lesson > 43 && basic.lesson <= MAX_BASIC_LESSONS)
117  {
118  lesson_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "basic_lesson_%i.txt",
119  main_path_user (), basic.lesson);
120  if (g_file_get_contents (lesson_file, &lesson_str, NULL, NULL))
121  {
122  tmpuc = g_utf8_to_ucs4_fast (lesson_str, -1, &basic.char_set_size);
123  if (basic.char_set_size > MAX_BASIC_CHAR_SET)
124  basic.char_set_size = MAX_BASIC_CHAR_SET;
125  for (i = j = 0; i < basic.char_set_size; i++)
126  if (g_unichar_isgraph (tmpuc[i]))
127  basic.char_set[j++] = tmpuc[i];
128  basic.char_set[j] = L'\0';
129  basic.char_set_size = j;
130  g_free (tmpuc);
131  g_free (lesson_str);
132  }
133  else
134  {
135  basic.char_set[0] = L' ';
136  basic.char_set[1] = L' ';
137  basic.char_set[2] = L'\0';
138  basic.char_set_size = 2;
139  }
140  g_free (lesson_file);
141 
142  gtk_widget_set_sensitive (wg, TRUE);
143  return (-1);
144  }
145  gtk_widget_set_sensitive (wg, FALSE);
146 
147  /*
148  * Open the lesson file
149  */
150  lesson_file = g_build_filename (main_path_data (), "basic_lessons.txt", NULL);
151  fh = (FILE *) g_fopen (lesson_file, "r");
152  g_free (lesson_file);
153  if (!fh)
154  g_error ("couldn't find the basic lessons' file.");
155 
156  /*
157  * Search the lesson
158  */
159  for (i = 1; i < basic.lesson; i++)
160  for (j = 0; j < 11; j++)
161  if (!(fgets (line_str, 16, fh)))
162  break;
163 
164  /*
165  * Pass heading line
166  */
167  if (!(fgets (line_str, 16, fh)))
168  {
169  basic.char_set[0] = L'\0';
170  basic.char_set_size = 0;
171  fclose (fh);
172  return (-1);
173  }
174 
175  /*
176  * Get chars, lower set
177  */
178  for (k = 0, i = 0; i < 4; i++)
179  {
180  if (!(fgets (line_str, 16, fh)))
181  {
182  basic.char_set[0] = L'\0';
183  basic.char_set_size = 0;
184  fclose (fh);
185  return (-1);
186  }
187  for (j = 0; j < 14; j++)
188  {
189  if (line_str[j] == '1' && g_unichar_isgraph (keyb_get_lochars (i, j)))
190  basic.char_set[k++] = g_unichar_tolower (keyb_get_lochars (i, j));
191  }
192  }
193 
194  /*
195  * Pass blank line
196  */
197  if (!(fgets (line_str, 16, fh)))
198  {
199  basic.char_set[0] = L'\0';
200  basic.char_set_size = 0;
201  fclose (fh);
202  return (-1);
203  }
204 
205  /*
206  * Get chars, upper set
207  */
208  for (i = 0; i < 4; i++)
209  {
210  if (!(fgets (line_str, 16, fh)))
211  {
212  basic.char_set[0] = L'\0';
213  basic.char_set_size = 0;
214  fclose (fh);
215  return (-1);
216  }
217  for (j = 0; j < 14; j++)
218  if (line_str[j] == '1' && g_unichar_isgraph (keyb_get_upchars (i, j)))
219  basic.char_set[k++] = g_unichar_tolower (keyb_get_upchars (i, j));
220  }
221  fclose (fh);
222 
223  basic.char_set[k] = L'\0';
224  basic.char_set_size = k;
225  return (0);
226 }
227 
228 /**********************************************************************
229  * Save the lesson's character set defined in the custom lesson entry,
230  * for the current lesson
231  */
232 void
233 basic_save_lesson (gchar * charset)
234 {
235  gchar *lesson_file;
236  FILE *fh;
237 
238  lesson_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "basic_lesson_%i.txt", main_path_user (), basic.lesson);
239  fh = (FILE *) g_fopen (lesson_file, "w");
240  if (fh == NULL)
241  g_warning ("couldn't save the file:\n %s", lesson_file);
242  else
243  {
244  fprintf (fh, "%s", charset);
245  fclose (fh);
246  if (strlen (charset) < 2)
247  g_unlink (lesson_file);
248  }
249  g_free (lesson_file);
250 }
251 
252 /**********************************************************************
253  * Put the lesson's characters at the main screen
254  */
255 #define N_LINES 8
256 void
258 {
259  gint i, j, k, len;
260  gint idx, rnd;
261  gchar *ut8_tmp;
262  gunichar sentence[9 * 6 + 4];
263  gunichar char_pool[2*(N_LINES * 9 * 5)];
264  GtkTextBuffer *buf;
265 
266  buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (get_wg ("text_tutor")));
267 
268  len = basic.char_set_size;
269  if (len < 2)
270  {
271  g_warning ("No character set for this lesson.");
272  return;
273  }
274 
275  if (basic.char_set[0] == basic.char_set[1])
276  {
277  ut8_tmp = g_strconcat (_("This custom lesson is empty."
278  " You can define two or more different characters "
279  "to generate a personal practice."
280  " Press the editting button in the upper-right corner."),
281  keyb_get_utf8_paragraph_symbol (), "\n", NULL);
282  gtk_text_buffer_insert_at_cursor (buf, ut8_tmp, -1);
283  gtk_text_buffer_insert_at_cursor (buf, ut8_tmp, -1);
284  gtk_text_buffer_insert_at_cursor (buf, ut8_tmp, -1);
285  gtk_text_buffer_insert_at_cursor (buf, ut8_tmp, -1);
286  g_free (ut8_tmp);
287  return;
288  }
289 
290  /*
291  * Draw the lines as sentences
292  */
293  memmove (char_pool, basic.char_set, len * sizeof (gunichar));
294  if (len > 4 && len < 14)
295  {
296  memmove (char_pool+len, basic.char_set, len * sizeof (gunichar));
297  len *= 2;
298  }
299  sentence[9 * 6] = L'\n';
300  sentence[9 * 6 + 1] = L'\0';
301  sentence[9 * 6 + 2] = L'\0';
302  for (i = 0; i < N_LINES; i++)
303  { /* lines (sentences) */
304  idx = 0;
305  for (j = 0; j < 9; j++)
306  { /* words */
307  for (k = 0; k < 5; k++)
308  { /* letters */
309  rnd = rand () % len;
310  sentence[idx++] = char_pool[rnd];
311  len--;
312  char_pool[rnd] = char_pool[len];
313  if (len == 0)
314  {
315  len = basic.char_set_size;
316  memmove (char_pool, basic.char_set, len * sizeof (gunichar));
317  if (len > 4 && len < 14)
318  {
319  memmove (char_pool+len, basic.char_set, len * sizeof (gunichar));
320  len *= 2;
321  }
322  }
323  if (keyb_is_diacritic (sentence[idx-1]))
324  {
325  if (tutor_is_tibetan())
326  {
327  if (k > 0 && keyb_is_vowel(sentence[idx-1]) && keyb_is_vowel(sentence[idx-2]) )
328  {
329  sentence[idx-1] = TIBETAN_WORD_DELIMITER;
330  }
331  }
332  else
333  {
334  sentence[idx-1] = L' ';
335  }
336  }
337  }
338  if (j == 8)
339  sentence[idx] = UPSYM;
340  else
341  sentence[idx] = tutor_is_tibetan() ? TIBETAN_WORD_DELIMITER : L' ';
342  idx++;
343  }
344  ut8_tmp = g_ucs4_to_utf8 (sentence, -1, NULL, NULL, NULL);
345  gtk_text_buffer_insert_at_cursor (buf, ut8_tmp, -1);
346  g_free (ut8_tmp);
347  if (len == 2 && i >= N_LINES/2-1)
348  break;
349  }
350 }
351 
352 /**********************************************************************
353  * Put on the screen the final comments
354  */
355 void
357 {
358  gchar *tmp_str;
359  GtkLabel *wg_label;
360  GtkWidget *wg;
361  GtkTextBuffer *buf;
362 
363  /*
364  * Comments
365  */
366  if (accuracy < tutor_goal_accuracy ())
367  tmp_str = g_strdup (":-(\n");
368  else
369  {
370  basic_set_lesson (basic.lesson + 1);
371  if (basic.lesson > 43)
372  {
373  if (basic.lesson > MAX_BASIC_LESSONS)
375  wg_label = GTK_LABEL (get_wg ("label_heading"));
376  gtk_label_set_text (wg_label, _("Positions of keys seems to be learned!"));
377  tmp_str = g_strdup (_(" Congratulations!\n"
378  " You have accomplished the entire basic course.\n"
379  " Go to the next type of exercise: adaptability.\n"
380  " There you will practice mainly the accuracy.\n"));
381  }
382  else
383  tmp_str = g_strdup (_(" All right, now you got it!\n Go to the next lesson.\n"));
384 
386  if (basic.lesson != MAX_BASIC_LESSONS)
387  basic.lesson_increased = TRUE;
388  }
389 
390  wg = get_wg ("text_tutor");
391  buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (wg));
392  gtk_text_buffer_insert_at_cursor (buf, tmp_str, strlen (tmp_str));
393  g_free (tmp_str);
394 }
gint idx
Definition: accuracy.c:48
GtkWidget * get_wg(gchar *name)
Definition: auxiliar.c:40
#define _(String)
Definition: auxiliar.h:45
gboolean lesson_increased
Definition: basic.c:41
gunichar char_set[(8 *14)]
Definition: basic.c:39
void basic_set_lesson_increased(gboolean state)
Definition: basic.c:76
gboolean basic_get_lesson_increased()
Definition: basic.c:70
void basic_set_lesson(gint lesson)
Definition: basic.c:54
gint basic_init_char_set()
Definition: basic.c:102
gint basic_get_lesson()
Definition: basic.c:48
#define N_LINES
Definition: basic.c:255
gunichar * basic_get_char_set()
Definition: basic.c:64
#define MAX_BASIC_CHAR_SET
Definition: basic.c:35
void basic_save_lesson(gchar *charset)
Definition: basic.c:233
gint lesson
Definition: basic.c:38
glong char_set_size
Definition: basic.c:40
struct @2 basic
void basic_init()
Definition: basic.c:85
void basic_draw_lesson()
Definition: basic.c:257
void basic_comment(gdouble accuracy)
Definition: basic.c:356
#define MAX_BASIC_LESSONS
Definition: basic.h:18
guint i
Definition: keyboard.c:55
gboolean keyb_is_vowel(gunichar chr)
Definition: keyboard.c:462
gchar * keyb_get_utf8_paragraph_symbol()
Definition: keyboard.c:1649
guint j
Definition: keyboard.c:56
gunichar keyb_get_lochars(gint i, gint j)
Definition: keyboard.c:232
gunichar keyb_get_upchars(gint i, gint j)
Definition: keyboard.c:238
gboolean keyb_is_diacritic(gunichar chr)
Definition: keyboard.c:476
#define UPSYM
Definition: keyboard.h:23
#define TIBETAN_WORD_DELIMITER
Definition: keyboard.h:27
gint main_preferences_get_int(gchar *group, gchar *key)
Definition: main.c:121
void main_preferences_set_int(gchar *group, gchar *key, gint value)
Definition: main.c:127
gchar * main_path_user()
Definition: main.c:61
gboolean main_preferences_exist(gchar *group, gchar *key)
Definition: main.c:97
gchar * main_path_data()
Definition: main.c:73
gboolean tutor_is_tibetan()
Definition: tutor.c:121
gdouble tutor_goal_accuracy()
Definition: tutor.c:240
double accuracy
Definition: tutor.c:67
gint len
Definition: velocity.c:40