dict @ 03aa0fe6c664f74e8e4e5877ef89b4e053b30bc5

feat: Add initial ncurses support

Alongside with loading and saving data from the dict.cc's text.
  1diff --git a/CMakeLists.txt b/CMakeLists.txt
  2index 2614aa6f52b569feba19c53168c92e37ffaa32d3..c34734d2daf984075b1bed87f236c2ac33e5ded2 100644
  3--- a/CMakeLists.txt
  4+++ b/CMakeLists.txt
  5@@ -7,5 +7,5 @@ add_executable(dict ${src})
  6 
  7 target_compile_options(dict PRIVATE -Wall -Wextra -Wpedantic -Werror)
  8 target_include_directories(dict PUBLIC "${PROJECT_BINARY_DIR}")
  9-target_link_libraries(dict sqlite3)
 10+target_link_libraries(dict sqlite3 ncursesw)
 11 
 12diff --git a/data.c b/data.c
 13index 5a9a103daf2dd02f9b494385a08cbbe4a8e316ea..777dcdf58b260a0ecf8c50fb56132b34d0a6c35d 100644
 14--- a/data.c
 15+++ b/data.c
 16@@ -25,7 +25,7 @@     sqlite3_close(data->db);
 17     free(data);
 18 }
 19 
 20-void insert(Data* data, char* line) {
 21+void insert(Data* data, char* line, int len) {
 22     sqlite3_stmt *stmt; 
 23     int r = sqlite3_prepare_v2(data->db, insert_into, -1, &stmt, NULL);
 24 
 25@@ -37,7 +37,7 @@         return;
 26     }
 27 
 28     // binds the paremets to the statement, in this case the line;
 29-    sqlite3_bind_text(stmt, 1, line, -1, NULL);
 30+    sqlite3_bind_text(stmt, 1, line, len, NULL);
 31 
 32     int c = sqlite3_step(stmt);
 33     if (c != SQLITE_DONE) {
 34@@ -45,6 +45,8 @@         printf("Error executing insert: ");
 35         print_result_code(r);
 36         printf("\n");
 37     }
 38+
 39+    sqlite3_finalize(stmt);
 40 }
 41 
 42 void bootstrap(Data* data) {
 43@@ -64,6 +66,8 @@         printf("Error executing bootstrap: ");
 44         print_result_code(r);
 45         printf("\n");
 46     }
 47+
 48+    sqlite3_finalize(stmt);
 49 }
 50 
 51 LIST* select(Data* data) {
 52diff --git a/data.h b/data.h
 53index db8aedc2a5e9ea62ef2f577718b9dbf8418c9a4c..393f8308c1ccf9032745260ee3ef84b9d5af3462 100644
 54--- a/data.h
 55+++ b/data.h
 56@@ -34,7 +34,7 @@
 57 /*
 58  * insert line into database.
 59  */
 60-void insert(Data*, char*);
 61+void insert(Data*, char*, int);
 62 
 63 /*
 64  * Select all words.
 65diff --git a/main.c b/main.c
 66index 720871ca2071734484ce7c6feb3b9ae706e2c4a1..dae1f2aa50de122aa0d00c8cfec74b3f939a5bfc 100644
 67--- a/main.c
 68+++ b/main.c
 69@@ -1,20 +1,101 @@
 70+#include <locale.h>
 71 #include <stdio.h>
 72 #include <sqlite3.h>
 73-
 74+#include <ncurses.h>
 75 #include "data.h"
 76 
 77+#define BUF_SIZE 100
 78+
 79+unsigned int count_lines(FILE* file);
 80+int load_or_save_db(sqlite3 *pInMemory, const char *zFilename, int isSave);
 81+
 82 int main() {
 83     Data *data = new_data(":memory:");
 84 
 85     bootstrap(data);
 86-    for (int x = 0; x < 10000; x++)
 87-        insert(data, "LINE X");
 88 
 89-    LIST *list = select(data);
 90+    setlocale(LC_ALL, "");
 91+    initscr();
 92 
 93-    for (unsigned int x = 0; x < list->size; x++) 
 94-        printf("This is a line: %s\n", ((Word*)list->list[x])->Line);
 95+    int maxx=getmaxx(stdscr);
 96 
 97-    list_free(list);
 98+    FILE *f = fopen("dict.txt", "r");
 99+    unsigned int lines = count_lines(f);
100+    fseek(f, 0, SEEK_SET);
101+
102+    char * line = NULL;
103+    size_t len = 0;
104+    ssize_t read;
105+    int count = 0;
106+    while ((read = getline(&line, &len, f)) != -1) {
107+        if (line[0] == '#' || line[0] == '\n')
108+            continue;
109+
110+        insert(data, line, read-1);
111+        count ++;
112+        move(0,0);
113+        float total = ((float)count/(float)lines);
114+        printw("%03.0f%% ", total*100);
115+        for (int x = 0; x < ((maxx-4)*total); x++) {
116+            printw("█");
117+        }
118+        move(1,0);
119+        printw("%d/%d",count,lines);
120+        refresh();
121+    }
122+
123+    move(2,0);
124+    printw("Saving db...");
125+    refresh();
126+    load_or_save_db(data->db, "backup.db", 1);
127+
128+    clear();
129+    refresh();
130     return 0;
131 }
132+
133+int load_or_save_db(sqlite3 *pInMemory, const char *zFilename, int isSave){
134+  int rc;                   /* Function return code */
135+  sqlite3 *pFile;           /* Database connection opened on zFilename */
136+  sqlite3_backup *pBackup;  /* Backup object used to copy data */
137+  sqlite3 *pTo;             /* Database to copy to (pFile or pInMemory) */
138+  sqlite3 *pFrom;           /* Database to copy from (pFile or pInMemory) */
139+
140+  rc = sqlite3_open(zFilename, &pFile);
141+  if( rc==SQLITE_OK ){
142+    pFrom = (isSave ? pInMemory : pFile);
143+    pTo   = (isSave ? pFile     : pInMemory);
144+
145+    pBackup = sqlite3_backup_init(pTo, "main", pFrom, "main");
146+    if( pBackup ){
147+      (void)sqlite3_backup_step(pBackup, -1);
148+      (void)sqlite3_backup_finish(pBackup);
149+    }
150+    rc = sqlite3_errcode(pTo);
151+  }
152+
153+  (void)sqlite3_close(pFile);
154+  return rc;
155+}
156+
157+unsigned int count_lines(FILE* file)
158+{
159+    char buf[BUF_SIZE];
160+    unsigned int counter = 0;
161+    for(;;)
162+    {
163+        size_t res = fread(buf, 1, BUF_SIZE, file);
164+        if (ferror(file))
165+            return -1;
166+
167+        size_t i;
168+        for(i = 0; i < res; i++)
169+            if (buf[i] == '\n')
170+                counter++;
171+
172+        if (feof(file))
173+            break;
174+    }
175+
176+    return counter;
177+}