/*****************************************************************************/ /* Klavaro - a flexible touch typing tutor */ /* Copyright (C) 2005, 2006, 2007, 2008 Felipe Castro */ /* Copyright (C) 2009 Free Software Foundation */ /* */ /* This program is free software, licensed under the terms of the GNU */ /* General Public License as published by the Free Software Foundation, */ /* either version 3 of the License, or (at your option) any later version. */ /* You should have received a copy of the GNU General Public License */ /* along with this program. If not, see . */ /*****************************************************************************/ /* * Basic course */ #include #include #include #include #include #include #include #include "auxiliar.h" #include "main.h" #include "keyboard.h" #include "tutor.h" #include "basic.h" #define MAX_BASIC_CHAR_SET (8 * 14) struct { gint lesson; gunichar char_set[MAX_BASIC_CHAR_SET]; glong char_set_size; gboolean lesson_increased; } basic; /******************************************************************************* * Interface functions */ gint basic_get_lesson () { return (basic.lesson); } void basic_set_lesson (gint lesson) { basic.lesson = lesson; main_preferences_set_int ("tutor", "basic_lesson", lesson); } gunichar * basic_get_char_set () { return (basic.char_set); } gboolean basic_get_lesson_increased () { return (basic.lesson_increased); } void basic_set_lesson_increased (gboolean state) { basic.lesson_increased = state; } /******************************************************************************* * Initialize basic vars */ void basic_init () { /* Retrieve the last lesson where the student had selected. */ basic.lesson_increased = FALSE; if (main_preferences_exist ("tutor", "basic_lesson")) basic.lesson = main_preferences_get_int ("tutor", "basic_lesson"); else basic_set_lesson (1); basic_init_char_set (); } /********************************************************************** * Read the characters to be used with the current basic.lesson */ gint basic_init_char_set () { gint i, j, k; gchar line_str[16]; gchar *lesson_file; gchar *lesson_str; gunichar *tmpuc; FILE *fh; GtkWidget *wg; /* * Custom lessons */ wg = get_wg ("togglebutton_edit_basic_lesson"); if (basic.lesson > 43 && basic.lesson <= 50) { lesson_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "basic_lesson_%i.txt", main_path_user (), basic.lesson); if (g_file_get_contents (lesson_file, &lesson_str, NULL, NULL)) { tmpuc = g_utf8_to_ucs4_fast (lesson_str, -1, &basic.char_set_size); if (basic.char_set_size > MAX_BASIC_CHAR_SET) basic.char_set_size = MAX_BASIC_CHAR_SET; for (i = j = 0; i < basic.char_set_size; i++) if (g_unichar_isgraph (tmpuc[i])) basic.char_set[j++] = tmpuc[i]; basic.char_set[j] = L'\0'; basic.char_set_size = j; g_free (tmpuc); g_free (lesson_str); } else { basic.char_set[0] = L' '; basic.char_set[1] = L' '; basic.char_set[2] = L'\0'; basic.char_set_size = 2; } g_free (lesson_file); gtk_widget_set_sensitive (wg, TRUE); return (-1); } gtk_widget_set_sensitive (wg, FALSE); /* * Open the lesson file */ lesson_file = g_build_filename (main_path_data (), "basic_lessons.txt", NULL); fh = (FILE *) g_fopen (lesson_file, "r"); g_free (lesson_file); if (!fh) g_error ("couldn't find the basic lessons' file."); /* * Search the lesson */ for (i = 1; i < basic.lesson; i++) for (j = 0; j < 11; j++) if (!(fgets (line_str, 16, fh))) break; /* * Pass heading line */ if (!(fgets (line_str, 16, fh))) { basic.char_set[0] = L'\0'; basic.char_set_size = 0; fclose (fh); return (-1); } /* * Get chars, lower set */ for (k = 0, i = 0; i < 4; i++) { if (!(fgets (line_str, 16, fh))) { basic.char_set[0] = L'\0'; basic.char_set_size = 0; fclose (fh); return (-1); } for (j = 0; j < 14; j++) { if (line_str[j] == '1' && g_unichar_isgraph (keyb_get_lochars (i, j))) basic.char_set[k++] = g_unichar_tolower (keyb_get_lochars (i, j)); } } /* * Pass blank line */ if (!(fgets (line_str, 16, fh))) { basic.char_set[0] = L'\0'; basic.char_set_size = 0; fclose (fh); return (-1); } /* * Get chars, upper set */ for (i = 0; i < 4; i++) { if (!(fgets (line_str, 16, fh))) { basic.char_set[0] = L'\0'; basic.char_set_size = 0; fclose (fh); return (-1); } for (j = 0; j < 14; j++) if (line_str[j] == '1' && g_unichar_isgraph (keyb_get_upchars (i, j))) basic.char_set[k++] = g_unichar_tolower (keyb_get_upchars (i, j)); } fclose (fh); basic.char_set[k] = L'\0'; basic.char_set_size = k; return (0); } /********************************************************************** * Save the lesson's character set defined in the custom lesson entry, * for the current lesson */ void basic_save_lesson (gchar * charset) { gchar *lesson_file; FILE *fh; lesson_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "basic_lesson_%i.txt", main_path_user (), basic.lesson); fh = (FILE *) g_fopen (lesson_file, "w"); if (fh == NULL) g_warning ("couldn't save the file:\n %s", lesson_file); else { fprintf (fh, "%s", charset); fclose (fh); if (strlen (charset) < 2) g_unlink (lesson_file); } g_free (lesson_file); } /********************************************************************** * Put the lesson's characters at the main screen */ #define N_LINES 8 void basic_draw_lesson () { gint i, j, k, len; gint remain, idx, rnd; gchar *ut8_tmp; gunichar sentence[9 * 6 + 4]; gunichar char_pool[N_LINES * 9 * 5]; GtkWidget *wg; GtkTextBuffer *buf; wg = get_wg ("text_tutor"); buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (wg)); /* * Fill in the character pool */ if ((len = basic.char_set_size) < 2) { g_warning ("no character set for this lesson."); return; } for (k = 0; k < (N_LINES * 9 * 5 - len); k += len) { memmove (char_pool + k, basic.char_set, len * sizeof (gunichar)); } remain = (N_LINES * 9 * 5) % len; remain = remain ? remain : len; memmove (char_pool + k, basic.char_set, remain * sizeof (gunichar)); /* * Draw the lines as sentences */ sentence[9 * 6] = L'\n'; sentence[9 * 6 + 1] = L'\0'; sentence[9 * 6 + 2] = L'\0'; len = N_LINES * 9 * 5; for (i = 0; i < N_LINES; i++) { /* lines (sentences) */ idx = 0; for (j = 0; j < 9; j++) { /* words */ for (k = 0; k < 5; k++) { /* letters */ rnd = rand () % len; sentence[idx++] = char_pool[rnd]; char_pool[rnd] = char_pool[--len]; if (keyb_is_diacritic (sentence[idx-1])) sentence[idx-1] = L' '; } sentence[idx++] = (j < 8) ? L' ' : UPSYM; } ut8_tmp = g_ucs4_to_utf8 (sentence, -1, NULL, NULL, NULL); gtk_text_buffer_insert_at_cursor (buf, ut8_tmp, -1); g_free (ut8_tmp); } } /********************************************************************** * Put on the screen the final comments */ void basic_comment (gdouble accuracy) { gchar *tmp_str; GtkLabel *wg_label; GtkWidget *wg; GtkTextBuffer *buf; /* * Comments */ if (accuracy < tutor_goal_accuracy ()) /* tmp_str = g_strdup_printf (_(" You did not succeed.\n" " The accuracy must be above %.0f%%.\n" " Try again!\n"), tutor_goal_accuracy ()); */ tmp_str = g_strdup (":-(\n"); else { basic_set_lesson (basic.lesson + 1); if (basic.lesson > 43) { if (basic.lesson > 50) basic_set_lesson (50); wg_label = GTK_LABEL (get_wg ("label_heading")); gtk_label_set_text (wg_label, _("Positions of keys seems to be learned!")); tmp_str = g_strdup (_(" Congratulations!\n" " You have accomplished the entire basic course.\n" " Go to the next type of exercise: adaptability.\n" " There you will practice mainly the accuracy.\n")); } else tmp_str = g_strdup (_(" All right, now you got it!\n Go to the next lesson.\n")); basic_init_char_set (); if (basic.lesson != 50) basic.lesson_increased = TRUE; } wg = get_wg ("text_tutor"); buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (wg)); gtk_text_buffer_insert_at_cursor (buf, tmp_str, strlen (tmp_str)); g_free (tmp_str); }